glsl2: Fix for dead strings being stored in the symbol table.
[mesa.git] / src / glsl / pp / sl_pp_define.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include "sl_pp_context.h"
31 #include "sl_pp_process.h"
32 #include "sl_pp_public.h"
33
34
35 static void
36 skip_whitespace(const struct sl_pp_token_info *input,
37 unsigned int *first,
38 unsigned int last)
39 {
40 while (*first < last && input[*first].token == SL_PP_WHITESPACE) {
41 (*first)++;
42 }
43 }
44
45
46 static int
47 _parse_formal_args(struct sl_pp_context *context,
48 const struct sl_pp_token_info *input,
49 unsigned int *first,
50 unsigned int last,
51 struct sl_pp_macro *macro)
52 {
53 struct sl_pp_macro_formal_arg **arg;
54
55 macro->num_args = 0;
56
57 skip_whitespace(input, first, last);
58 if (*first < last) {
59 if (input[*first].token == SL_PP_RPAREN) {
60 (*first)++;
61 return 0;
62 }
63 } else {
64 strcpy(context->error_msg, "expected either macro formal argument or `)'");
65 return -1;
66 }
67
68 arg = &macro->arg;
69
70 for (;;) {
71 if (*first < last && input[*first].token != SL_PP_IDENTIFIER) {
72 strcpy(context->error_msg, "expected macro formal argument");
73 return -1;
74 }
75
76 *arg = malloc(sizeof(struct sl_pp_macro_formal_arg));
77 if (!*arg) {
78 strcpy(context->error_msg, "out of memory");
79 return -1;
80 }
81
82 (**arg).name = input[*first].data.identifier;
83 (*first)++;
84
85 (**arg).next = NULL;
86 arg = &(**arg).next;
87
88 macro->num_args++;
89
90 skip_whitespace(input, first, last);
91 if (*first < last) {
92 if (input[*first].token == SL_PP_COMMA) {
93 (*first)++;
94 skip_whitespace(input, first, last);
95 } else if (input[*first].token == SL_PP_RPAREN) {
96 (*first)++;
97 return 0;
98 } else {
99 strcpy(context->error_msg, "expected either `,' or `)'");
100 return -1;
101 }
102 } else {
103 strcpy(context->error_msg, "expected either `,' or `)'");
104 return -1;
105 }
106 }
107
108 /* Should not gete here. */
109 }
110
111
112 int
113 sl_pp_process_define(struct sl_pp_context *context,
114 const struct sl_pp_token_info *input,
115 unsigned int first,
116 unsigned int last)
117 {
118 int macro_name = -1;
119 struct sl_pp_macro *macro;
120 unsigned int i;
121 unsigned int body_len;
122 unsigned int j;
123
124 if (first < last && input[first].token == SL_PP_IDENTIFIER) {
125 macro_name = input[first].data.identifier;
126 first++;
127 }
128 if (macro_name == -1) {
129 strcpy(context->error_msg, "expected macro name");
130 return -1;
131 }
132
133 /* Check for reserved macro names */
134 {
135 const char *name = sl_pp_context_cstr(context, macro_name);
136
137 if (strstr(name, "__")) {
138 strcpy(context->error_msg, "macro names containing `__' are reserved");
139 return 1;
140 }
141 if (name[0] == 'G' && name[1] == 'L' && name[2] == '_') {
142 strcpy(context->error_msg, "macro names prefixed with `GL_' are reserved");
143 return 1;
144 }
145 }
146
147 for (macro = context->macro; macro; macro = macro->next) {
148 if (macro->name == macro_name) {
149 break;
150 }
151 }
152
153 if (!macro) {
154 macro = sl_pp_macro_new();
155 if (!macro) {
156 strcpy(context->error_msg, "out of memory");
157 return -1;
158 }
159
160 *context->macro_tail = macro;
161 context->macro_tail = &macro->next;
162 } else {
163 sl_pp_macro_reset(macro);
164 }
165
166 macro->name = macro_name;
167
168 /*
169 * If there is no whitespace between macro name and left paren, a macro
170 * formal argument list follows. This is the only place where the presence
171 * of a whitespace matters and it's the only reason why we are dealing
172 * with whitespace at this level.
173 */
174 if (first < last && input[first].token == SL_PP_LPAREN) {
175 first++;
176 if (_parse_formal_args(context, input, &first, last, macro)) {
177 return -1;
178 }
179 }
180
181 /* Calculate body size, trim out whitespace, make room for EOF. */
182 body_len = 1;
183 for (i = first; i < last; i++) {
184 if (input[i].token != SL_PP_WHITESPACE) {
185 body_len++;
186 }
187 }
188
189 macro->body = malloc(sizeof(struct sl_pp_token_info) * body_len);
190 if (!macro->body) {
191 strcpy(context->error_msg, "out of memory");
192 return -1;
193 }
194
195 for (j = 0, i = first; i < last; i++) {
196 if (input[i].token != SL_PP_WHITESPACE) {
197 macro->body[j++] = input[i];
198 }
199 }
200 macro->body[j++].token = SL_PP_EOF;
201
202 return 0;
203 }
204
205
206 int
207 sl_pp_process_undef(struct sl_pp_context *context,
208 const struct sl_pp_token_info *input,
209 unsigned int first,
210 unsigned int last)
211 {
212 int macro_name = -1;
213 struct sl_pp_macro **pmacro;
214 struct sl_pp_macro *macro;
215
216 if (first < last && input[first].token == SL_PP_IDENTIFIER) {
217 macro_name = input[first].data.identifier;
218 }
219 if (macro_name == -1) {
220 return 0;
221 }
222
223 for (pmacro = &context->macro; *pmacro; pmacro = &(**pmacro).next) {
224 if ((**pmacro).name == macro_name) {
225 break;
226 }
227 }
228 if (!*pmacro) {
229 return 0;
230 }
231
232 macro = *pmacro;
233 *pmacro = macro->next;
234 macro->next = NULL;
235 sl_pp_macro_free(macro);
236
237 return 0;
238 }