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