2 * $XConsortium: ifparser.c /main/10 1996/09/28 16:15:18 rws $
3 * $XFree86: xc/config/makedepend/ifparser.c,v 3.6 1996/12/30 13:57:55 dawes Exp $
5 * Copyright 1992 Network Computing Devices, Inc.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Network Computing Devices may not be
12 * used in advertising or publicity pertaining to distribution of the software
13 * without specific, written prior permission. Network Computing Devices makes
14 * no representations about the suitability of this software for any purpose.
15 * It is provided ``as is'' without express or implied warranty.
17 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
19 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
20 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
26 * Network Computing Devices, Inc.
28 * Simple if statement processor
30 * This module can be used to evaluate string representations of C language
31 * if constructs. It accepts the following grammar:
34 * | VALUE BINOP EXPRESSION
35 * | VALUE '?' EXPRESSION ':' EXPRESSION
37 * VALUE := '(' EXPRESSION ')'
41 * | 'defined' '(' variable ')'
42 * | 'defined' variable
43 * | # variable '(' variable-list ')'
47 * BINOP := '*' | '/' | '%'
50 * | '<' | '>' | '<=' | '>='
55 * The normal C order of precedence is supported.
58 * External Entry Points:
60 * ParseIfExpression parse a string for #if
66 /****************************************************************************
67 Internal Macros and Utilities for Parser
68 ****************************************************************************/
70 #define DO(val) if (!(val)) return NULL
71 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
72 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
73 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
77 parse_variable (g, cp, varp)
84 if (!isvarfirstletter (*cp))
85 return CALLFUNC(g, handle_error) (g, cp, "variable name");
89 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
95 parse_number (g, cp, valp)
103 return CALLFUNC(g, handle_error) (g, cp, "number");
105 *valp = strtol(cp, &cp, 0);
106 /* skip trailing qualifiers */
107 while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
111 for (cp++; isdigit(*cp); cp++) ;
117 parse_character (g, cp, valp)
127 case 'n': val = '\n'; break;
128 case 't': val = '\t'; break;
129 case 'v': val = '\v'; break;
130 case 'b': val = '\b'; break;
131 case 'r': val = '\r'; break;
132 case 'f': val = '\f'; break;
133 case 'a': val = '\a'; break;
134 case '\\': val = '\\'; break;
135 case '?': val = '\?'; break;
136 case '\'': val = '\''; break;
137 case '\"': val = '\"'; break;
138 case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
139 default: val = (char) strtol (cp + 1, NULL, 8); break;
143 while (*cp != '\'') cp++;
149 parse_value (g, cp, valp)
164 DO (cp = ParseIfExpression (g, cp + 1, valp));
167 return CALLFUNC(g, handle_error) (g, cp, ")");
169 return cp + 1; /* skip the right paren */
172 DO (cp = parse_value (g, cp + 1, valp));
177 DO (cp = parse_value (g, cp + 1, valp));
182 DO (cp = parse_value (g, cp + 1, valp));
187 DO (cp = parse_variable (g, cp + 1, &var));
190 return CALLFUNC(g, handle_error) (g, cp, "(");
192 DO (cp = parse_variable (g, cp + 1, &var));
194 } while (*cp && *cp != ')');
196 return CALLFUNC(g, handle_error) (g, cp, ")");
201 DO (cp = parse_character (g, cp + 1, valp));
203 return CALLFUNC(g, handle_error) (g, cp, "'");
207 if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
217 DO (cp = parse_variable (g, cp, &var));
220 if (paren && *cp != ')')
221 return CALLFUNC(g, handle_error) (g, cp, ")");
222 *valp = (*(g->funcs.eval_defined)) (g, var, len);
223 return cp + paren; /* skip the right paren */
229 DO (cp = parse_number (g, cp, valp));
230 } else if (!isvarfirstletter(*cp))
231 return CALLFUNC(g, handle_error) (g, cp, "variable or number");
233 DO (cp = parse_variable (g, cp, &var));
234 *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
243 parse_product (g, cp, valp)
250 DO (cp = parse_value (g, cp, valp));
255 DO (cp = parse_product (g, cp + 1, &rightval));
256 *valp = (*valp * rightval);
260 DO (cp = parse_product (g, cp + 1, &rightval));
261 *valp = (*valp / rightval);
265 DO (cp = parse_product (g, cp + 1, &rightval));
266 *valp = (*valp % rightval);
274 parse_sum (g, cp, valp)
281 DO (cp = parse_product (g, cp, valp));
286 DO (cp = parse_sum (g, cp + 1, &rightval));
287 *valp = (*valp + rightval);
291 DO (cp = parse_sum (g, cp + 1, &rightval));
292 *valp = (*valp - rightval);
300 parse_shift (g, cp, valp)
307 DO (cp = parse_sum (g, cp, valp));
313 DO (cp = parse_shift (g, cp + 2, &rightval));
314 *valp = (*valp << rightval);
320 DO (cp = parse_shift (g, cp + 2, &rightval));
321 *valp = (*valp >> rightval);
330 parse_inequality (g, cp, valp)
337 DO (cp = parse_shift (g, cp, valp));
343 DO (cp = parse_inequality (g, cp + 2, &rightval));
344 *valp = (*valp <= rightval);
346 DO (cp = parse_inequality (g, cp + 1, &rightval));
347 *valp = (*valp < rightval);
353 DO (cp = parse_inequality (g, cp + 2, &rightval));
354 *valp = (*valp >= rightval);
356 DO (cp = parse_inequality (g, cp + 1, &rightval));
357 *valp = (*valp > rightval);
366 parse_equality (g, cp, valp)
373 DO (cp = parse_inequality (g, cp, valp));
380 DO (cp = parse_equality (g, cp + 1, &rightval));
381 *valp = (*valp == rightval);
387 DO (cp = parse_equality (g, cp + 2, &rightval));
388 *valp = (*valp != rightval);
396 parse_band (g, cp, valp)
403 DO (cp = parse_equality (g, cp, valp));
409 DO (cp = parse_band (g, cp + 1, &rightval));
410 *valp = (*valp & rightval);
419 parse_bxor (g, cp, valp)
426 DO (cp = parse_band (g, cp, valp));
431 DO (cp = parse_bxor (g, cp + 1, &rightval));
432 *valp = (*valp ^ rightval);
440 parse_bor (g, cp, valp)
447 DO (cp = parse_bxor (g, cp, valp));
453 DO (cp = parse_bor (g, cp + 1, &rightval));
454 *valp = (*valp | rightval);
463 parse_land (g, cp, valp)
470 DO (cp = parse_bor (g, cp, valp));
476 return CALLFUNC(g, handle_error) (g, cp, "&&");
477 DO (cp = parse_land (g, cp + 2, &rightval));
478 *valp = (*valp && rightval);
486 parse_lor (g, cp, valp)
493 DO (cp = parse_land (g, cp, valp));
499 return CALLFUNC(g, handle_error) (g, cp, "||");
500 DO (cp = parse_lor (g, cp + 2, &rightval));
501 *valp = (*valp || rightval);
509 parse_cond(g, cp, valp)
514 long trueval, falseval;
516 DO (cp = parse_lor (g, cp, valp));
521 DO (cp = parse_cond (g, cp + 1, &trueval));
524 return CALLFUNC(g, handle_error) (g, cp, ":");
525 DO (cp = parse_cond (g, cp + 1, &falseval));
526 *valp = (*valp ? trueval : falseval);
533 /****************************************************************************
534 External Entry Points
535 ****************************************************************************/
538 ParseIfExpression (g, cp, valp)
543 return parse_cond (g, cp, valp);