2
* $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld 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
34
* | VALUE '?' EXPRESSION ':' EXPRESSION
36
* 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
62
/* $XFree86: xc/config/makedepend/ifparser.c,v 3.11 2002/09/23 01:48:08 tsi Exp $ */
69
/****************************************************************************
70
Internal Macros and Utilities for Parser
71
****************************************************************************/
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) == '_')
80
parse_variable (IfParser *g, const char *cp, const char **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 (IfParser *g, const char *cp, long *valp)
101
return CALLFUNC(g, handle_error) (g, cp, "number");
107
if ((*cp == 'x') || (*cp == 'X')) {
115
/* Ignore overflows and assume ASCII, what source is usually written in */
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
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';
134
*valp = (*valp * base) + increment;
137
/* Skip trailing qualifiers */
138
while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
143
parse_character (IfParser *g, const char *cp, long *valp)
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;
166
while (*cp != '\'') cp++;
172
parse_value (IfParser *g, const char *cp, long *valp)
174
const char *var, *varend;
184
DO (cp = ParseIfExpression (g, cp + 1, valp));
187
return CALLFUNC(g, handle_error) (g, cp, ")");
189
return cp + 1; /* skip the right paren */
192
DO (cp = parse_value (g, cp + 1, valp));
197
DO (cp = parse_value (g, cp + 1, valp));
202
DO (cp = parse_value (g, cp + 1, valp));
206
DO (cp = parse_value (g, cp + 1, valp));
211
DO (cp = parse_variable (g, cp + 1, &var));
214
return CALLFUNC(g, handle_error) (g, cp, "(");
216
DO (cp = parse_variable (g, cp + 1, &var));
218
} while (*cp && *cp != ')');
220
return CALLFUNC(g, handle_error) (g, cp, ")");
225
DO (cp = parse_character (g, cp + 1, valp));
227
return CALLFUNC(g, handle_error) (g, cp, "'");
231
if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
241
DO (cp = parse_variable (g, cp, &var));
244
if (paren && *cp != ')')
245
return CALLFUNC(g, handle_error) (g, cp, ")");
246
*valp = (*(g->funcs.eval_defined)) (g, var, len);
247
return cp + paren; /* skip the right paren */
253
DO (cp = parse_number (g, cp, valp));
254
} else if (!isvarfirstletter(*cp))
255
return CALLFUNC(g, handle_error) (g, cp, "variable or number");
257
DO (cp = parse_variable (g, cp, &var));
261
*valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
265
DO (cp = ParseIfExpression (g, cp + 1, &dummy));
270
return CALLFUNC(g, handle_error) (g, cp, ",");
284
parse_product (IfParser *g, const char *cp, long *valp)
288
DO (cp = parse_value (g, cp, valp));
293
DO (cp = parse_product (g, cp + 1, &rightval));
294
*valp = (*valp * rightval);
298
DO (cp = parse_product (g, cp + 1, &rightval));
300
return CALLFUNC(g, handle_error) (g, cp, "0");
301
*valp = (*valp / rightval);
305
DO (cp = parse_product (g, cp + 1, &rightval));
306
*valp = (*valp % rightval);
314
parse_sum (IfParser *g, const char *cp, long *valp)
318
DO (cp = parse_product (g, cp, valp));
323
DO (cp = parse_sum (g, cp + 1, &rightval));
324
*valp = (*valp + rightval);
328
DO (cp = parse_sum (g, cp + 1, &rightval));
329
*valp = (*valp - rightval);
337
parse_shift (IfParser *g, const char *cp, long *valp)
341
DO (cp = parse_sum (g, cp, valp));
347
DO (cp = parse_shift (g, cp + 2, &rightval));
348
*valp = (*valp << rightval);
354
DO (cp = parse_shift (g, cp + 2, &rightval));
355
*valp = (*valp >> rightval);
364
parse_inequality (IfParser *g, const char *cp, long *valp)
368
DO (cp = parse_shift (g, cp, valp));
374
DO (cp = parse_inequality (g, cp + 2, &rightval));
375
*valp = (*valp <= rightval);
377
DO (cp = parse_inequality (g, cp + 1, &rightval));
378
*valp = (*valp < rightval);
384
DO (cp = parse_inequality (g, cp + 2, &rightval));
385
*valp = (*valp >= rightval);
387
DO (cp = parse_inequality (g, cp + 1, &rightval));
388
*valp = (*valp > rightval);
397
parse_equality (IfParser *g, const char *cp, long *valp)
401
DO (cp = parse_inequality (g, cp, valp));
408
DO (cp = parse_equality (g, cp + 1, &rightval));
409
*valp = (*valp == rightval);
415
DO (cp = parse_equality (g, cp + 2, &rightval));
416
*valp = (*valp != rightval);
424
parse_band (IfParser *g, const char *cp, long *valp)
428
DO (cp = parse_equality (g, cp, valp));
434
DO (cp = parse_band (g, cp + 1, &rightval));
435
*valp = (*valp & rightval);
444
parse_bxor (IfParser *g, const char *cp, long *valp)
448
DO (cp = parse_band (g, cp, valp));
453
DO (cp = parse_bxor (g, cp + 1, &rightval));
454
*valp = (*valp ^ rightval);
462
parse_bor (IfParser *g, const char *cp, long *valp)
466
DO (cp = parse_bxor (g, cp, valp));
472
DO (cp = parse_bor (g, cp + 1, &rightval));
473
*valp = (*valp | rightval);
482
parse_land (IfParser *g, const char *cp, long *valp)
486
DO (cp = parse_bor (g, cp, valp));
492
return CALLFUNC(g, handle_error) (g, cp, "&&");
493
DO (cp = parse_land (g, cp + 2, &rightval));
494
*valp = (*valp && rightval);
502
parse_lor (IfParser *g, const char *cp, long *valp)
506
DO (cp = parse_land (g, cp, valp));
512
return CALLFUNC(g, handle_error) (g, cp, "||");
513
DO (cp = parse_lor (g, cp + 2, &rightval));
514
*valp = (*valp || rightval);
522
parse_cond(IfParser *g, const char *cp, long *valp)
524
long trueval, falseval;
526
DO (cp = parse_lor (g, cp, valp));
531
DO (cp = parse_cond (g, cp + 1, &trueval));
534
return CALLFUNC(g, handle_error) (g, cp, ":");
535
DO (cp = parse_cond (g, cp + 1, &falseval));
536
*valp = (*valp ? trueval : falseval);
543
/****************************************************************************
544
External Entry Points
545
****************************************************************************/
548
ParseIfExpression (IfParser *g, const char *cp, long *valp)
550
return parse_cond (g, cp, valp);