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
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])) {
171 DO (cp
= parse_variable (g
, cp
, &var
));
174 if (paren
&& *cp
!= ')')
175 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
176 *valp
= (*(g
->funcs
.eval_defined
)) (g
, var
, len
);
177 return cp
+ paren
; /* skip the right paren */
183 DO (cp
= parse_number (g
, cp
, valp
));
184 } else if (!isvarfirstletter(*cp
))
185 return CALLFUNC(g
, handle_error
) (g
, cp
, "variable or number");
187 DO (cp
= parse_variable (g
, cp
, &var
));
188 *valp
= (*(g
->funcs
.eval_variable
)) (g
, var
, cp
- var
);
197 parse_product (g
, cp
, valp
)
204 DO (cp
= parse_value (g
, cp
, valp
));
209 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
210 *valp
= (*valp
* rightval
);
214 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
216 /* Do nothing in the divide-by-zero case. */
218 *valp
= (*valp
/ rightval
);
223 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
224 *valp
= (*valp
% rightval
);
232 parse_sum (g
, cp
, valp
)
239 DO (cp
= parse_product (g
, cp
, valp
));
244 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
245 *valp
= (*valp
+ rightval
);
249 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
250 *valp
= (*valp
- rightval
);
258 parse_shift (g
, cp
, valp
)
265 DO (cp
= parse_sum (g
, cp
, valp
));
271 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
272 *valp
= (*valp
<< rightval
);
278 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
279 *valp
= (*valp
>> rightval
);
288 parse_inequality (g
, cp
, valp
)
295 DO (cp
= parse_shift (g
, cp
, valp
));
301 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
302 *valp
= (*valp
<= rightval
);
304 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
305 *valp
= (*valp
< rightval
);
311 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
312 *valp
= (*valp
>= rightval
);
314 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
315 *valp
= (*valp
> rightval
);
324 parse_equality (g
, cp
, valp
)
331 DO (cp
= parse_inequality (g
, cp
, valp
));
338 DO (cp
= parse_equality (g
, cp
+ 1, &rightval
));
339 *valp
= (*valp
== rightval
);
345 DO (cp
= parse_equality (g
, cp
+ 2, &rightval
));
346 *valp
= (*valp
!= rightval
);
354 parse_band (g
, cp
, valp
)
361 DO (cp
= parse_equality (g
, cp
, valp
));
367 DO (cp
= parse_band (g
, cp
+ 1, &rightval
));
368 *valp
= (*valp
& rightval
);
377 parse_bor (g
, cp
, valp
)
384 DO (cp
= parse_band (g
, cp
, valp
));
390 DO (cp
= parse_bor (g
, cp
+ 1, &rightval
));
391 *valp
= (*valp
| rightval
);
400 parse_land (g
, cp
, valp
)
407 DO (cp
= parse_bor (g
, cp
, valp
));
413 return CALLFUNC(g
, handle_error
) (g
, cp
, "&&");
414 DO (cp
= parse_land (g
, cp
+ 2, &rightval
));
415 *valp
= (*valp
&& rightval
);
423 parse_lor (g
, cp
, valp
)
430 DO (cp
= parse_land (g
, cp
, valp
));
436 return CALLFUNC(g
, handle_error
) (g
, cp
, "||");
437 DO (cp
= parse_lor (g
, cp
+ 2, &rightval
));
438 *valp
= (*valp
|| rightval
);
445 /****************************************************************************
446 External Entry Points
447 ****************************************************************************/
450 ParseIfExpression (g
, cp
, valp
)
455 return parse_lor (g
, cp
, valp
);