2 * $XConsortium: ifparser.c,v 1.8 95/06/03 00:01:41 gildea 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
65 /****************************************************************************
66 Internal Macros and Utilities for Parser
67 ****************************************************************************/
69 #define DO(val) if (!(val)) return NULL
70 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
71 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
72 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
76 parse_variable (g
, cp
, varp
)
83 if (!isvarfirstletter (*cp
))
84 return CALLFUNC(g
, handle_error
) (g
, cp
, "variable name");
88 for (cp
++; isalnum(*cp
) || *cp
== '_'; cp
++) ;
94 parse_number (g
, cp
, valp
)
102 return CALLFUNC(g
, handle_error
) (g
, cp
, "number");
105 *valp
= strtol(cp
, &cp
, 0);
109 for (cp
++; isdigit(*cp
); cp
++) ;
116 parse_value (g
, cp
, valp
)
131 DO (cp
= ParseIfExpression (g
, cp
+ 1, valp
));
134 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
136 return cp
+ 1; /* skip the right paren */
139 DO (cp
= parse_value (g
, cp
+ 1, valp
));
144 DO (cp
= parse_value (g
, cp
+ 1, valp
));
149 DO (cp
= parse_variable (g
, cp
+ 1, &var
));
152 return CALLFUNC(g
, handle_error
) (g
, cp
, "(");
154 DO (cp
= parse_variable (g
, cp
+ 1, &var
));
156 } while (*cp
&& *cp
!= ')');
158 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
163 if (strncmp (cp
, "defined", 7) == 0 && !isalnum(cp
[7])) {
173 DO (cp
= parse_variable (g
, cp
, &var
));
176 if (paren
&& *cp
!= ')')
177 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
178 *valp
= (*(g
->funcs
.eval_defined
)) (g
, var
, len
);
179 return cp
+ paren
; /* skip the right paren */
185 DO (cp
= parse_number (g
, cp
, valp
));
186 } else if (!isvarfirstletter(*cp
))
187 return CALLFUNC(g
, handle_error
) (g
, cp
, "variable or number");
189 DO (cp
= parse_variable (g
, cp
, &var
));
190 *valp
= (*(g
->funcs
.eval_variable
)) (g
, var
, cp
- var
);
199 parse_product (g
, cp
, valp
)
206 DO (cp
= parse_value (g
, cp
, valp
));
211 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
212 *valp
= (*valp
* rightval
);
216 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
218 /* Do nothing in the divide-by-zero case. */
220 *valp
= (*valp
/ rightval
);
225 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
226 *valp
= (*valp
% rightval
);
234 parse_sum (g
, cp
, valp
)
241 DO (cp
= parse_product (g
, cp
, valp
));
246 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
247 *valp
= (*valp
+ rightval
);
251 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
252 *valp
= (*valp
- rightval
);
260 parse_shift (g
, cp
, valp
)
267 DO (cp
= parse_sum (g
, cp
, valp
));
273 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
274 *valp
= (*valp
<< rightval
);
280 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
281 *valp
= (*valp
>> rightval
);
290 parse_inequality (g
, cp
, valp
)
297 DO (cp
= parse_shift (g
, cp
, valp
));
303 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
304 *valp
= (*valp
<= rightval
);
306 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
307 *valp
= (*valp
< rightval
);
313 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
314 *valp
= (*valp
>= rightval
);
316 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
317 *valp
= (*valp
> rightval
);
326 parse_equality (g
, cp
, valp
)
333 DO (cp
= parse_inequality (g
, cp
, valp
));
340 DO (cp
= parse_equality (g
, cp
+ 1, &rightval
));
341 *valp
= (*valp
== rightval
);
347 DO (cp
= parse_equality (g
, cp
+ 2, &rightval
));
348 *valp
= (*valp
!= rightval
);
356 parse_band (g
, cp
, valp
)
363 DO (cp
= parse_equality (g
, cp
, valp
));
369 DO (cp
= parse_band (g
, cp
+ 1, &rightval
));
370 *valp
= (*valp
& rightval
);
379 parse_bor (g
, cp
, valp
)
386 DO (cp
= parse_band (g
, cp
, valp
));
392 DO (cp
= parse_bor (g
, cp
+ 1, &rightval
));
393 *valp
= (*valp
| rightval
);
402 parse_land (g
, cp
, valp
)
409 DO (cp
= parse_bor (g
, cp
, valp
));
415 return CALLFUNC(g
, handle_error
) (g
, cp
, "&&");
416 DO (cp
= parse_land (g
, cp
+ 2, &rightval
));
417 *valp
= (*valp
&& rightval
);
425 parse_lor (g
, cp
, valp
)
432 DO (cp
= parse_land (g
, cp
, valp
));
438 return CALLFUNC(g
, handle_error
) (g
, cp
, "||");
439 DO (cp
= parse_lor (g
, cp
+ 2, &rightval
));
440 *valp
= (*valp
|| rightval
);
447 /****************************************************************************
448 External Entry Points
449 ****************************************************************************/
452 ParseIfExpression (g
, cp
, valp
)
457 return parse_lor (g
, cp
, valp
);