2 * $XConsortium: ifparser.c /main/10 1996/09/28 16:15:18 rws $
4 * Copyright 1992 Network Computing Devices, Inc.
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.
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.
25 * Network Computing Devices, Inc.
27 * Simple if statement processor
29 * This module can be used to evaluate string representations of C language
30 * if constructs. It accepts the following grammar:
33 * | VALUE BINOP EXPRESSION
35 * VALUE := '(' EXPRESSION ')'
38 * | 'defined' '(' variable ')'
39 * | 'defined' variable
40 * | # variable '(' variable-list ')'
44 * BINOP := '*' | '/' | '%'
47 * | '<' | '>' | '<=' | '>='
52 * The normal C order of precidence is supported.
55 * External Entry Points:
57 * ParseIfExpression parse a string for #if
63 /****************************************************************************
64 Internal Macros and Utilities for Parser
65 ****************************************************************************/
67 #define DO(val) if (!(val)) return NULL
68 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
69 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
70 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
74 parse_variable (g, cp, varp)
81 if (!isvarfirstletter (*cp))
82 return CALLFUNC(g, handle_error) (g, cp, "variable name");
86 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
92 parse_number (g, cp, valp)
100 return CALLFUNC(g, handle_error) (g, cp, "number");
102 *valp = strtol(cp, &cp, 0);
103 /* skip trailing qualifiers */
104 while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
108 for (cp++; isdigit(*cp); cp++) ;
114 parse_character (g, cp, valp)
124 case 'n': val = '\n'; break;
125 case 't': val = '\t'; break;
126 case 'v': val = '\v'; break;
127 case 'b': val = '\b'; break;
128 case 'r': val = '\r'; break;
129 case 'f': val = '\f'; break;
130 case 'a': val = '\a'; break;
131 case '\\': val = '\\'; break;
132 case '?': val = '\?'; break;
133 case '\'': val = '\''; break;
134 case '\"': val = '\"'; break;
135 case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
136 default: val = (char) strtol (cp + 1, NULL, 8); break;
140 while (*cp != '\'') cp++;
146 parse_value (g, cp, valp)
161 DO (cp = ParseIfExpression (g, cp + 1, valp));
164 return CALLFUNC(g, handle_error) (g, cp, ")");
166 return cp + 1; /* skip the right paren */
169 DO (cp = parse_value (g, cp + 1, valp));
174 DO (cp = parse_value (g, cp + 1, valp));
179 DO (cp = parse_variable (g, cp + 1, &var));
182 return CALLFUNC(g, handle_error) (g, cp, "(");
184 DO (cp = parse_variable (g, cp + 1, &var));
186 } while (*cp && *cp != ')');
188 return CALLFUNC(g, handle_error) (g, cp, ")");
193 DO (cp = parse_character (g, cp + 1, valp));
195 return CALLFUNC(g, handle_error) (g, cp, "'");
199 if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
209 DO (cp = parse_variable (g, cp, &var));
212 if (paren && *cp != ')')
213 return CALLFUNC(g, handle_error) (g, cp, ")");
214 *valp = (*(g->funcs.eval_defined)) (g, var, len);
215 return cp + paren; /* skip the right paren */
221 DO (cp = parse_number (g, cp, valp));
222 } else if (!isvarfirstletter(*cp))
223 return CALLFUNC(g, handle_error) (g, cp, "variable or number");
225 DO (cp = parse_variable (g, cp, &var));
226 *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
235 parse_product (g, cp, valp)
242 DO (cp = parse_value (g, cp, valp));
247 DO (cp = parse_product (g, cp + 1, &rightval));
248 *valp = (*valp * rightval);
252 DO (cp = parse_product (g, cp + 1, &rightval));
253 *valp = (*valp / rightval);
257 DO (cp = parse_product (g, cp + 1, &rightval));
258 *valp = (*valp % rightval);
266 parse_sum (g, cp, valp)
273 DO (cp = parse_product (g, cp, valp));
278 DO (cp = parse_sum (g, cp + 1, &rightval));
279 *valp = (*valp + rightval);
283 DO (cp = parse_sum (g, cp + 1, &rightval));
284 *valp = (*valp - rightval);
292 parse_shift (g, cp, valp)
299 DO (cp = parse_sum (g, cp, valp));
305 DO (cp = parse_shift (g, cp + 2, &rightval));
306 *valp = (*valp << rightval);
312 DO (cp = parse_shift (g, cp + 2, &rightval));
313 *valp = (*valp >> rightval);
322 parse_inequality (g, cp, valp)
329 DO (cp = parse_shift (g, cp, valp));
335 DO (cp = parse_inequality (g, cp + 2, &rightval));
336 *valp = (*valp <= rightval);
338 DO (cp = parse_inequality (g, cp + 1, &rightval));
339 *valp = (*valp < rightval);
345 DO (cp = parse_inequality (g, cp + 2, &rightval));
346 *valp = (*valp >= rightval);
348 DO (cp = parse_inequality (g, cp + 1, &rightval));
349 *valp = (*valp > rightval);
358 parse_equality (g, cp, valp)
365 DO (cp = parse_inequality (g, cp, valp));
372 DO (cp = parse_equality (g, cp + 1, &rightval));
373 *valp = (*valp == rightval);
379 DO (cp = parse_equality (g, cp + 2, &rightval));
380 *valp = (*valp != rightval);
388 parse_band (g, cp, valp)
395 DO (cp = parse_equality (g, cp, valp));
401 DO (cp = parse_band (g, cp + 1, &rightval));
402 *valp = (*valp & rightval);
411 parse_bor (g, cp, valp)
418 DO (cp = parse_band (g, cp, valp));
424 DO (cp = parse_bor (g, cp + 1, &rightval));
425 *valp = (*valp | rightval);
434 parse_land (g, cp, valp)
441 DO (cp = parse_bor (g, cp, valp));
447 return CALLFUNC(g, handle_error) (g, cp, "&&");
448 DO (cp = parse_land (g, cp + 2, &rightval));
449 *valp = (*valp && rightval);
457 parse_lor (g, cp, valp)
464 DO (cp = parse_land (g, cp, valp));
470 return CALLFUNC(g, handle_error) (g, cp, "||");
471 DO (cp = parse_lor (g, cp + 2, &rightval));
472 *valp = (*valp || rightval);
479 /****************************************************************************
480 External Entry Points
481 ****************************************************************************/
484 ParseIfExpression (g, cp, valp)
489 return parse_lor (g, cp, valp);