Merge branch 'mesa_7_7_branch'
[mesa.git] / src / glsl / pp / sl_pp_expression.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_expression.h"
31 #include "sl_pp_public.h"
32
33
34 struct parse_context {
35 struct sl_pp_context *context;
36 const struct sl_pp_token_info *input;
37 };
38
39 static int
40 _parse_or(struct parse_context *ctx,
41 int *result);
42
43 static int
44 _parse_primary(struct parse_context *ctx,
45 int *result)
46 {
47 if (ctx->input->token == SL_PP_UINT) {
48 *result = atoi(sl_pp_context_cstr(ctx->context, ctx->input->data._uint));
49 ctx->input++;
50 } else {
51 if (ctx->input->token != SL_PP_LPAREN) {
52 strcpy(ctx->context->error_msg, "expected `('");
53 return -1;
54 }
55 ctx->input++;
56 if (_parse_or(ctx, result)) {
57 return -1;
58 }
59 if (ctx->input->token != SL_PP_RPAREN) {
60 strcpy(ctx->context->error_msg, "expected `)'");
61 return -1;
62 }
63 ctx->input++;
64 }
65 return 0;
66 }
67
68 static int
69 _parse_unary(struct parse_context *ctx,
70 int *result)
71 {
72 if (!_parse_primary(ctx, result)) {
73 return 0;
74 }
75
76 switch (ctx->input->token) {
77 case SL_PP_PLUS:
78 ctx->input++;
79 if (_parse_unary(ctx, result)) {
80 return -1;
81 }
82 *result = +*result;
83 break;
84
85 case SL_PP_MINUS:
86 ctx->input++;
87 if (_parse_unary(ctx, result)) {
88 return -1;
89 }
90 *result = -*result;
91 break;
92
93 case SL_PP_NOT:
94 ctx->input++;
95 if (_parse_unary(ctx, result)) {
96 return -1;
97 }
98 *result = !*result;
99 break;
100
101 case SL_PP_BITNOT:
102 ctx->input++;
103 if (_parse_unary(ctx, result)) {
104 return -1;
105 }
106 *result = ~*result;
107 break;
108
109 default:
110 return -1;
111 }
112
113 return 0;
114 }
115
116 static int
117 _parse_multiplicative(struct parse_context *ctx,
118 int *result)
119 {
120 if (_parse_unary(ctx, result)) {
121 return -1;
122 }
123 for (;;) {
124 int right;
125
126 switch (ctx->input->token) {
127 case SL_PP_STAR:
128 ctx->input++;
129 if (_parse_unary(ctx, &right)) {
130 return -1;
131 }
132 *result = *result * right;
133 break;
134
135 case SL_PP_SLASH:
136 ctx->input++;
137 if (_parse_unary(ctx, &right)) {
138 return -1;
139 }
140 *result = *result / right;
141 break;
142
143 case SL_PP_MODULO:
144 ctx->input++;
145 if (_parse_unary(ctx, &right)) {
146 return -1;
147 }
148 *result = *result % right;
149 break;
150
151 default:
152 return 0;
153 }
154 }
155 }
156
157 static int
158 _parse_additive(struct parse_context *ctx,
159 int *result)
160 {
161 if (_parse_multiplicative(ctx, result)) {
162 return -1;
163 }
164 for (;;) {
165 int right;
166
167 switch (ctx->input->token) {
168 case SL_PP_PLUS:
169 ctx->input++;
170 if (_parse_multiplicative(ctx, &right)) {
171 return -1;
172 }
173 *result = *result + right;
174 break;
175
176 case SL_PP_MINUS:
177 ctx->input++;
178 if (_parse_multiplicative(ctx, &right)) {
179 return -1;
180 }
181 *result = *result - right;
182 break;
183
184 default:
185 return 0;
186 }
187 }
188 }
189
190 static int
191 _parse_shift(struct parse_context *ctx,
192 int *result)
193 {
194 if (_parse_additive(ctx, result)) {
195 return -1;
196 }
197 for (;;) {
198 int right;
199
200 switch (ctx->input->token) {
201 case SL_PP_LSHIFT:
202 ctx->input++;
203 if (_parse_additive(ctx, &right)) {
204 return -1;
205 }
206 *result = *result << right;
207 break;
208
209 case SL_PP_RSHIFT:
210 ctx->input++;
211 if (_parse_additive(ctx, &right)) {
212 return -1;
213 }
214 *result = *result >> right;
215 break;
216
217 default:
218 return 0;
219 }
220 }
221 }
222
223 static int
224 _parse_relational(struct parse_context *ctx,
225 int *result)
226 {
227 if (_parse_shift(ctx, result)) {
228 return -1;
229 }
230 for (;;) {
231 int right;
232
233 switch (ctx->input->token) {
234 case SL_PP_LESSEQUAL:
235 ctx->input++;
236 if (_parse_shift(ctx, &right)) {
237 return -1;
238 }
239 *result = *result <= right;
240 break;
241
242 case SL_PP_GREATEREQUAL:
243 ctx->input++;
244 if (_parse_shift(ctx, &right)) {
245 return -1;
246 }
247 *result = *result >= right;
248 break;
249
250 case SL_PP_LESS:
251 ctx->input++;
252 if (_parse_shift(ctx, &right)) {
253 return -1;
254 }
255 *result = *result < right;
256 break;
257
258 case SL_PP_GREATER:
259 ctx->input++;
260 if (_parse_shift(ctx, &right)) {
261 return -1;
262 }
263 *result = *result > right;
264 break;
265
266 default:
267 return 0;
268 }
269 }
270 }
271
272 static int
273 _parse_equality(struct parse_context *ctx,
274 int *result)
275 {
276 if (_parse_relational(ctx, result)) {
277 return -1;
278 }
279 for (;;) {
280 int right;
281
282 switch (ctx->input->token) {
283 case SL_PP_EQUAL:
284 ctx->input++;
285 if (_parse_relational(ctx, &right)) {
286 return -1;
287 }
288 *result = *result == right;
289 break;
290
291 case SL_PP_NOTEQUAL:
292 ctx->input++;
293 if (_parse_relational(ctx, &right)) {
294 return -1;
295 }
296 *result = *result != right;
297 break;
298
299 default:
300 return 0;
301 }
302 }
303 }
304
305 static int
306 _parse_bitand(struct parse_context *ctx,
307 int *result)
308 {
309 if (_parse_equality(ctx, result)) {
310 return -1;
311 }
312 while (ctx->input->token == SL_PP_BITAND) {
313 int right;
314
315 ctx->input++;
316 if (_parse_equality(ctx, &right)) {
317 return -1;
318 }
319 *result = *result & right;
320 }
321 return 0;
322 }
323
324 static int
325 _parse_xor(struct parse_context *ctx,
326 int *result)
327 {
328 if (_parse_bitand(ctx, result)) {
329 return -1;
330 }
331 while (ctx->input->token == SL_PP_XOR) {
332 int right;
333
334 ctx->input++;
335 if (_parse_bitand(ctx, &right)) {
336 return -1;
337 }
338 *result = *result ^ right;
339 }
340 return 0;
341 }
342
343 static int
344 _parse_bitor(struct parse_context *ctx,
345 int *result)
346 {
347 if (_parse_xor(ctx, result)) {
348 return -1;
349 }
350 while (ctx->input->token == SL_PP_BITOR) {
351 int right;
352
353 ctx->input++;
354 if (_parse_xor(ctx, &right)) {
355 return -1;
356 }
357 *result = *result | right;
358 }
359 return 0;
360 }
361
362 static int
363 _parse_and(struct parse_context *ctx,
364 int *result)
365 {
366 if (_parse_bitor(ctx, result)) {
367 return -1;
368 }
369 while (ctx->input->token == SL_PP_AND) {
370 int right;
371
372 ctx->input++;
373 if (_parse_bitor(ctx, &right)) {
374 return -1;
375 }
376 *result = *result && right;
377 }
378 return 0;
379 }
380
381 static int
382 _parse_or(struct parse_context *ctx,
383 int *result)
384 {
385 if (_parse_and(ctx, result)) {
386 return -1;
387 }
388 while (ctx->input->token == SL_PP_OR) {
389 int right;
390
391 ctx->input++;
392 if (_parse_and(ctx, &right)) {
393 return -1;
394 }
395 *result = *result || right;
396 }
397 return 0;
398 }
399
400 int
401 sl_pp_execute_expression(struct sl_pp_context *context,
402 const struct sl_pp_token_info *input,
403 int *result)
404 {
405 struct parse_context ctx;
406
407 ctx.context = context;
408 ctx.input = input;
409
410 return _parse_or(&ctx, result);
411 }