1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * $XConsortium: ifparser.c,v 1.8 95/06/03 00:01:41 gildea Exp $
5 * Copyright 1992 Network Computing Devices, Inc.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Network Computing Devices may not be
12 * used in advertising or publicity pertaining to distribution of the software
13 * without specific, written prior permission. Network Computing Devices makes
14 * no representations about the suitability of this software for any purpose.
15 * It is provided ``as is'' without express or implied warranty.
17 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
19 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
20 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
26 * Network Computing Devices, Inc.
28 * Simple if statement processor
30 * This module can be used to evaluate string representations of C language
31 * if constructs. It accepts the following grammar:
34 * | VALUE BINOP EXPRESSION
36 * VALUE := '(' EXPRESSION ')'
39 * | 'defined' '(' variable ')'
40 * | 'defined' variable
41 * | # variable '(' variable-list ')'
45 * BINOP := '*' | '/' | '%'
48 * | '<' | '>' | '<=' | '>='
53 * The normal C order of precidence is supported.
56 * External Entry Points:
58 * ParseIfExpression parse a string for #if
66 /****************************************************************************
67 Internal Macros and Utilities for Parser
68 ****************************************************************************/
70 #define DO(val) if (!(val)) return NULL
71 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
72 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
73 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
77 parse_variable (g
, cp
, 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 (g
, cp
, valp
)
103 return CALLFUNC(g
, handle_error
) (g
, cp
, "number");
108 *valp
= strtol(cp
, &cp2
, 0);
113 for (cp
++; isdigit(*cp
); cp
++) ;
120 parse_value (g
, cp
, valp
)
135 DO (cp
= ParseIfExpression (g
, cp
+ 1, valp
));
138 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
140 return cp
+ 1; /* skip the right paren */
143 DO (cp
= parse_value (g
, cp
+ 1, valp
));
148 DO (cp
= parse_value (g
, cp
+ 1, valp
));
153 DO (cp
= parse_variable (g
, cp
+ 1, &var
));
156 return CALLFUNC(g
, handle_error
) (g
, cp
, "(");
158 DO (cp
= parse_variable (g
, cp
+ 1, &var
));
160 } while (*cp
&& *cp
!= ')');
162 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
167 if (strncmp (cp
, "defined", 7) == 0 && !isalnum(cp
[7])) {
177 DO (cp
= parse_variable (g
, cp
, &var
));
178 len
= (int)(cp
- var
);
180 if (paren
&& *cp
!= ')')
181 return CALLFUNC(g
, handle_error
) (g
, cp
, ")");
182 *valp
= (*(g
->funcs
.eval_defined
)) (g
, var
, len
);
183 return cp
+ paren
; /* skip the right paren */
189 DO (cp
= parse_number (g
, cp
, valp
));
190 } else if (!isvarfirstletter(*cp
))
191 return CALLFUNC(g
, handle_error
) (g
, cp
, "variable or number");
193 DO (cp
= parse_variable (g
, cp
, &var
));
194 *valp
= (*(g
->funcs
.eval_variable
)) (g
, var
, cp
- var
);
203 parse_product (g
, cp
, valp
)
210 DO (cp
= parse_value (g
, cp
, valp
));
215 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
216 *valp
= (*valp
* rightval
);
220 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
222 /* Do nothing in the divide-by-zero case. */
224 *valp
= (*valp
/ rightval
);
229 DO (cp
= parse_product (g
, cp
+ 1, &rightval
));
230 *valp
= (*valp
% rightval
);
238 parse_sum (g
, cp
, valp
)
245 DO (cp
= parse_product (g
, cp
, valp
));
250 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
251 *valp
= (*valp
+ rightval
);
255 DO (cp
= parse_sum (g
, cp
+ 1, &rightval
));
256 *valp
= (*valp
- rightval
);
264 parse_shift (g
, cp
, valp
)
271 DO (cp
= parse_sum (g
, cp
, valp
));
277 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
278 *valp
= (*valp
<< rightval
);
284 DO (cp
= parse_shift (g
, cp
+ 2, &rightval
));
285 *valp
= (*valp
>> rightval
);
294 parse_inequality (g
, cp
, valp
)
301 DO (cp
= parse_shift (g
, cp
, valp
));
307 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
308 *valp
= (*valp
<= rightval
);
310 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
311 *valp
= (*valp
< rightval
);
317 DO (cp
= parse_inequality (g
, cp
+ 2, &rightval
));
318 *valp
= (*valp
>= rightval
);
320 DO (cp
= parse_inequality (g
, cp
+ 1, &rightval
));
321 *valp
= (*valp
> rightval
);
330 parse_equality (g
, cp
, valp
)
337 DO (cp
= parse_inequality (g
, cp
, valp
));
344 DO (cp
= parse_equality (g
, cp
+ 1, &rightval
));
345 *valp
= (*valp
== rightval
);
351 DO (cp
= parse_equality (g
, cp
+ 2, &rightval
));
352 *valp
= (*valp
!= rightval
);
360 parse_band (g
, cp
, valp
)
367 DO (cp
= parse_equality (g
, cp
, valp
));
373 DO (cp
= parse_band (g
, cp
+ 1, &rightval
));
374 *valp
= (*valp
& rightval
);
383 parse_bor (g
, cp
, valp
)
390 DO (cp
= parse_band (g
, cp
, valp
));
396 DO (cp
= parse_bor (g
, cp
+ 1, &rightval
));
397 *valp
= (*valp
| rightval
);
406 parse_land (g
, cp
, valp
)
413 DO (cp
= parse_bor (g
, cp
, valp
));
419 return CALLFUNC(g
, handle_error
) (g
, cp
, "&&");
420 DO (cp
= parse_land (g
, cp
+ 2, &rightval
));
421 *valp
= (*valp
&& rightval
);
429 parse_lor (g
, cp
, valp
)
436 DO (cp
= parse_land (g
, cp
, valp
));
442 return CALLFUNC(g
, handle_error
) (g
, cp
, "||");
443 DO (cp
= parse_lor (g
, cp
+ 2, &rightval
));
444 *valp
= (*valp
|| rightval
);
451 /****************************************************************************
452 External Entry Points
453 ****************************************************************************/
456 ParseIfExpression (g
, cp
, valp
)
461 return parse_lor (g
, cp
, valp
);
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */