nv50: fix build-predicate function
[mesa.git] / src / glsl / pp / sl_pp_process.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 <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "sl_pp_context.h"
32 #include "sl_pp_macro.h"
33 #include "sl_pp_process.h"
34 #include "sl_pp_public.h"
35 #include "sl_pp_token.h"
36
37
38 int
39 sl_pp_process_out(struct sl_pp_process_state *state,
40 const struct sl_pp_token_info *token)
41 {
42 if (state->out_len >= state->out_max) {
43 unsigned int new_max = state->out_max;
44
45 if (new_max < 0x100) {
46 new_max = 0x100;
47 } else if (new_max < 0x10000) {
48 new_max *= 2;
49 } else {
50 new_max += 0x10000;
51 }
52
53 state->out = realloc(state->out, new_max * sizeof(struct sl_pp_token_info));
54 if (!state->out) {
55 return -1;
56 }
57 state->out_max = new_max;
58 }
59
60 state->out[state->out_len++] = *token;
61 return 0;
62 }
63
64 int
65 sl_pp_process_get(struct sl_pp_context *context,
66 struct sl_pp_token_info *output)
67 {
68 if (!context->process_state.out) {
69 if (context->line > 1) {
70 struct sl_pp_token_info ti;
71
72 ti.token = SL_PP_LINE;
73 ti.data.line.lineno = context->line - 1;
74 ti.data.line.fileno = context->file;
75 if (sl_pp_process_out(&context->process_state, &ti)) {
76 strcpy(context->error_msg, "out of memory");
77 return -1;
78 }
79
80 ti.token = SL_PP_NEWLINE;
81 if (sl_pp_process_out(&context->process_state, &ti)) {
82 strcpy(context->error_msg, "out of memory");
83 return -1;
84 }
85 }
86 }
87
88 for (;;) {
89 struct sl_pp_token_info input;
90 int found_eof = 0;
91
92 if (context->process_state.out_len) {
93 assert(context->process_state.out);
94 *output = context->process_state.out[0];
95
96 if (context->process_state.out_len > 1) {
97 unsigned int i;
98
99 for (i = 1; i < context->process_state.out_len; i++) {
100 context->process_state.out[i - 1] = context->process_state.out[i];
101 }
102 }
103 context->process_state.out_len--;
104
105 return 0;
106 }
107
108 if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
109 return -1;
110 }
111 if (input.token == SL_PP_HASH) {
112 if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
113 return -1;
114 }
115 switch (input.token) {
116 case SL_PP_IDENTIFIER:
117 {
118 int name;
119 int found_eol = 0;
120 struct sl_pp_token_info endof;
121 struct sl_pp_token_peek peek;
122 int result = 0;
123
124 /* Directive name. */
125 name = input.data.identifier;
126
127 if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
128 return -1;
129 }
130 sl_pp_token_buffer_unget(&context->tokens, &input);
131
132 if (sl_pp_token_peek_init(&peek, &context->tokens)) {
133 return -1;
134 }
135
136 while (!found_eol) {
137 if (sl_pp_token_peek_get(&peek, &input)) {
138 sl_pp_token_peek_destroy(&peek);
139 return -1;
140 }
141 switch (input.token) {
142 case SL_PP_NEWLINE:
143 /* Preserve newline just for the sake of line numbering. */
144 endof = input;
145 found_eol = 1;
146 break;
147
148 case SL_PP_EOF:
149 endof = input;
150 found_eof = 1;
151 found_eol = 1;
152 break;
153
154 default:
155 break;
156 }
157 }
158
159 if (name == context->dict._if) {
160 struct sl_pp_token_buffer buffer;
161
162 result = sl_pp_token_peek_to_buffer(&peek, &buffer);
163 if (result == 0) {
164 result = sl_pp_process_if(context, &buffer);
165 sl_pp_token_buffer_destroy(&buffer);
166 }
167 } else if (name == context->dict.ifdef) {
168 result = sl_pp_process_ifdef(context, peek.tokens, 0, peek.size - 1);
169 } else if (name == context->dict.ifndef) {
170 result = sl_pp_process_ifndef(context, peek.tokens, 0, peek.size - 1);
171 } else if (name == context->dict.elif) {
172 struct sl_pp_token_buffer buffer;
173
174 result = sl_pp_token_peek_to_buffer(&peek, &buffer);
175 if (result == 0) {
176 result = sl_pp_process_elif(context, &buffer);
177 sl_pp_token_buffer_destroy(&buffer);
178 }
179 } else if (name == context->dict._else) {
180 result = sl_pp_process_else(context, peek.tokens, 0, peek.size - 1);
181 } else if (name == context->dict.endif) {
182 result = sl_pp_process_endif(context, peek.tokens, 0, peek.size - 1);
183 } else if (context->if_value) {
184 if (name == context->dict.define) {
185 result = sl_pp_process_define(context, peek.tokens, 0, peek.size - 1);
186 } else if (name == context->dict.error) {
187 sl_pp_process_error(context, peek.tokens, 0, peek.size - 1);
188 result = -1;
189 } else if (name == context->dict.extension) {
190 result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &context->process_state);
191 } else if (name == context->dict.line) {
192 struct sl_pp_token_buffer buffer;
193
194 result = sl_pp_token_peek_to_buffer(&peek, &buffer);
195 if (result == 0) {
196 result = sl_pp_process_line(context, &buffer, &context->process_state);
197 sl_pp_token_buffer_destroy(&buffer);
198 }
199 } else if (name == context->dict.pragma) {
200 result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &context->process_state);
201 } else if (name == context->dict.undef) {
202 result = sl_pp_process_undef(context, peek.tokens, 0, peek.size - 1);
203 } else {
204 strcpy(context->error_msg, "unrecognised directive name");
205 result = -1;
206 }
207 }
208
209 sl_pp_token_peek_commit(&peek);
210 sl_pp_token_peek_destroy(&peek);
211
212 if (result) {
213 return result;
214 }
215
216 if (sl_pp_process_out(&context->process_state, &endof)) {
217 strcpy(context->error_msg, "out of memory");
218 return -1;
219 }
220 context->line++;
221 }
222 break;
223
224 case SL_PP_NEWLINE:
225 /* Empty directive. */
226 if (sl_pp_process_out(&context->process_state, &input)) {
227 strcpy(context->error_msg, "out of memory");
228 return -1;
229 }
230 context->line++;
231 break;
232
233 case SL_PP_EOF:
234 /* Empty directive. */
235 if (sl_pp_process_out(&context->process_state, &input)) {
236 strcpy(context->error_msg, "out of memory");
237 return -1;
238 }
239 found_eof = 1;
240 break;
241
242 default:
243 strcpy(context->error_msg, "expected a directive name");
244 return -1;
245 }
246 } else {
247 int found_eol = 0;
248
249 sl_pp_token_buffer_unget(&context->tokens, &input);
250
251 while (!found_eol) {
252 if (sl_pp_token_buffer_get(&context->tokens, &input)) {
253 return -1;
254 }
255
256 switch (input.token) {
257 case SL_PP_WHITESPACE:
258 /* Drop whitespace all together at this point. */
259 break;
260
261 case SL_PP_NEWLINE:
262 /* Preserve newline just for the sake of line numbering. */
263 if (sl_pp_process_out(&context->process_state, &input)) {
264 strcpy(context->error_msg, "out of memory");
265 return -1;
266 }
267 context->line++;
268 found_eol = 1;
269 break;
270
271 case SL_PP_EOF:
272 if (sl_pp_process_out(&context->process_state, &input)) {
273 strcpy(context->error_msg, "out of memory");
274 return -1;
275 }
276 found_eof = 1;
277 found_eol = 1;
278 break;
279
280 case SL_PP_IDENTIFIER:
281 sl_pp_token_buffer_unget(&context->tokens, &input);
282 if (sl_pp_macro_expand(context, &context->tokens, NULL, &context->process_state,
283 context->if_value ? sl_pp_macro_expand_normal : sl_pp_macro_expand_mute)) {
284 return -1;
285 }
286 break;
287
288 default:
289 if (context->if_value) {
290 if (sl_pp_process_out(&context->process_state, &input)) {
291 strcpy(context->error_msg, "out of memory");
292 return -1;
293 }
294 }
295 }
296 }
297 }
298
299 if (found_eof) {
300 if (context->if_ptr != SL_PP_MAX_IF_NESTING) {
301 strcpy(context->error_msg, "expected `#endif' directive");
302 return -1;
303 }
304 }
305 }
306 }
307
308 int
309 sl_pp_process(struct sl_pp_context *context,
310 struct sl_pp_token_info **output)
311 {
312 struct sl_pp_process_state state;
313
314 memset(&state, 0, sizeof(state));
315 for (;;) {
316 struct sl_pp_token_info input;
317
318 if (sl_pp_process_get(context, &input)) {
319 free(state.out);
320 return -1;
321 }
322 if (sl_pp_process_out(&state, &input)) {
323 free(state.out);
324 return -1;
325 }
326 if (input.token == SL_PP_EOF) {
327 *output = state.out;
328 return 0;
329 }
330 }
331 }