update dev300-m58
[ooovba.git] / soltools / mkdepend / ifparser.c
blob2ff372f1efc6c3ffbdb1bf307ce01ee2eae7c08d
1 /*
2 * $XConsortium: ifparser.c,v 1.8 95/06/03 00:01:41 gildea Exp $
4 * Copyright 1992 Network Computing Devices, Inc.
5 *
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.
24 * Author: Jim Fulton
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:
32 * EXPRESSION := VALUE
33 * | VALUE BINOP EXPRESSION
35 * VALUE := '(' EXPRESSION ')'
36 * | '!' VALUE
37 * | '-' VALUE
38 * | 'defined' '(' variable ')'
39 * | 'defined' variable
40 * | # variable '(' variable-list ')'
41 * | variable
42 * | number
44 * BINOP := '*' | '/' | '%'
45 * | '+' | '-'
46 * | '<<' | '>>'
47 * | '<' | '>' | '<=' | '>='
48 * | '==' | '!='
49 * | '&' | '|'
50 * | '&&' | '||'
52 * The normal C order of precidence is supported.
55 * External Entry Points:
57 * ParseIfExpression parse a string for #if
60 #include "ifparser.h"
61 #include <ctype.h>
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) == '_')
73 static const char *
74 parse_variable (g, cp, varp)
75 IfParser *g;
76 const char *cp;
77 const char **varp;
79 SKIPSPACE (cp);
81 if (!isvarfirstletter (*cp))
82 return CALLFUNC(g, handle_error) (g, cp, "variable name");
84 *varp = cp;
85 /* EMPTY */
86 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
87 return cp;
91 static const char *
92 parse_number (g, cp, valp)
93 IfParser *g;
94 const char *cp;
95 int *valp;
97 SKIPSPACE (cp);
99 if (!isdigit(*cp))
100 return CALLFUNC(g, handle_error) (g, cp, "number");
102 #ifdef WIN32
103 *valp = strtol(cp, &cp, 0);
104 #else
105 *valp = atoi (cp);
106 /* EMPTY */
107 for (cp++; isdigit(*cp); cp++) ;
108 #endif
109 return cp;
113 static const char *
114 parse_value (g, cp, valp)
115 IfParser *g;
116 const char *cp;
117 int *valp;
119 const char *var;
121 *valp = 0;
123 SKIPSPACE (cp);
124 if (!*cp)
125 return cp;
127 switch (*cp) {
128 case '(':
129 DO (cp = ParseIfExpression (g, cp + 1, valp));
130 SKIPSPACE (cp);
131 if (*cp != ')')
132 return CALLFUNC(g, handle_error) (g, cp, ")");
134 return cp + 1; /* skip the right paren */
136 case '!':
137 DO (cp = parse_value (g, cp + 1, valp));
138 *valp = !(*valp);
139 return cp;
141 case '-':
142 DO (cp = parse_value (g, cp + 1, valp));
143 *valp = -(*valp);
144 return cp;
146 case '#':
147 DO (cp = parse_variable (g, cp + 1, &var));
148 SKIPSPACE (cp);
149 if (*cp != '(')
150 return CALLFUNC(g, handle_error) (g, cp, "(");
151 do {
152 DO (cp = parse_variable (g, cp + 1, &var));
153 SKIPSPACE (cp);
154 } while (*cp && *cp != ')');
155 if (*cp != ')')
156 return CALLFUNC(g, handle_error) (g, cp, ")");
157 *valp = 1; /* XXX */
158 return cp + 1;
160 case 'd':
161 if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
162 int paren = 0;
163 int len;
165 cp += 7;
166 SKIPSPACE (cp);
167 if (*cp == '(') {
168 paren = 1;
169 cp++;
171 DO (cp = parse_variable (g, cp, &var));
172 len = cp - var;
173 SKIPSPACE (cp);
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 */
179 /* fall out */
182 if (isdigit(*cp)) {
183 DO (cp = parse_number (g, cp, valp));
184 } else if (!isvarfirstletter(*cp))
185 return CALLFUNC(g, handle_error) (g, cp, "variable or number");
186 else {
187 DO (cp = parse_variable (g, cp, &var));
188 *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
191 return cp;
196 static const char *
197 parse_product (g, cp, valp)
198 IfParser *g;
199 const char *cp;
200 int *valp;
202 int rightval;
204 DO (cp = parse_value (g, cp, valp));
205 SKIPSPACE (cp);
207 switch (*cp) {
208 case '*':
209 DO (cp = parse_product (g, cp + 1, &rightval));
210 *valp = (*valp * rightval);
211 break;
213 case '/':
214 DO (cp = parse_product (g, cp + 1, &rightval));
216 /* Do nothing in the divide-by-zero case. */
217 if (rightval) {
218 *valp = (*valp / rightval);
220 break;
222 case '%':
223 DO (cp = parse_product (g, cp + 1, &rightval));
224 *valp = (*valp % rightval);
225 break;
227 return cp;
231 static const char *
232 parse_sum (g, cp, valp)
233 IfParser *g;
234 const char *cp;
235 int *valp;
237 int rightval;
239 DO (cp = parse_product (g, cp, valp));
240 SKIPSPACE (cp);
242 switch (*cp) {
243 case '+':
244 DO (cp = parse_sum (g, cp + 1, &rightval));
245 *valp = (*valp + rightval);
246 break;
248 case '-':
249 DO (cp = parse_sum (g, cp + 1, &rightval));
250 *valp = (*valp - rightval);
251 break;
253 return cp;
257 static const char *
258 parse_shift (g, cp, valp)
259 IfParser *g;
260 const char *cp;
261 int *valp;
263 int rightval;
265 DO (cp = parse_sum (g, cp, valp));
266 SKIPSPACE (cp);
268 switch (*cp) {
269 case '<':
270 if (cp[1] == '<') {
271 DO (cp = parse_shift (g, cp + 2, &rightval));
272 *valp = (*valp << rightval);
274 break;
276 case '>':
277 if (cp[1] == '>') {
278 DO (cp = parse_shift (g, cp + 2, &rightval));
279 *valp = (*valp >> rightval);
281 break;
283 return cp;
287 static const char *
288 parse_inequality (g, cp, valp)
289 IfParser *g;
290 const char *cp;
291 int *valp;
293 int rightval;
295 DO (cp = parse_shift (g, cp, valp));
296 SKIPSPACE (cp);
298 switch (*cp) {
299 case '<':
300 if (cp[1] == '=') {
301 DO (cp = parse_inequality (g, cp + 2, &rightval));
302 *valp = (*valp <= rightval);
303 } else {
304 DO (cp = parse_inequality (g, cp + 1, &rightval));
305 *valp = (*valp < rightval);
307 break;
309 case '>':
310 if (cp[1] == '=') {
311 DO (cp = parse_inequality (g, cp + 2, &rightval));
312 *valp = (*valp >= rightval);
313 } else {
314 DO (cp = parse_inequality (g, cp + 1, &rightval));
315 *valp = (*valp > rightval);
317 break;
319 return cp;
323 static const char *
324 parse_equality (g, cp, valp)
325 IfParser *g;
326 const char *cp;
327 int *valp;
329 int rightval;
331 DO (cp = parse_inequality (g, cp, valp));
332 SKIPSPACE (cp);
334 switch (*cp) {
335 case '=':
336 if (cp[1] == '=')
337 cp++;
338 DO (cp = parse_equality (g, cp + 1, &rightval));
339 *valp = (*valp == rightval);
340 break;
342 case '!':
343 if (cp[1] != '=')
344 break;
345 DO (cp = parse_equality (g, cp + 2, &rightval));
346 *valp = (*valp != rightval);
347 break;
349 return cp;
353 static const char *
354 parse_band (g, cp, valp)
355 IfParser *g;
356 const char *cp;
357 int *valp;
359 int rightval;
361 DO (cp = parse_equality (g, cp, valp));
362 SKIPSPACE (cp);
364 switch (*cp) {
365 case '&':
366 if (cp[1] != '&') {
367 DO (cp = parse_band (g, cp + 1, &rightval));
368 *valp = (*valp & rightval);
370 break;
372 return cp;
376 static const char *
377 parse_bor (g, cp, valp)
378 IfParser *g;
379 const char *cp;
380 int *valp;
382 int rightval;
384 DO (cp = parse_band (g, cp, valp));
385 SKIPSPACE (cp);
387 switch (*cp) {
388 case '|':
389 if (cp[1] != '|') {
390 DO (cp = parse_bor (g, cp + 1, &rightval));
391 *valp = (*valp | rightval);
393 break;
395 return cp;
399 static const char *
400 parse_land (g, cp, valp)
401 IfParser *g;
402 const char *cp;
403 int *valp;
405 int rightval;
407 DO (cp = parse_bor (g, cp, valp));
408 SKIPSPACE (cp);
410 switch (*cp) {
411 case '&':
412 if (cp[1] != '&')
413 return CALLFUNC(g, handle_error) (g, cp, "&&");
414 DO (cp = parse_land (g, cp + 2, &rightval));
415 *valp = (*valp && rightval);
416 break;
418 return cp;
422 static const char *
423 parse_lor (g, cp, valp)
424 IfParser *g;
425 const char *cp;
426 int *valp;
428 int rightval;
430 DO (cp = parse_land (g, cp, valp));
431 SKIPSPACE (cp);
433 switch (*cp) {
434 case '|':
435 if (cp[1] != '|')
436 return CALLFUNC(g, handle_error) (g, cp, "||");
437 DO (cp = parse_lor (g, cp + 2, &rightval));
438 *valp = (*valp || rightval);
439 break;
441 return cp;
445 /****************************************************************************
446 External Entry Points
447 ****************************************************************************/
449 const char *
450 ParseIfExpression (g, cp, valp)
451 IfParser *g;
452 const char *cp;
453 int *valp;
455 return parse_lor (g, cp, valp);