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