(file) Return to ifparser.c CVS log (file) (dir) Up to [XFree86 CVS] / xc / config / makedepend

  1 dawes 1.1 /*
  2 dawes 3.8  * $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $
  3 dawes 1.1  *
  4            * Copyright 1992 Network Computing Devices, Inc.
  5            * 
  6            * Permission to use, copy, modify, and distribute this software and its
  7            * documentation for any purpose and without fee is hereby granted, provided
  8            * that the above copyright notice appear in all copies and that both that
  9            * copyright notice and this permission notice appear in supporting
 10            * documentation, and that the name of Network Computing Devices may not be
 11            * used in advertising or publicity pertaining to distribution of the software
 12            * without specific, written prior permission.  Network Computing Devices makes
 13            * no representations about the suitability of this software for any purpose.
 14            * It is provided ``as is'' without express or implied warranty.
 15            * 
 16            * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 17            * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
 18            * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
 19            * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 20            * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 21            * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 22            * PERFORMANCE OF THIS SOFTWARE.
 23            * 
 24 dawes 1.1  * Author:  Jim Fulton
 25            *          Network Computing Devices, Inc.
 26            * 
 27            * Simple if statement processor
 28            *
 29            * This module can be used to evaluate string representations of C language
 30            * if constructs.  It accepts the following grammar:
 31            * 
 32            *     EXPRESSION	:=	VALUE
 33            * 			 |	VALUE  BINOP	EXPRESSION
 34 dawes 3.6  *			 |	VALUE	'?'	EXPRESSION ':'	EXPRESSION
 35 dawes 1.1  * 
 36            *     VALUE		:=	'('  EXPRESSION  ')'
 37            * 			 |	'!'  VALUE
 38            * 			 |	'-'  VALUE
 39 dawes 3.10  * 			 |	'+'  VALUE
 40 dawes 3.6   *			 |	'~'  VALUE
 41 dawes 1.1   * 			 |	'defined'  '('  variable  ')'
 42             * 			 |	'defined'  variable
 43             *			 |	# variable '(' variable-list ')'
 44             * 			 |	variable
 45             * 			 |	number
 46             * 
 47             *     BINOP		:=	'*'	|  '/'	|  '%'
 48             * 			 |	'+'	|  '-'
 49             * 			 |	'<<'	|  '>>'
 50             * 			 |	'<'	|  '>'	|  '<='  |  '>='
 51             * 			 |	'=='	|  '!='
 52 dawes 3.6   * 			 |	'&'	|  '^'  |  '|'
 53 dawes 1.1   * 			 |	'&&'	|  '||'
 54             * 
 55 dawes 3.6   * The normal C order of precedence is supported.
 56 dawes 1.1   * 
 57             * 
 58             * External Entry Points:
 59             * 
 60             *     ParseIfExpression		parse a string for #if
 61             */
 62 tsi   3.11 /* $XFree86: xc/config/makedepend/ifparser.c,v 3.10tsi Exp $ */
 63 dawes 1.1  
 64            #include "ifparser.h"
 65            #include <ctype.h>
 66 dawes 3.7  #include <stdlib.h>
 67            #include <string.h>
 68 dawes 1.1  
 69            /****************************************************************************
 70            		   Internal Macros and Utilities for Parser
 71             ****************************************************************************/
 72            
 73            #define DO(val) if (!(val)) return NULL
 74            #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
 75            #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
 76            #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
 77            
 78            
 79            static const char *
 80 dawes 3.7  parse_variable (IfParser *g, const char *cp, const char **varp)
 81 dawes 1.1  {
 82                SKIPSPACE (cp);
 83            
 84                if (!isvarfirstletter (*cp))
 85            	return CALLFUNC(g, handle_error) (g, cp, "variable name");
 86            
 87                *varp = cp;
 88                /* EMPTY */
 89                for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
 90                return cp;
 91            }
 92            
 93            
 94            static const char *
 95 dawes 3.7  parse_number (IfParser *g, const char *cp, long *valp)
 96 dawes 1.1  {
 97 tsi   3.9      long base = 10;
 98 dawes 1.1      SKIPSPACE (cp);
 99            
100                if (!isdigit(*cp))
101            	return CALLFUNC(g, handle_error) (g, cp, "number");
102            
103 tsi   3.9      *valp = 0;
104            
105                if (*cp == '0') {
106            	cp++;
107            	if ((*cp == 'x') || (*cp == 'X')) {
108            	    base = 16;
109            	    cp++;
110            	} else {
111            	    base = 8;
112            	}
113                }
114            
115                /* Ignore overflows and assume ASCII, what source is usually written in */
116                while (1) {
117            	int increment = -1;
118            	if (base == 8) {
119            	    if ((*cp >= '0') && (*cp <= '7'))
120            		increment = *cp++ - '0';
121            	} else if (base == 16) {
122            	    if ((*cp >= '0') && (*cp <= '9'))
123            		increment = *cp++ - '0';
124 tsi   3.9  	    else if ((*cp >= 'A') &&  (*cp <= 'F'))
125            		increment = *cp++ - ('A' - 10);
126            	    else if ((*cp >= 'a') && (*cp <= 'f'))
127            		increment = *cp++ - ('a' - 10);
128            	} else {	/* Decimal */
129            	    if ((*cp >= '0') && (*cp <= '9'))
130            		increment = *cp++ - '0';
131            	}
132            	if (increment < 0)
133            	    break;
134            	*valp = (*valp * base) + increment;
135                }
136            
137                /* Skip trailing qualifiers */
138 dawes 3.1      while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
139 dawes 1.1      return cp;
140            }
141            
142 dawes 3.1  static const char *
143 dawes 3.7  parse_character (IfParser *g, const char *cp, long *valp)
144 dawes 3.1  {
145                char val;
146            
147                SKIPSPACE (cp);
148                if (*cp == '\\')
149            	switch (cp[1]) {
150            	case 'n': val = '\n'; break;
151            	case 't': val = '\t'; break;
152            	case 'v': val = '\v'; break;
153            	case 'b': val = '\b'; break;
154            	case 'r': val = '\r'; break;
155            	case 'f': val = '\f'; break;
156            	case 'a': val = '\a'; break;
157            	case '\\': val = '\\'; break;
158            	case '?': val = '\?'; break;
159            	case '\'': val = '\''; break;
160            	case '\"': val = '\"'; break;
161            	case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
162            	default: val = (char) strtol (cp + 1, NULL, 8); break;
163            	}
164                else
165 dawes 3.1  	val = *cp;
166                while (*cp != '\'') cp++;
167                *valp = (long) val;
168                return cp;
169            }
170 dawes 1.1  
171            static const char *
172 dawes 3.7  parse_value (IfParser *g, const char *cp, long *valp)
173 dawes 1.1  {
174 tsi   3.11     const char *var, *varend;
175 dawes 1.1  
176                *valp = 0;
177            
178                SKIPSPACE (cp);
179                if (!*cp)
180            	return cp;
181            
182                switch (*cp) {
183                  case '(':
184            	DO (cp = ParseIfExpression (g, cp + 1, valp));
185            	SKIPSPACE (cp);
186            	if (*cp != ')') 
187            	    return CALLFUNC(g, handle_error) (g, cp, ")");
188            
189            	return cp + 1;			/* skip the right paren */
190            
191                  case '!':
192            	DO (cp = parse_value (g, cp + 1, valp));
193            	*valp = !(*valp);
194            	return cp;
195            
196 dawes 1.1        case '-':
197            	DO (cp = parse_value (g, cp + 1, valp));
198            	*valp = -(*valp);
199 dawes 3.10 	return cp;
200            
201                  case '+':
202            	DO (cp = parse_value (g, cp + 1, valp));
203 dawes 1.1  	return cp;
204            
205 dawes 3.2        case '~':
206            	DO (cp = parse_value (g, cp + 1, valp));
207            	*valp = ~(*valp);
208            	return cp;
209            
210 dawes 1.1        case '#':
211            	DO (cp = parse_variable (g, cp + 1, &var));
212            	SKIPSPACE (cp);
213            	if (*cp != '(')
214            	    return CALLFUNC(g, handle_error) (g, cp, "(");
215            	do {
216            	    DO (cp = parse_variable (g, cp + 1, &var));
217            	    SKIPSPACE (cp);
218            	} while (*cp && *cp != ')');
219            	if (*cp != ')')
220            	    return CALLFUNC(g, handle_error) (g, cp, ")");
221            	*valp = 1; /* XXX */
222            	return cp + 1;
223            
224 dawes 3.1        case '\'':
225            	DO (cp = parse_character (g, cp + 1, valp));
226            	if (*cp != '\'')
227            	    return CALLFUNC(g, handle_error) (g, cp, "'");
228            	return cp + 1;
229            
230 dawes 1.1        case 'd':
231            	if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
232            	    int paren = 0;
233 dawes 3.0  	    int len;
234            
235 dawes 1.1  	    cp += 7;
236            	    SKIPSPACE (cp);
237            	    if (*cp == '(') {
238            		paren = 1;
239            		cp++;
240            	    }
241            	    DO (cp = parse_variable (g, cp, &var));
242 dawes 3.0  	    len = cp - var;
243 dawes 1.1  	    SKIPSPACE (cp);
244            	    if (paren && *cp != ')')
245            		return CALLFUNC(g, handle_error) (g, cp, ")");
246 dawes 3.0  	    *valp = (*(g->funcs.eval_defined)) (g, var, len);
247 dawes 1.1  	    return cp + paren;		/* skip the right paren */
248            	}
249            	/* fall out */
250                }
251            
252                if (isdigit(*cp)) {
253            	DO (cp = parse_number (g, cp, valp));
254                } else if (!isvarfirstletter(*cp))
255            	return CALLFUNC(g, handle_error) (g, cp, "variable or number");
256                else {
257            	DO (cp = parse_variable (g, cp, &var));
258 tsi   3.11 	varend = cp;
259            	SKIPSPACE(cp);
260            	if (*cp != '(') {
261            	    *valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
262            	} else {
263            	    do {
264            		long dummy;
265            		DO (cp = ParseIfExpression (g, cp + 1, &dummy));
266            		SKIPSPACE(cp);
267            		if (*cp == ')')
268            		    break;
269            		if (*cp != ',')
270            		    return CALLFUNC(g, handle_error) (g, cp, ",");
271            	    } while (1);
272            
273            	    *valp = 1;	/* XXX */
274            	    cp++;
275            	}
276 dawes 1.1      }
277                
278                return cp;
279            }
280            
281            
282            
283            static const char *
284 dawes 3.7  parse_product (IfParser *g, const char *cp, long *valp)
285 dawes 1.1  {
286 dawes 3.1      long rightval;
287 dawes 1.1  
288                DO (cp = parse_value (g, cp, valp));
289                SKIPSPACE (cp);
290            
291                switch (*cp) {
292                  case '*':
293            	DO (cp = parse_product (g, cp + 1, &rightval));
294            	*valp = (*valp * rightval);
295            	break;
296            
297                  case '/':
298            	DO (cp = parse_product (g, cp + 1, &rightval));
299            	*valp = (*valp / rightval);
300            	break;
301            
302                  case '%':
303            	DO (cp = parse_product (g, cp + 1, &rightval));
304            	*valp = (*valp % rightval);
305            	break;
306                }
307                return cp;
308 dawes 1.1  }
309            
310            
311            static const char *
312 dawes 3.7  parse_sum (IfParser *g, const char *cp, long *valp)
313 dawes 1.1  {
314 dawes 3.1      long rightval;
315 dawes 1.1  
316                DO (cp = parse_product (g, cp, valp));
317                SKIPSPACE (cp);
318            
319                switch (*cp) {
320                  case '+':
321            	DO (cp = parse_sum (g, cp + 1, &rightval));
322            	*valp = (*valp + rightval);
323            	break;
324            
325                  case '-':
326            	DO (cp = parse_sum (g, cp + 1, &rightval));
327            	*valp = (*valp - rightval);
328            	break;
329                }
330                return cp;
331            }
332            
333            
334            static const char *
335 dawes 3.7  parse_shift (IfParser *g, const char *cp, long *valp)
336 dawes 1.1  {
337 dawes 3.1      long rightval;
338 dawes 1.1  
339                DO (cp = parse_sum (g, cp, valp));
340                SKIPSPACE (cp);
341            
342                switch (*cp) {
343                  case '<':
344            	if (cp[1] == '<') {
345            	    DO (cp = parse_shift (g, cp + 2, &rightval));
346            	    *valp = (*valp << rightval);
347            	}
348            	break;
349            
350                  case '>':
351            	if (cp[1] == '>') {
352            	    DO (cp = parse_shift (g, cp + 2, &rightval));
353            	    *valp = (*valp >> rightval);
354            	}
355            	break;
356                }
357                return cp;
358            }
359 dawes 1.1  
360            
361            static const char *
362 dawes 3.7  parse_inequality (IfParser *g, const char *cp, long *valp)
363 dawes 1.1  {
364 dawes 3.1      long rightval;
365 dawes 1.1  
366                DO (cp = parse_shift (g, cp, valp));
367                SKIPSPACE (cp);
368            
369                switch (*cp) {
370                  case '<':
371            	if (cp[1] == '=') {
372            	    DO (cp = parse_inequality (g, cp + 2, &rightval));
373            	    *valp = (*valp <= rightval);
374            	} else {
375            	    DO (cp = parse_inequality (g, cp + 1, &rightval));
376            	    *valp = (*valp < rightval);
377            	}
378            	break;
379            
380                  case '>':
381            	if (cp[1] == '=') {
382            	    DO (cp = parse_inequality (g, cp + 2, &rightval));
383            	    *valp = (*valp >= rightval);
384            	} else {
385            	    DO (cp = parse_inequality (g, cp + 1, &rightval));
386 dawes 1.1  	    *valp = (*valp > rightval);
387            	}
388            	break;
389                }
390                return cp;
391            }
392            
393            
394            static const char *
395 dawes 3.7  parse_equality (IfParser *g, const char *cp, long *valp)
396 dawes 1.1  {
397 dawes 3.1      long rightval;
398 dawes 1.1  
399                DO (cp = parse_inequality (g, cp, valp));
400                SKIPSPACE (cp);
401            
402                switch (*cp) {
403                  case '=':
404            	if (cp[1] == '=')
405            	    cp++;
406            	DO (cp = parse_equality (g, cp + 1, &rightval));
407            	*valp = (*valp == rightval);
408            	break;
409            
410                  case '!':
411            	if (cp[1] != '=')
412            	    break;
413            	DO (cp = parse_equality (g, cp + 2, &rightval));
414            	*valp = (*valp != rightval);
415            	break;
416                }
417                return cp;
418            }
419 dawes 1.1  
420            
421            static const char *
422 dawes 3.7  parse_band (IfParser *g, const char *cp, long *valp)
423 dawes 1.1  {
424 dawes 3.1      long rightval;
425 dawes 1.1  
426                DO (cp = parse_equality (g, cp, valp));
427                SKIPSPACE (cp);
428            
429                switch (*cp) {
430                  case '&':
431            	if (cp[1] != '&') {
432            	    DO (cp = parse_band (g, cp + 1, &rightval));
433            	    *valp = (*valp & rightval);
434            	}
435            	break;
436                }
437                return cp;
438            }
439            
440            
441            static const char *
442 dawes 3.7  parse_bxor (IfParser *g, const char *cp, long *valp)
443 dawes 3.6  {
444                long rightval;
445            
446                DO (cp = parse_band (g, cp, valp));
447                SKIPSPACE (cp);
448            
449                switch (*cp) {
450                  case '^':
451            	DO (cp = parse_bxor (g, cp + 1, &rightval));
452            	*valp = (*valp ^ rightval);
453            	break;
454                }
455                return cp;
456            }
457            
458            
459            static const char *
460 dawes 3.7  parse_bor (IfParser *g, const char *cp, long *valp)
461 dawes 1.1  {
462 dawes 3.1      long rightval;
463 dawes 1.1  
464 dawes 3.6      DO (cp = parse_bxor (g, cp, valp));
465 dawes 1.1      SKIPSPACE (cp);
466            
467                switch (*cp) {
468                  case '|':
469            	if (cp[1] != '|') {
470            	    DO (cp = parse_bor (g, cp + 1, &rightval));
471            	    *valp = (*valp | rightval);
472            	}
473            	break;
474                }
475                return cp;
476            }
477            
478            
479            static const char *
480 dawes 3.7  parse_land (IfParser *g, const char *cp, long *valp)
481 dawes 1.1  {
482 dawes 3.1      long rightval;
483 dawes 1.1  
484                DO (cp = parse_bor (g, cp, valp));
485                SKIPSPACE (cp);
486            
487                switch (*cp) {
488                  case '&':
489            	if (cp[1] != '&')
490            	    return CALLFUNC(g, handle_error) (g, cp, "&&");
491            	DO (cp = parse_land (g, cp + 2, &rightval));
492            	*valp = (*valp && rightval);
493            	break;
494                }
495                return cp;
496            }
497            
498            
499            static const char *
500 dawes 3.7  parse_lor (IfParser *g, const char *cp, long *valp)
501 dawes 1.1  {
502 dawes 3.1      long rightval;
503 dawes 1.1  
504                DO (cp = parse_land (g, cp, valp));
505                SKIPSPACE (cp);
506            
507                switch (*cp) {
508                  case '|':
509            	if (cp[1] != '|')
510            	    return CALLFUNC(g, handle_error) (g, cp, "||");
511            	DO (cp = parse_lor (g, cp + 2, &rightval));
512            	*valp = (*valp || rightval);
513            	break;
514                }
515                return cp;
516            }
517            
518            
519 dawes 3.6  static const char *
520 dawes 3.7  parse_cond(IfParser *g, const char *cp, long *valp)
521 dawes 3.6  {
522                long trueval, falseval;
523            
524                DO (cp = parse_lor (g, cp, valp));
525                SKIPSPACE (cp);
526            
527                switch (*cp) {
528                  case '?':
529            	DO (cp = parse_cond (g, cp + 1, &trueval));
530            	SKIPSPACE (cp);
531            	if (*cp != ':')
532            	    return CALLFUNC(g, handle_error) (g, cp, ":");
533            	DO (cp = parse_cond (g, cp + 1, &falseval));
534            	*valp = (*valp ? trueval : falseval);
535            	break;
536                }
537                return cp;
538            }
539            
540            
541 dawes 1.1  /****************************************************************************
542            			     External Entry Points
543             ****************************************************************************/
544            
545            const char *
546 dawes 3.7  ParseIfExpression (IfParser *g, const char *cp, long *valp)
547 dawes 1.1  {
548 dawes 3.6      return parse_cond (g, cp, valp);
549 dawes 1.1  }

Powered by
ViewCVS 0.9.2