security/nss/coreconf/mkdepend/ifparser.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 $ */
    64 #include "ifparser.h"
    65 #include <ctype.h>
    66 #include <stdlib.h>
    67 #include <string.h>
    69 /****************************************************************************
    70 		   Internal Macros and Utilities for Parser
    71  ****************************************************************************/
    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) == '_')
    79 static const char *
    80 parse_variable (IfParser *g, const char *cp, const char **varp)
    81 {
    82     SKIPSPACE (cp);
    84     if (!isvarfirstletter (*cp))
    85 	return CALLFUNC(g, handle_error) (g, cp, "variable name");
    87     *varp = cp;
    88     /* EMPTY */
    89     for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
    90     return cp;
    91 }
    94 static const char *
    95 parse_number (IfParser *g, const char *cp, long *valp)
    96 {
    97     long base = 10;
    98     SKIPSPACE (cp);
   100     if (!isdigit(*cp))
   101 	return CALLFUNC(g, handle_error) (g, cp, "number");
   103     *valp = 0;
   105     if (*cp == '0') {
   106 	cp++;
   107 	if ((*cp == 'x') || (*cp == 'X')) {
   108 	    base = 16;
   109 	    cp++;
   110 	} else {
   111 	    base = 8;
   112 	}
   113     }
   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     }
   137     /* Skip trailing qualifiers */
   138     while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
   139     return cp;
   140 }
   142 static const char *
   143 parse_character (IfParser *g, const char *cp, long *valp)
   144 {
   145     char val;
   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 }
   171 static const char *
   172 parse_value (IfParser *g, const char *cp, long *valp)
   173 {
   174     const char *var, *varend;
   176     *valp = 0;
   178     SKIPSPACE (cp);
   179     if (!*cp)
   180 	return cp;
   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, ")");
   189 	return cp + 1;			/* skip the right paren */
   191       case '!':
   192 	DO (cp = parse_value (g, cp + 1, valp));
   193 	*valp = !(*valp);
   194 	return cp;
   196       case '-':
   197 	DO (cp = parse_value (g, cp + 1, valp));
   198 	*valp = -(*valp);
   199 	return cp;
   201       case '+':
   202 	DO (cp = parse_value (g, cp + 1, valp));
   203 	return cp;
   205       case '~':
   206 	DO (cp = parse_value (g, cp + 1, valp));
   207 	*valp = ~(*valp);
   208 	return cp;
   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;
   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;
   230       case 'd':
   231 	if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
   232 	    int paren = 0;
   233 	    int len;
   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     }
   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);
   273 	    *valp = 1;	/* XXX */
   274 	    cp++;
   275 	}
   276     }
   278     return cp;
   279 }
   283 static const char *
   284 parse_product (IfParser *g, const char *cp, long *valp)
   285 {
   286     long rightval;
   288     DO (cp = parse_value (g, cp, valp));
   289     SKIPSPACE (cp);
   291     switch (*cp) {
   292       case '*':
   293 	DO (cp = parse_product (g, cp + 1, &rightval));
   294 	*valp = (*valp * rightval);
   295 	break;
   297       case '/':
   298 	DO (cp = parse_product (g, cp + 1, &rightval));
   299 	if (rightval == 0)
   300 	  return CALLFUNC(g, handle_error) (g, cp, "0");
   301 	*valp = (*valp / rightval);
   302 	break;
   304       case '%':
   305 	DO (cp = parse_product (g, cp + 1, &rightval));
   306 	*valp = (*valp % rightval);
   307 	break;
   308     }
   309     return cp;
   310 }
   313 static const char *
   314 parse_sum (IfParser *g, const char *cp, long *valp)
   315 {
   316     long rightval;
   318     DO (cp = parse_product (g, cp, valp));
   319     SKIPSPACE (cp);
   321     switch (*cp) {
   322       case '+':
   323 	DO (cp = parse_sum (g, cp + 1, &rightval));
   324 	*valp = (*valp + rightval);
   325 	break;
   327       case '-':
   328 	DO (cp = parse_sum (g, cp + 1, &rightval));
   329 	*valp = (*valp - rightval);
   330 	break;
   331     }
   332     return cp;
   333 }
   336 static const char *
   337 parse_shift (IfParser *g, const char *cp, long *valp)
   338 {
   339     long rightval;
   341     DO (cp = parse_sum (g, cp, valp));
   342     SKIPSPACE (cp);
   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;
   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 }
   363 static const char *
   364 parse_inequality (IfParser *g, const char *cp, long *valp)
   365 {
   366     long rightval;
   368     DO (cp = parse_shift (g, cp, valp));
   369     SKIPSPACE (cp);
   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;
   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 }
   396 static const char *
   397 parse_equality (IfParser *g, const char *cp, long *valp)
   398 {
   399     long rightval;
   401     DO (cp = parse_inequality (g, cp, valp));
   402     SKIPSPACE (cp);
   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;
   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 }
   423 static const char *
   424 parse_band (IfParser *g, const char *cp, long *valp)
   425 {
   426     long rightval;
   428     DO (cp = parse_equality (g, cp, valp));
   429     SKIPSPACE (cp);
   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 }
   443 static const char *
   444 parse_bxor (IfParser *g, const char *cp, long *valp)
   445 {
   446     long rightval;
   448     DO (cp = parse_band (g, cp, valp));
   449     SKIPSPACE (cp);
   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 }
   461 static const char *
   462 parse_bor (IfParser *g, const char *cp, long *valp)
   463 {
   464     long rightval;
   466     DO (cp = parse_bxor (g, cp, valp));
   467     SKIPSPACE (cp);
   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 }
   481 static const char *
   482 parse_land (IfParser *g, const char *cp, long *valp)
   483 {
   484     long rightval;
   486     DO (cp = parse_bor (g, cp, valp));
   487     SKIPSPACE (cp);
   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 }
   501 static const char *
   502 parse_lor (IfParser *g, const char *cp, long *valp)
   503 {
   504     long rightval;
   506     DO (cp = parse_land (g, cp, valp));
   507     SKIPSPACE (cp);
   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 }
   521 static const char *
   522 parse_cond(IfParser *g, const char *cp, long *valp)
   523 {
   524     long trueval, falseval;
   526     DO (cp = parse_lor (g, cp, valp));
   527     SKIPSPACE (cp);
   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 }
   543 /****************************************************************************
   544 			     External Entry Points
   545  ****************************************************************************/
   547 const char *
   548 ParseIfExpression (IfParser *g, const char *cp, long *valp)
   549 {
   550     return parse_cond (g, cp, valp);
   551 }

mercurial