slang/pp: Use a dictionary for the remaining string literals.
[mesa.git] / src / glsl / pp / sl_pp_macro.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 <stdio.h>
30 #include "sl_pp_macro.h"
31 #include "sl_pp_process.h"
32
33
34 static void
35 _macro_init(struct sl_pp_macro *macro)
36 {
37 macro->name = -1;
38 macro->num_args = -1;
39 macro->arg = NULL;
40 macro->body = NULL;
41 }
42
43 struct sl_pp_macro *
44 sl_pp_macro_new(void)
45 {
46 struct sl_pp_macro *macro;
47
48 macro = calloc(1, sizeof(struct sl_pp_macro));
49 if (macro) {
50 _macro_init(macro);
51 }
52 return macro;
53 }
54
55 static void
56 _macro_destroy(struct sl_pp_macro *macro)
57 {
58 struct sl_pp_macro_formal_arg *arg = macro->arg;
59
60 while (arg) {
61 struct sl_pp_macro_formal_arg *next_arg = arg->next;
62
63 free(arg);
64 arg = next_arg;
65 }
66
67 free(macro->body);
68 }
69
70 void
71 sl_pp_macro_free(struct sl_pp_macro *macro)
72 {
73 while (macro) {
74 struct sl_pp_macro *next_macro = macro->next;
75
76 _macro_destroy(macro);
77 free(macro);
78 macro = next_macro;
79 }
80 }
81
82 void
83 sl_pp_macro_reset(struct sl_pp_macro *macro)
84 {
85 _macro_destroy(macro);
86 _macro_init(macro);
87 }
88
89 static void
90 skip_whitespace(const struct sl_pp_token_info *input,
91 unsigned int *pi)
92 {
93 while (input[*pi].token == SL_PP_WHITESPACE) {
94 (*pi)++;
95 }
96 }
97
98 static int
99 _out_number(struct sl_pp_context *context,
100 struct sl_pp_process_state *state,
101 unsigned int number)
102 {
103 char buf[32];
104 struct sl_pp_token_info ti;
105
106 sprintf(buf, "%u", number);
107
108 ti.token = SL_PP_NUMBER;
109 ti.data.number = sl_pp_context_add_unique_str(context, buf);
110 if (sl_pp_process_out(state, &ti)) {
111 strcpy(context->error_msg, "out of memory");
112 return -1;
113 }
114
115 return 0;
116 }
117
118 int
119 sl_pp_macro_expand(struct sl_pp_context *context,
120 const struct sl_pp_token_info *input,
121 unsigned int *pi,
122 struct sl_pp_macro *local,
123 struct sl_pp_process_state *state,
124 int mute)
125 {
126 int macro_name;
127 struct sl_pp_macro *macro = NULL;
128 struct sl_pp_macro *actual_arg = NULL;
129 unsigned int j;
130
131 if (input[*pi].token != SL_PP_IDENTIFIER) {
132 strcpy(context->error_msg, "expected an identifier");
133 return -1;
134 }
135
136 macro_name = input[*pi].data.identifier;
137
138 if (macro_name == context->dict.___LINE__) {
139 if (!mute && _out_number(context, state, context->line)) {
140 return -1;
141 }
142 (*pi)++;
143 return 0;
144 }
145 if (macro_name == context->dict.___FILE__) {
146 if (!mute && _out_number(context, state, context->file)) {
147 return -1;
148 }
149 (*pi)++;
150 return 0;
151 }
152 if (macro_name == context->dict.__VERSION__) {
153 if (!mute && _out_number(context, state, 110)) {
154 return -1;
155 }
156 (*pi)++;
157 return 0;
158 }
159
160 if (local) {
161 for (macro = local; macro; macro = macro->next) {
162 if (macro->name == macro_name) {
163 break;
164 }
165 }
166 }
167
168 if (!macro) {
169 for (macro = context->macro; macro; macro = macro->next) {
170 if (macro->name == macro_name) {
171 break;
172 }
173 }
174 }
175
176 if (!macro) {
177 if (!mute) {
178 if (sl_pp_process_out(state, &input[*pi])) {
179 strcpy(context->error_msg, "out of memory");
180 return -1;
181 }
182 }
183 (*pi)++;
184 return 0;
185 }
186
187 (*pi)++;
188
189 if (macro->num_args >= 0) {
190 skip_whitespace(input, pi);
191 if (input[*pi].token != SL_PP_LPAREN) {
192 strcpy(context->error_msg, "expected `('");
193 return -1;
194 }
195 (*pi)++;
196 skip_whitespace(input, pi);
197 }
198
199 if (macro->num_args > 0) {
200 struct sl_pp_macro_formal_arg *formal_arg = macro->arg;
201 struct sl_pp_macro **pmacro = &actual_arg;
202
203 for (j = 0; j < (unsigned int)macro->num_args; j++) {
204 unsigned int body_len;
205 unsigned int i;
206 int done = 0;
207 unsigned int paren_nesting = 0;
208 unsigned int k;
209
210 *pmacro = sl_pp_macro_new();
211 if (!*pmacro) {
212 strcpy(context->error_msg, "out of memory");
213 return -1;
214 }
215
216 (**pmacro).name = formal_arg->name;
217
218 body_len = 1;
219 for (i = *pi; !done; i++) {
220 switch (input[i].token) {
221 case SL_PP_WHITESPACE:
222 break;
223
224 case SL_PP_COMMA:
225 if (!paren_nesting) {
226 if (j < (unsigned int)macro->num_args - 1) {
227 done = 1;
228 } else {
229 strcpy(context->error_msg, "too many actual macro arguments");
230 return -1;
231 }
232 } else {
233 body_len++;
234 }
235 break;
236
237 case SL_PP_LPAREN:
238 paren_nesting++;
239 body_len++;
240 break;
241
242 case SL_PP_RPAREN:
243 if (!paren_nesting) {
244 if (j == (unsigned int)macro->num_args - 1) {
245 done = 1;
246 } else {
247 strcpy(context->error_msg, "too few actual macro arguments");
248 return -1;
249 }
250 } else {
251 paren_nesting--;
252 body_len++;
253 }
254 break;
255
256 case SL_PP_EOF:
257 strcpy(context->error_msg, "too few actual macro arguments");
258 return -1;
259
260 default:
261 body_len++;
262 }
263 }
264
265 (**pmacro).body = malloc(sizeof(struct sl_pp_token_info) * body_len);
266 if (!(**pmacro).body) {
267 strcpy(context->error_msg, "out of memory");
268 return -1;
269 }
270
271 for (done = 0, k = 0, i = *pi; !done; i++) {
272 switch (input[i].token) {
273 case SL_PP_WHITESPACE:
274 break;
275
276 case SL_PP_COMMA:
277 if (!paren_nesting && j < (unsigned int)macro->num_args - 1) {
278 done = 1;
279 } else {
280 (**pmacro).body[k++] = input[i];
281 }
282 break;
283
284 case SL_PP_LPAREN:
285 paren_nesting++;
286 (**pmacro).body[k++] = input[i];
287 break;
288
289 case SL_PP_RPAREN:
290 if (!paren_nesting && j == (unsigned int)macro->num_args - 1) {
291 done = 1;
292 } else {
293 paren_nesting--;
294 (**pmacro).body[k++] = input[i];
295 }
296 break;
297
298 default:
299 (**pmacro).body[k++] = input[i];
300 }
301 }
302
303 (**pmacro).body[k++].token = SL_PP_EOF;
304 (*pi) = i;
305
306 formal_arg = formal_arg->next;
307 pmacro = &(**pmacro).next;
308 }
309 }
310
311 /* Right paren for non-empty argument list has already been eaten. */
312 if (macro->num_args == 0) {
313 skip_whitespace(input, pi);
314 if (input[*pi].token != SL_PP_RPAREN) {
315 strcpy(context->error_msg, "expected `)'");
316 return -1;
317 }
318 (*pi)++;
319 }
320
321 for (j = 0;;) {
322 switch (macro->body[j].token) {
323 case SL_PP_NEWLINE:
324 if (sl_pp_process_out(state, &macro->body[j])) {
325 strcpy(context->error_msg, "out of memory");
326 return -1;
327 }
328 j++;
329 break;
330
331 case SL_PP_IDENTIFIER:
332 if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state, mute)) {
333 return -1;
334 }
335 break;
336
337 case SL_PP_EOF:
338 sl_pp_macro_free(actual_arg);
339 return 0;
340
341 default:
342 if (!mute) {
343 if (sl_pp_process_out(state, &macro->body[j])) {
344 strcpy(context->error_msg, "out of memory");
345 return -1;
346 }
347 }
348 j++;
349 }
350 }
351 }