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