2
* $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws Exp $
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");
103
*valp = strtol(cp, &cp, 0);
107
for (cp++; isdigit(*cp); cp++) ;
114
parse_value (g, cp, valp)
129
DO (cp = ParseIfExpression (g, cp + 1, valp));
132
return CALLFUNC(g, handle_error) (g, cp, ")");
134
return cp + 1; /* skip the right paren */
137
DO (cp = parse_value (g, cp + 1, valp));
142
DO (cp = parse_value (g, cp + 1, valp));
147
DO (cp = parse_variable (g, cp + 1, &var));
150
return CALLFUNC(g, handle_error) (g, cp, "(");
152
DO (cp = parse_variable (g, cp + 1, &var));
154
} while (*cp && *cp != ')');
156
return CALLFUNC(g, handle_error) (g, cp, ")");
161
if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
169
DO (cp = parse_variable (g, cp, &var));
171
if (paren && *cp != ')')
172
return CALLFUNC(g, handle_error) (g, cp, ")");
173
*valp = (*(g->funcs.eval_defined)) (g, var, cp - var);
174
return cp + paren; /* skip the right paren */
180
DO (cp = parse_number (g, cp, valp));
181
} else if (!isvarfirstletter(*cp))
182
return CALLFUNC(g, handle_error) (g, cp, "variable or number");
184
DO (cp = parse_variable (g, cp, &var));
185
*valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
194
parse_product (g, cp, valp)
201
DO (cp = parse_value (g, cp, valp));
206
DO (cp = parse_product (g, cp + 1, &rightval));
207
*valp = (*valp * rightval);
211
DO (cp = parse_product (g, cp + 1, &rightval));
212
*valp = (*valp / rightval);
216
DO (cp = parse_product (g, cp + 1, &rightval));
217
*valp = (*valp % rightval);
225
parse_sum (g, cp, valp)
232
DO (cp = parse_product (g, cp, valp));
237
DO (cp = parse_sum (g, cp + 1, &rightval));
238
*valp = (*valp + rightval);
242
DO (cp = parse_sum (g, cp + 1, &rightval));
243
*valp = (*valp - rightval);
251
parse_shift (g, cp, valp)
258
DO (cp = parse_sum (g, cp, valp));
264
DO (cp = parse_shift (g, cp + 2, &rightval));
265
*valp = (*valp << rightval);
271
DO (cp = parse_shift (g, cp + 2, &rightval));
272
*valp = (*valp >> rightval);
281
parse_inequality (g, cp, valp)
288
DO (cp = parse_shift (g, cp, valp));
294
DO (cp = parse_inequality (g, cp + 2, &rightval));
295
*valp = (*valp <= rightval);
297
DO (cp = parse_inequality (g, cp + 1, &rightval));
298
*valp = (*valp < rightval);
304
DO (cp = parse_inequality (g, cp + 2, &rightval));
305
*valp = (*valp >= rightval);
307
DO (cp = parse_inequality (g, cp + 1, &rightval));
308
*valp = (*valp > rightval);
317
parse_equality (g, cp, valp)
324
DO (cp = parse_inequality (g, cp, valp));
331
DO (cp = parse_equality (g, cp + 1, &rightval));
332
*valp = (*valp == rightval);
338
DO (cp = parse_equality (g, cp + 2, &rightval));
339
*valp = (*valp != rightval);
347
parse_band (g, cp, valp)
354
DO (cp = parse_equality (g, cp, valp));
360
DO (cp = parse_band (g, cp + 1, &rightval));
361
*valp = (*valp & rightval);
370
parse_bor (g, cp, valp)
377
DO (cp = parse_band (g, cp, valp));
383
DO (cp = parse_bor (g, cp + 1, &rightval));
384
*valp = (*valp | rightval);
393
parse_land (g, cp, valp)
400
DO (cp = parse_bor (g, cp, valp));
406
return CALLFUNC(g, handle_error) (g, cp, "&&");
407
DO (cp = parse_land (g, cp + 2, &rightval));
408
*valp = (*valp && rightval);
416
parse_lor (g, cp, valp)
423
DO (cp = parse_land (g, cp, valp));
429
return CALLFUNC(g, handle_error) (g, cp, "||");
430
DO (cp = parse_lor (g, cp + 2, &rightval));
431
*valp = (*valp || rightval);
438
/****************************************************************************
439
External Entry Points
440
****************************************************************************/
443
ParseIfExpression (g, cp, valp)
448
return parse_lor (g, cp, valp);