/[jscoverage]/trunk/js/config/mkdepend/ifparser.c
ViewVC logotype

Annotation of /trunk/js/config/mkdepend/ifparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 460 - (hide annotations)
Sat Sep 26 23:15:22 2009 UTC (12 years, 9 months ago) by siliconforks
File MIME type: text/plain
File size: 12313 byte(s)
Upgrade to SpiderMonkey from Firefox 3.5.3.

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

  ViewVC Help
Powered by ViewVC 1.1.24