1 %{
2 //////////////////////////////////////////////////////////////////////
3 //
4 // Pixie
5 //
6 // Copyright � 1999 - 2003, Okan Arikan
7 //
8 // Contact: okan@cs.utexas.edu
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 ///////////////////////////////////////////////////////////////////////
25 ///////////////////////////////////////////////////////////////////////
26 //
27 // File : ifexpr.y
28 // Classes : -
29 // Description : Parser for the IF expressions
30 //
31 ////////////////////////////////////////////////////////////////////////
32 #undef alloca
33 #include <string.h>
34
35 #include "common/os.h"
36 #include "ri_config.h"
37 #include "error.h"
38 #include "rendererc.h"
39 #include "renderer.h"
40 #include "rendererContext.h"
41
42 int iflex(void ); // Forward definition for stupid yacc
43 void iferror(const char *,...);
44
45 static CRendererContext *context = NULL;
46 static int silent = FALSE;
47 static int result = 0; // 0 - FALSE
48 // 1 - TRUE
49 // 2 - error
50
51
52
53 ///////////////////////////////////////////////////////////////////////
54 // Class : CExpr
55 // Description : Holds an expression value
56 // Comments :
57 class CExpr {
58 public:
59 EVariableType type; // The type of the expression
60 const void *value; // Value of the expression
61 float floatValue;
62 int intValue;
63 char *stringValue;
64 };
65
66 ///////////////////////////////////////////////////////////////////////
67 // Function : getString
68 // Description : Take the expression and form a string
69 // Return Value : The string
70 // Comments :
getString(const CExpr & expr)71 static inline const char *getString(const CExpr &expr) {
72 const void *value = expr.value;
73
74 switch (expr.type) {
75 case TYPE_FLOAT:
76 case TYPE_COLOR:
77 case TYPE_VECTOR:
78 case TYPE_NORMAL:
79 case TYPE_POINT:
80 case TYPE_MATRIX:
81 case TYPE_QUAD:
82 case TYPE_DOUBLE:
83 break;
84 case TYPE_STRING:
85 if (value == NULL) return expr.stringValue;
86 else return *((const char **) value);
87 case TYPE_INTEGER:
88 default:
89 break;
90 };
91
92 error(CODE_SYNTAX,"Unable to cast a string in the expression\n");
93
94 return "__nonsense__";
95 }
96
97
98 ///////////////////////////////////////////////////////////////////////
99 // Function : getFloat
100 // Description : Take the expression and form a float
101 // Return Value : The float
102 // Comments :
getFloat(const CExpr & expr)103 static inline float getFloat(const CExpr &expr) {
104 const void *value = expr.value;
105
106 switch (expr.type) {
107 case TYPE_FLOAT:
108 if (value == NULL) return expr.floatValue;
109 else return *((float *) value);
110 case TYPE_COLOR:
111 case TYPE_VECTOR:
112 case TYPE_NORMAL:
113 case TYPE_POINT:
114 case TYPE_MATRIX:
115 case TYPE_QUAD:
116 case TYPE_DOUBLE:
117 case TYPE_STRING:
118 break;
119 case TYPE_INTEGER:
120 if (value == NULL) return (float) expr.intValue;
121 else return (float) *((int *) value);
122 default:
123 break;
124 };
125
126 error(CODE_SYNTAX,"Unable to cast a float in the expression\n");
127
128 return 0;
129 }
130
131 ///////////////////////////////////////////////////////////////////////
132 // Function : getInt
133 // Description : Take the expression and form an int
134 // Return Value : The int
135 // Comments :
getInt(const CExpr & expr)136 static inline int getInt(const CExpr &expr) {
137 const void *value = expr.value;
138
139 switch (expr.type) {
140 case TYPE_FLOAT:
141 if (value == NULL) return (int) expr.floatValue;
142 else return (int) *((float *) value);
143 case TYPE_COLOR:
144 case TYPE_VECTOR:
145 case TYPE_NORMAL:
146 case TYPE_POINT:
147 case TYPE_MATRIX:
148 case TYPE_QUAD:
149 case TYPE_DOUBLE:
150 case TYPE_STRING:
151 break;
152 case TYPE_INTEGER:
153 if (value == NULL) return expr.intValue;
154 else return *((int *) value);
155 default:
156 break;
157 };
158
159 error(CODE_SYNTAX,"Unable to cast an integer in the expression\n");
160
161 return 0;
162 }
163
164 ///////////////////////////////////////////////////////////////////////
165 // Function : setFloat
166 // Description : Create a float expression
167 // Return Value :
168 // Comments :
setFloat(CExpr & expr,float val)169 static inline void setFloat(CExpr &expr,float val) {
170 expr.type = TYPE_FLOAT;
171 expr.value = NULL;
172 expr.floatValue = val;
173 }
174
175 ///////////////////////////////////////////////////////////////////////
176 // Function : setInt
177 // Description : Create an int expression
178 // Return Value :
179 // Comments :
setInt(CExpr & expr,int val)180 static inline void setInt(CExpr &expr,int val) {
181 expr.type = TYPE_INTEGER;
182 expr.value = NULL;
183 expr.intValue = val;
184 }
185
186 ///////////////////////////////////////////////////////////////////////
187 // Function : findExpr
188 // Description : Find a float expression
189 // Return Value :
190 // Comments :
191 static void findExpr(CExpr &expr,const char *name,const char *decl=NULL,int attributes=FALSE,int typeSet=FALSE) {
192 const char *p;
193
194 if (strncmp(name,"Attribute:",10) == 0) {
195 name += 10;
196
197 findExpr(expr,name,NULL,TRUE,TRUE);
198 } else if (strncmp(name,"Option:",7) == 0) {
199 name += 7;
200
201 findExpr(expr,name,NULL,FALSE,TRUE);
202 } else if ((p = strchr(name,':')) != NULL) {
203 char category[256];
204
205 assert((p-name) < 255); // Sanity check
206 strncpy(category,name,p-name); // Copy the category
207 category[p-name] = '\0'; // Make sure it terminates
208
209 findExpr(expr,p+1,category,attributes,typeSet);
210 } else {
211
212 if (attributes) {
213 // Lookup the attributes
214 CAttributes *cAttributes = context->getAttributes(TRUE);
215
216 if (cAttributes->find(name,decl,expr.type,expr.value,expr.intValue,expr.floatValue) == FALSE) {
217 if (typeSet == FALSE) {
218 COptions *cOptions = context->getOptions();
219 if (cOptions->find(name,decl,expr.type,expr.value,expr.intValue,expr.floatValue) == FALSE) {
220 if (!silent) error(CODE_BADTOKEN,"Failed to find variable \"%s\"\n",name);
221 result = FALSE;
222 }
223 } else {
224 if (!silent) error(CODE_BADTOKEN,"Failed to find variable \"%s\"\n",name);
225 result = FALSE;
226 }
227 }
228 } else {
229 // Lookup the options
230 COptions *cOptions = context->getOptions();
231
232 if (cOptions->find(name,decl,expr.type,expr.value,expr.intValue,expr.floatValue) == FALSE) {
233 if (typeSet == FALSE) {
234 CAttributes *cAttributes = context->getAttributes(TRUE);
235 if (cAttributes->find(name,decl,expr.type,expr.value,expr.intValue,expr.floatValue) == FALSE) {
236 if (!silent) error(CODE_BADTOKEN,"Failed to find variable \"%s\"\n",name);
237 result = FALSE;
238 }
239 } else {
240 if (!silent) error(CODE_BADTOKEN,"Failed to find variable \"%s\"\n",name);
241 result = FALSE;
242 }
243 }
244 }
245 }
246 }
247
248
249 %}
250 %union slval {
251 char *string;
252 CExpr expr;
253 float real;
254 }
255
256 %token IF_OPEN
257 %token IF_CLOSE
258 %token IF_PLUS
259 %token IF_MINUS
260 %token IF_MUL
261 %token IF_DIV
262 %token IF_MULMUL
263 %token IF_AND
264 %token IF_POW
265 %token IF_OR
266 %token IF_EQUAL
267 %token IF_NEQUAL
268 %token IF_LESSE
269 %token IF_GREATERE
270 %token IF_LESS
271 %token IF_GREATER
272 %token IF_ANDAND
273 %token IF_OROR
274 %token IF_NOT
275 %token IF_DOLLAR
276 %token IF_MATCH
277 %token IF_DEFINED
278 %token IF_CONCAT
279 %token IF_COMMA
280 %token<string> IF_TEXT_VALUE
281 %token<string> IF_IDENTIFIER_VALUE
282 %token<real> IF_FLOAT_VALUE
283 %type<expr> ifExpr
284
285 %left IF_EQUAL
286 %left IF_NEQUAL
287 %left IF_GREATERE
288 %left IF_LESSE
289 %left IF_GREATER
290 %left IF_LESS
291 %left IF_PLUS
292 %left IF_MINUS
293 %left IF_DIV
294 %left IF_MUL
295 %left IF_OR
296 %left IF_AND
297 %left IF_OROR
298 %left IF_ANDAND
299 %left IF_POW
300 %left IF_NOT
301 %left IF_MATCH
302 %left IF_DOLLAR
303 %%
304 start: ifExpr
305 {
306 // If no result set so far
307 if (result == 2) {
308
309 ////////////////////////////////////////////////////////////////////
310 // Compute the value of the expression
311 if ($1.type == TYPE_STRING) result = TRUE;
312 else result = (getFloat($1) != 0);
313 }
314 };
315
316 ifExpr: //////////////////////////////////////////////////////////////////////////
317 // The terminals
318 IF_DOLLAR
319 IF_IDENTIFIER_VALUE
320 {
321 // Find the variable here
322 findExpr($$,$2);
323 }
324 |
325 IF_DOLLAR
326 IF_OPEN
327 ifExpr
328 IF_CLOSE
329 {
330 // Find the variable here
331 findExpr($$,getString($3));
332 }
333 |
334 IF_FLOAT_VALUE
335 {
336 setFloat($$,$1);
337 }
338 |
339 IF_TEXT_VALUE
340 {
341 $$.type = TYPE_STRING;
342 $$.value = NULL;
343 $$.stringValue = $1;
344 }
345 |
346 //////////////////////////////////////////////////////////////////////////
347 // The arithmetic operations
348 ifExpr
349 IF_PLUS
350 ifExpr
351 {
352 setFloat($$,getFloat($1) + getFloat($3));
353 }
354 |
355 ifExpr
356 IF_MINUS
357 ifExpr
358 {
359 setFloat($$,getFloat($1) - getFloat($3));
360 }
361 |
362 ifExpr
363 IF_MUL
364 ifExpr
365 {
366 setFloat($$,getFloat($1) * getFloat($3));
367 }
368 |
369 ifExpr
370 IF_DIV
371 ifExpr
372 {
373 setFloat($$,getFloat($1) / getFloat($3));
374 }
375 |
376 //////////////////////////////////////////////////////////////////////////
377 // The bitwise operations (run on integers)
378 ifExpr
379 IF_AND
380 ifExpr
381 {
382 setInt($$,getInt($1) & getInt($3));
383 }
384 |
385 ifExpr
386 IF_OR
387 ifExpr
388 {
389 setInt($$,getInt($1) | getInt($3));
390 }
391 |
392 ifExpr
393 IF_POW
394 ifExpr
395 {
396 setInt($$,getInt($1) ^ getInt($3));
397 }
398 |
399 //////////////////////////////////////////////////////////////////////////
400 // Relational operations
401 ifExpr
402 IF_EQUAL
403 ifExpr
404 {
405 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
406 setInt($$,strcmp(getString($1),getString($3)) == 0);
407 } else {
408 setInt($$,getFloat($1) == getFloat($3));
409 }
410 }
411 |
412 ifExpr
413 IF_NEQUAL
414 ifExpr
415 {
416 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
417 setInt($$,strcmp(getString($1),getString($3)) != 0);
418 } else {
419 setInt($$,getFloat($1) != getFloat($3));
420 }
421 }
422 |
423 ifExpr
424 IF_GREATER
425 ifExpr
426 {
427 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
428 setInt($$,strcmp(getString($1),getString($3)) > 0);
429 } else {
430 setInt($$,getFloat($1) > getFloat($3));
431 }
432 }
433 |
434 ifExpr
435 IF_LESS
436 ifExpr
437 {
438 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
439 setInt($$,strcmp(getString($1),getString($3)) < 0);
440 } else {
441 setInt($$,getFloat($1) < getFloat($3));
442 }
443 }
444 |
445 ifExpr
446 IF_GREATERE
447 ifExpr
448 {
449 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
450 setInt($$,strcmp(getString($1),getString($3)) >= 0);
451 } else {
452 setInt($$,getFloat($1) >= getFloat($3));
453 }
454 }
455 |
456 ifExpr
457 IF_LESSE
458 ifExpr
459 {
460 if ($1.type == TYPE_STRING || $3.type == TYPE_STRING) {
461 setInt($$,strcmp(getString($1),getString($3)) <= 0);
462 } else {
463 setInt($$,getFloat($1) <= getFloat($3));
464 }
465 }
466 |
467 //////////////////////////////////////////////////////////////////////////
468 // String matching
469 ifExpr
470 IF_MATCH
471 ifExpr
472 {
473 // FIXME: Implement pattern matching
474 setInt($$,strcmp(getString($1),getString($3)) == 0);
475 }
476 |
477 //////////////////////////////////////////////////////////////////////////
478 // Logical operations
479 ifExpr
480 IF_ANDAND
481 ifExpr
482 {
483 setInt($$,getInt($1) && getInt($3));
484 }
485 |
486 ifExpr
487 IF_OROR
488 ifExpr
489 {
490 setInt($$,getInt($1) || getInt($3));
491 }
492 |
493 IF_NOT
494 ifExpr
495 {
496 setInt($$,! getInt($2));
497 }
498 |
499 //////////////////////////////////////////////////////////////////////////
500 // Grouping
501 IF_OPEN
502 ifExpr
503 IF_CLOSE
504 {
505 $$ = $2;
506 }
507 |
508 //////////////////////////////////////////////////////////////////////////
509 // Defined
510 IF_DEFINED
511 IF_OPEN
512 ifExpr
513 IF_CLOSE
514 {
515 CExpr e;
516 // save previous result & silent status
517 int prevResult = result;
518 int prevSilent = silent;
519 silent = TRUE;
520 result = TRUE;
521 // lookup (result will be false if it fails)
522 findExpr(e,getString($3));
523 setInt($$,result == TRUE);
524 // restore state
525 result = prevResult;
526 silent = prevSilent;
527 }
528 |
529 IF_DEFINED
530 IF_OPEN
531 IF_IDENTIFIER_VALUE
532 IF_CLOSE
533 {
534 CExpr e;
535 // save previous result & silent status
536 int prevResult = result;
537 int prevSilent = silent;
538 silent = TRUE;
539 result = TRUE;
540 // lookup (result will be false if it fails)
541 findExpr(e,$3);
542 setInt($$,result == TRUE);
543 // restore state
544 result = prevResult;
545 silent = prevSilent;
546 }
547 |
548 //////////////////////////////////////////////////////////////////////////
549 // Concat
550 IF_CONCAT
551 IF_OPEN
552 ifExpr
553 IF_COMMA
554 ifExpr
555 IF_CLOSE
556 {
557 $$.type = TYPE_STRING;
558 $$.value = NULL;
559 $$.stringValue = (char *) ralloc((int) strlen(getString($3)) + (int) strlen(getString($5)) + 2,CRenderer::globalMemory);
560 strcpy($$.stringValue,getString($3));
561 strcat($$.stringValue,getString($5));
562 }
563 ;
564
565 %%
566
567 #include "lex.if.cpp"
568
569
570 ///////////////////////////////////////////////////////////////////////
571 // Function : ifParse
572 // Description : Parse an if statement
573 // Return Value : TRUE/FALSE
574 // Comments :
575 int CRendererContext::ifParse(const char *expr) {
576
577 // Begin a new page
578 memBegin(CRenderer::globalMemory);
579
580 YY_BUFFER_STATE savedState = YY_CURRENT_BUFFER; // Save the old buffer
581 YY_BUFFER_STATE newState;
582
583 // Save the necessary info
584 context = this;
585 result = 2;
586 silent = FALSE;
587
588 newState = if_scan_string(expr); // Create a new buffer
589 ifparse(); // Scan the buffer
590 if_delete_buffer(newState); // Ditch the buffer
591
592 if_switch_to_buffer( savedState ); // Switch to the old buffer
593
594 // Restore the memory page
595 memEnd(CRenderer::globalMemory);
596
597 return result;
598 }
599
600 ///////////////////////////////////////////////////////////////////////
601 // Function : dsoerror
602 // Description : Count the parse errors
603 // Return Value :
604 // Comments :
iferror(const char *,...)605 void iferror(const char *,...) {
606 // What do we do in the case of an error ?
607 warning(CODE_BADTOKEN,"Condition parse error\n");
608 }
609
610
611
612
613
614
615