PageRenderTime 34ms CodeModel.GetById 1ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 1ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C | 549 lines | 391 code | 86 blank | 72 comment | 121 complexity | f30a8546e956a485428846402ca567af MD5 | raw file
  1/*
  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
 79static const char *
 80parse_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
 94static const char *
 95parse_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
142static const char *
143parse_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
171static const char *
172parse_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
283static const char *
284parse_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	*valp = (*valp / rightval);
300	break;
301
302      case '%':
303	DO (cp = parse_product (g, cp + 1, &rightval));
304	*valp = (*valp % rightval);
305	break;
306    }
307    return cp;
308}
309
310
311static const char *
312parse_sum (IfParser *g, const char *cp, long *valp)
313{
314    long rightval;
315
316    DO (cp = parse_product (g, cp, valp));
317    SKIPSPACE (cp);
318
319    switch (*cp) {
320      case '+':
321	DO (cp = parse_sum (g, cp + 1, &rightval));
322	*valp = (*valp + rightval);
323	break;
324
325      case '-':
326	DO (cp = parse_sum (g, cp + 1, &rightval));
327	*valp = (*valp - rightval);
328	break;
329    }
330    return cp;
331}
332
333
334static const char *
335parse_shift (IfParser *g, const char *cp, long *valp)
336{
337    long rightval;
338
339    DO (cp = parse_sum (g, cp, valp));
340    SKIPSPACE (cp);
341
342    switch (*cp) {
343      case '<':
344	if (cp[1] == '<') {
345	    DO (cp = parse_shift (g, cp + 2, &rightval));
346	    *valp = (*valp << rightval);
347	}
348	break;
349
350      case '>':
351	if (cp[1] == '>') {
352	    DO (cp = parse_shift (g, cp + 2, &rightval));
353	    *valp = (*valp >> rightval);
354	}
355	break;
356    }
357    return cp;
358}
359
360
361static const char *
362parse_inequality (IfParser *g, const char *cp, long *valp)
363{
364    long rightval;
365
366    DO (cp = parse_shift (g, cp, valp));
367    SKIPSPACE (cp);
368
369    switch (*cp) {
370      case '<':
371	if (cp[1] == '=') {
372	    DO (cp = parse_inequality (g, cp + 2, &rightval));
373	    *valp = (*valp <= rightval);
374	} else {
375	    DO (cp = parse_inequality (g, cp + 1, &rightval));
376	    *valp = (*valp < rightval);
377	}
378	break;
379
380      case '>':
381	if (cp[1] == '=') {
382	    DO (cp = parse_inequality (g, cp + 2, &rightval));
383	    *valp = (*valp >= rightval);
384	} else {
385	    DO (cp = parse_inequality (g, cp + 1, &rightval));
386	    *valp = (*valp > rightval);
387	}
388	break;
389    }
390    return cp;
391}
392
393
394static const char *
395parse_equality (IfParser *g, const char *cp, long *valp)
396{
397    long rightval;
398
399    DO (cp = parse_inequality (g, cp, valp));
400    SKIPSPACE (cp);
401
402    switch (*cp) {
403      case '=':
404	if (cp[1] == '=')
405	    cp++;
406	DO (cp = parse_equality (g, cp + 1, &rightval));
407	*valp = (*valp == rightval);
408	break;
409
410      case '!':
411	if (cp[1] != '=')
412	    break;
413	DO (cp = parse_equality (g, cp + 2, &rightval));
414	*valp = (*valp != rightval);
415	break;
416    }
417    return cp;
418}
419
420
421static const char *
422parse_band (IfParser *g, const char *cp, long *valp)
423{
424    long rightval;
425
426    DO (cp = parse_equality (g, cp, valp));
427    SKIPSPACE (cp);
428
429    switch (*cp) {
430      case '&':
431	if (cp[1] != '&') {
432	    DO (cp = parse_band (g, cp + 1, &rightval));
433	    *valp = (*valp & rightval);
434	}
435	break;
436    }
437    return cp;
438}
439
440
441static const char *
442parse_bxor (IfParser *g, const char *cp, long *valp)
443{
444    long rightval;
445
446    DO (cp = parse_band (g, cp, valp));
447    SKIPSPACE (cp);
448
449    switch (*cp) {
450      case '^':
451	DO (cp = parse_bxor (g, cp + 1, &rightval));
452	*valp = (*valp ^ rightval);
453	break;
454    }
455    return cp;
456}
457
458
459static const char *
460parse_bor (IfParser *g, const char *cp, long *valp)
461{
462    long rightval;
463
464    DO (cp = parse_bxor (g, cp, valp));
465    SKIPSPACE (cp);
466
467    switch (*cp) {
468      case '|':
469	if (cp[1] != '|') {
470	    DO (cp = parse_bor (g, cp + 1, &rightval));
471	    *valp = (*valp | rightval);
472	}
473	break;
474    }
475    return cp;
476}
477
478
479static const char *
480parse_land (IfParser *g, const char *cp, long *valp)
481{
482    long rightval;
483
484    DO (cp = parse_bor (g, cp, valp));
485    SKIPSPACE (cp);
486
487    switch (*cp) {
488      case '&':
489	if (cp[1] != '&')
490	    return CALLFUNC(g, handle_error) (g, cp, "&&");
491	DO (cp = parse_land (g, cp + 2, &rightval));
492	*valp = (*valp && rightval);
493	break;
494    }
495    return cp;
496}
497
498
499static const char *
500parse_lor (IfParser *g, const char *cp, long *valp)
501{
502    long rightval;
503
504    DO (cp = parse_land (g, cp, valp));
505    SKIPSPACE (cp);
506
507    switch (*cp) {
508      case '|':
509	if (cp[1] != '|')
510	    return CALLFUNC(g, handle_error) (g, cp, "||");
511	DO (cp = parse_lor (g, cp + 2, &rightval));
512	*valp = (*valp || rightval);
513	break;
514    }
515    return cp;
516}
517
518
519static const char *
520parse_cond(IfParser *g, const char *cp, long *valp)
521{
522    long trueval, falseval;
523
524    DO (cp = parse_lor (g, cp, valp));
525    SKIPSPACE (cp);
526
527    switch (*cp) {
528      case '?':
529	DO (cp = parse_cond (g, cp + 1, &trueval));
530	SKIPSPACE (cp);
531	if (*cp != ':')
532	    return CALLFUNC(g, handle_error) (g, cp, ":");
533	DO (cp = parse_cond (g, cp + 1, &falseval));
534	*valp = (*valp ? trueval : falseval);
535	break;
536    }
537    return cp;
538}
539
540
541/****************************************************************************
542			     External Entry Points
543 ****************************************************************************/
544
545const char *
546ParseIfExpression (IfParser *g, const char *cp, long *valp)
547{
548    return parse_cond (g, cp, valp);
549}