Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
ifparser.c
Go to the documentation of this file.
1/*
2 * $XConsortium: ifparser.c /main/10 1996/09/28 16:15:18 rws $
3 * $XFree86: xc/config/makedepend/ifparser.c,v 3.6 1996/12/30 13:57:55 dawes Exp $
4 *
5 * Copyright 1992 Network Computing Devices, Inc.
6 *
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.
16 *
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.
24 *
25 * Author: Jim Fulton
26 * Network Computing Devices, Inc.
27 *
28 * Simple if statement processor
29 *
30 * This module can be used to evaluate string representations of C language
31 * if constructs. It accepts the following grammar:
32 *
33 * EXPRESSION := VALUE
34 * | VALUE BINOP EXPRESSION
35 * | VALUE '?' EXPRESSION ':' EXPRESSION
36 *
37 * VALUE := '(' EXPRESSION ')'
38 * | '!' VALUE
39 * | '-' VALUE
40 * | '~' VALUE
41 * | 'defined' '(' variable ')'
42 * | 'defined' variable
43 * | # variable '(' variable-list ')'
44 * | variable
45 * | number
46 *
47 * BINOP := '*' | '/' | '%'
48 * | '+' | '-'
49 * | '<<' | '>>'
50 * | '<' | '>' | '<=' | '>='
51 * | '==' | '!='
52 * | '&' | '^' | '|'
53 * | '&&' | '||'
54 *
55 * The normal C order of precedence is supported.
56 *
57 *
58 * External Entry Points:
59 *
60 * ParseIfExpression parse a string for #if
61 */
62
63#include "ifparser.h"
64#include <ctype.h>
65#include <stdlib.h>
66#include <string.h>
67
68/****************************************************************************
69 Internal Macros and Utilities for Parser
70 ****************************************************************************/
71
72#define DO(val) if (!(val)) return NULL
73#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
74#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
75#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
76
77static const char *parse_variable(IfParser *g, const char *cp, const char **varp)
78{
79 SKIPSPACE(cp);
80
81 if (!isvarfirstletter(*cp))
82 return CALLFUNC(g, handle_error)(g, cp, "variable name");
83
84 *varp = cp;
85 /* EMPTY */
86 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
87 return cp;
88}
89
90static const char *parse_number(IfParser *g, const char *cp, long *valp)
91{
92 SKIPSPACE(cp);
93
94 if (!isdigit(*cp))
95 return CALLFUNC(g, handle_error)(g, cp, "number");
96
97 char *endp;
98 *valp = strtol(cp, &endp, 0);
99 cp = endp;
100 /* skip trailing qualifiers */
101 while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
102#if 0
103 *valp = atoi(cp);
104 /* EMPTY */
105 for (cp++; isdigit(*cp); cp++) ;
106#endif
107 return cp;
108}
109
110static const char *parse_character(IfParser *g, const char *cp, long *valp)
111{
112 char val;
113 if (g) { } /* use argument */
114
115 SKIPSPACE(cp);
116 if (*cp == '\\')
117 switch (cp[1]) {
118 case 'n':
119 val = '\n';
120 break;
121 case 't':
122 val = '\t';
123 break;
124 case 'v':
125 val = '\v';
126 break;
127 case 'b':
128 val = '\b';
129 break;
130 case 'r':
131 val = '\r';
132 break;
133 case 'f':
134 val = '\f';
135 break;
136 case 'a':
137 val = '\a';
138 break;
139 case '\\':
140 val = '\\';
141 break;
142 case '?':
143 val = '\?';
144 break;
145 case '\'':
146 val = '\'';
147 break;
148 case '\"':
149 val = '\"';
150 break;
151 case 'x':
152 val = (char) strtol(cp + 2, NULL, 16);
153 break;
154 default:
155 val = (char) strtol(cp + 1, NULL, 8);
156 break;
157 }
158 else
159 val = *cp;
160 while (*cp != '\'') cp++;
161 *valp = (long) val;
162 return cp;
163}
164
165static const char *parse_value(IfParser *g, const char *cp, long *valp)
166{
167 const char *var;
168
169 *valp = 0;
170 var = 0;
171
172 SKIPSPACE(cp);
173 if (!*cp)
174 return cp;
175
176 switch (*cp) {
177 case '(':
178 DO(cp = ParseIfExpression(g, cp + 1, valp));
179 SKIPSPACE(cp);
180 if (*cp != ')')
181 return CALLFUNC(g, handle_error)(g, cp, ")");
182
183 return cp + 1; /* skip the right paren */
184
185 case '!':
186 DO(cp = parse_value(g, cp + 1, valp));
187 *valp = !(*valp);
188 return cp;
189
190 case '-':
191 DO(cp = parse_value(g, cp + 1, valp));
192 *valp = -(*valp);
193 return cp;
194
195 case '~':
196 DO(cp = parse_value(g, cp + 1, valp));
197 *valp = ~(*valp);
198 return cp;
199
200 case '#':
201 DO(cp = parse_variable(g, cp + 1, &var));
202 SKIPSPACE(cp);
203 if (*cp != '(')
204 return CALLFUNC(g, handle_error)(g, cp, "(");
205 do {
206 DO(cp = parse_variable(g, cp + 1, &var));
207 SKIPSPACE(cp);
208 } while (*cp && *cp != ')');
209 if (*cp != ')')
210 return CALLFUNC(g, handle_error)(g, cp, ")");
211 *valp = 1; /* XXX */
212 return cp + 1;
213
214 case '\'':
215 DO(cp = parse_character(g, cp + 1, valp));
216 if (*cp != '\'')
217 return CALLFUNC(g, handle_error)(g, cp, "'");
218 return cp + 1;
219
220 case 'd':
221 if (strncmp(cp, "defined", 7) == 0 && !isalnum(cp[7])) {
222 int paren = 0;
223 int len;
224
225 cp += 7;
226 SKIPSPACE(cp);
227 if (*cp == '(') {
228 paren = 1;
229 cp++;
230 }
231 DO(cp = parse_variable(g, cp, &var));
232 len = cp - var;
233 SKIPSPACE(cp);
234 if (paren && *cp != ')')
235 return CALLFUNC(g, handle_error)(g, cp, ")");
236 *valp = (*(g->funcs.eval_defined))(g, var, len);
237 return cp + paren; /* skip the right paren */
238 }
239 /* fall out */
240 case '_':
241 if (strncmp(cp, "__has_", 6) == 0) {
242 cp += 6;
243 while (isalnum(*cp) || *cp == '_')
244 ++cp;
245
246 int paren = 0;
247 SKIPSPACE(cp);
248 if (*cp == '(') {
249 paren = 1;
250 cp++;
251 }
252 DO(cp = parse_variable(g, cp, &var));
253 SKIPSPACE(cp);
254 if (paren && *cp != ')')
255 return CALLFUNC(g, handle_error)(g, cp, ")");
256 *valp = 0; /* no features / attributes by default */
257 return cp + paren; /* skip the right paren */
258 } else if (strncmp(cp, "__GNUC_PREREQ", 13) == 0 && (cp += 7)) {
259 cp += 13;
260 while (*cp != '(' && *cp) ++cp;
261 while (*cp != ')' && *cp) ++cp;
262 *valp = 0; // assume old GCC
263 return cp;
264 }
265
266 /* fall out */
267 }
268
269 if (isdigit(*cp)) {
270 DO(cp = parse_number(g, cp, valp));
271 } else if (!isvarfirstletter(*cp))
272 return CALLFUNC(g, handle_error)(g, cp, "variable or number");
273 else {
274 DO(cp = parse_variable(g, cp, &var));
275 *valp = (*(g->funcs.eval_variable))(g, var, cp - var);
276 }
277
278 return cp;
279}
280
281static const char *parse_product(IfParser *g, const char *cp, long *valp)
282{
283 long rightval;
284
285 DO(cp = parse_value(g, cp, valp));
286 SKIPSPACE(cp);
287
288 switch (*cp) {
289 case '*':
290 DO(cp = parse_product(g, cp + 1, &rightval));
291 *valp = (*valp * rightval);
292 break;
293
294 case '/':
295 DO(cp = parse_product(g, cp + 1, &rightval));
296 if (rightval)
297 *valp = (*valp / rightval);
298 break;
299
300 case '%':
301 DO(cp = parse_product(g, cp + 1, &rightval));
302 if (rightval)
303 *valp = (*valp % rightval);
304 break;
305 }
306 return cp;
307}
308
309static const char *parse_sum(IfParser *g, const char *cp, long *valp)
310{
311 long rightval;
312
313 DO(cp = parse_product(g, cp, valp));
314 SKIPSPACE(cp);
315
316 switch (*cp) {
317 case '+':
318 DO(cp = parse_sum(g, cp + 1, &rightval));
319 *valp = (*valp + rightval);
320 break;
321
322 case '-':
323 DO(cp = parse_sum(g, cp + 1, &rightval));
324 *valp = (*valp - rightval);
325 break;
326 }
327 return cp;
328}
329
330static const char *parse_shift(IfParser *g, const char *cp, long *valp)
331{
332 long rightval;
333
334 DO(cp = parse_sum(g, cp, valp));
335 SKIPSPACE(cp);
336
337 switch (*cp) {
338 case '<':
339 if (cp[1] == '<') {
340 DO(cp = parse_shift(g, cp + 2, &rightval));
341 *valp = (*valp << rightval);
342 }
343 break;
344
345 case '>':
346 if (cp[1] == '>') {
347 DO(cp = parse_shift(g, cp + 2, &rightval));
348 *valp = (*valp >> rightval);
349 }
350 break;
351 }
352 return cp;
353}
354
355static const char *parse_inequality(IfParser *g, const char *cp, long *valp)
356{
357 long rightval;
358
359 DO(cp = parse_shift(g, cp, valp));
360 SKIPSPACE(cp);
361
362 switch (*cp) {
363 case '<':
364 if (cp[1] == '=') {
365 DO(cp = parse_inequality(g, cp + 2, &rightval));
366 *valp = (*valp <= rightval);
367 } else {
368 DO(cp = parse_inequality(g, cp + 1, &rightval));
369 *valp = (*valp < rightval);
370 }
371 break;
372
373 case '>':
374 if (cp[1] == '=') {
375 DO(cp = parse_inequality(g, cp + 2, &rightval));
376 *valp = (*valp >= rightval);
377 } else {
378 DO(cp = parse_inequality(g, cp + 1, &rightval));
379 *valp = (*valp > rightval);
380 }
381 break;
382 }
383 return cp;
384}
385
386static const char *parse_equality(IfParser *g, const char *cp, long *valp)
387{
388 long rightval;
389
390 DO(cp = parse_inequality(g, cp, valp));
391 SKIPSPACE(cp);
392
393 switch (*cp) {
394 case '=':
395 if (cp[1] == '=')
396 cp++;
397 DO(cp = parse_equality(g, cp + 1, &rightval));
398 *valp = (*valp == rightval);
399 break;
400
401 case '!':
402 if (cp[1] != '=')
403 break;
404 DO(cp = parse_equality(g, cp + 2, &rightval));
405 *valp = (*valp != rightval);
406 break;
407 }
408 return cp;
409}
410
411static const char *parse_band(IfParser *g, const char *cp, long *valp)
412{
413 long rightval;
414
415 DO(cp = parse_equality(g, cp, valp));
416 SKIPSPACE(cp);
417
418 switch (*cp) {
419 case '&':
420 if (cp[1] != '&') {
421 DO(cp = parse_band(g, cp + 1, &rightval));
422 *valp = (*valp & rightval);
423 }
424 break;
425 }
426 return cp;
427}
428
429static const char *parse_bxor(IfParser *g, const char *cp, long *valp)
430{
431 long rightval;
432
433 DO(cp = parse_band(g, cp, valp));
434 SKIPSPACE(cp);
435
436 switch (*cp) {
437 case '^':
438 DO(cp = parse_bxor(g, cp + 1, &rightval));
439 *valp = (*valp ^ rightval);
440 break;
441 }
442 return cp;
443}
444
445static const char *parse_bor(IfParser *g, const char *cp, long *valp)
446{
447 long rightval;
448
449 DO(cp = parse_bxor(g, cp, valp));
450 SKIPSPACE(cp);
451
452 switch (*cp) {
453 case '|':
454 if (cp[1] != '|') {
455 DO(cp = parse_bor(g, cp + 1, &rightval));
456 *valp = (*valp | rightval);
457 }
458 break;
459 }
460 return cp;
461}
462
463static const char *parse_land(IfParser *g, const char *cp, long *valp)
464{
465 long rightval;
466
467 DO(cp = parse_bor(g, cp, valp));
468 SKIPSPACE(cp);
469
470 switch (*cp) {
471 case '&':
472 if (cp[1] != '&')
473 return CALLFUNC(g, handle_error)(g, cp, "&&");
474 DO(cp = parse_land(g, cp + 2, &rightval));
475 *valp = (*valp && rightval);
476 break;
477 }
478 return cp;
479}
480
481static const char *parse_lor(IfParser *g, const char *cp, long *valp)
482{
483 long rightval;
484
485 DO(cp = parse_land(g, cp, valp));
486 SKIPSPACE(cp);
487
488 switch (*cp) {
489 case '|':
490 if (cp[1] != '|')
491 return CALLFUNC(g, handle_error)(g, cp, "||");
492 DO(cp = parse_lor(g, cp + 2, &rightval));
493 *valp = (*valp || rightval);
494 break;
495 }
496 return cp;
497}
498
499static const char *parse_cond(IfParser *g, const char *cp, long *valp)
500{
501 long trueval, falseval;
502
503 DO(cp = parse_lor(g, cp, valp));
504 SKIPSPACE(cp);
505
506 switch (*cp) {
507 case '?':
508 DO(cp = parse_cond(g, cp + 1, &trueval));
509 SKIPSPACE(cp);
510 if (*cp != ':')
511 return CALLFUNC(g, handle_error)(g, cp, ":");
512 DO(cp = parse_cond(g, cp + 1, &falseval));
513 *valp = (*valp ? trueval : falseval);
514 break;
515 }
516 return cp;
517}
518
519
520/****************************************************************************
521 External Entry Points
522 ****************************************************************************/
523
524const char *ParseIfExpression(IfParser *g, const char *cp, long *valp)
525{
526 return parse_cond(g, cp, valp);
527}
#define g(i)
Definition RSha256.hxx:105
#define NULL
Definition ZInflate.c:15
static const char * parse_variable(IfParser *g, const char *cp, const char **varp)
Definition ifparser.c:77
#define DO(val)
Definition ifparser.c:72
static const char * parse_shift(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:330
static const char * parse_bor(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:445
static const char * parse_number(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:90
#define isvarfirstletter(ccc)
Definition ifparser.c:75
static const char * parse_product(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:281
static const char * parse_equality(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:386
#define CALLFUNC(ggg, fff)
Definition ifparser.c:73
static const char * parse_bxor(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:429
static const char * parse_cond(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:499
static const char * parse_value(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:165
static const char * parse_sum(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:309
static const char * parse_band(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:411
static const char * parse_land(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:463
static const char * parse_lor(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:481
#define SKIPSPACE(ccc)
Definition ifparser.c:74
static const char * parse_inequality(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:355
static const char * parse_character(IfParser *g, const char *cp, long *valp)
Definition ifparser.c:110
const char * ParseIfExpression()
struct _if_parser IfParser