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