1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/coreconf/mkdepend/ifparser.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,551 @@ 1.4 +/* 1.5 + * $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $ 1.6 + * 1.7 + * Copyright 1992 Network Computing Devices, Inc. 1.8 + * 1.9 + * Permission to use, copy, modify, and distribute this software and its 1.10 + * documentation for any purpose and without fee is hereby granted, provided 1.11 + * that the above copyright notice appear in all copies and that both that 1.12 + * copyright notice and this permission notice appear in supporting 1.13 + * documentation, and that the name of Network Computing Devices may not be 1.14 + * used in advertising or publicity pertaining to distribution of the software 1.15 + * without specific, written prior permission. Network Computing Devices makes 1.16 + * no representations about the suitability of this software for any purpose. 1.17 + * It is provided ``as is'' without express or implied warranty. 1.18 + * 1.19 + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1.20 + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, 1.21 + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, 1.22 + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1.23 + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 1.24 + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1.25 + * PERFORMANCE OF THIS SOFTWARE. 1.26 + * 1.27 + * Author: Jim Fulton 1.28 + * Network Computing Devices, Inc. 1.29 + * 1.30 + * Simple if statement processor 1.31 + * 1.32 + * This module can be used to evaluate string representations of C language 1.33 + * if constructs. It accepts the following grammar: 1.34 + * 1.35 + * EXPRESSION := VALUE 1.36 + * | VALUE BINOP EXPRESSION 1.37 + * | VALUE '?' EXPRESSION ':' EXPRESSION 1.38 + * 1.39 + * VALUE := '(' EXPRESSION ')' 1.40 + * | '!' VALUE 1.41 + * | '-' VALUE 1.42 + * | '+' VALUE 1.43 + * | '~' VALUE 1.44 + * | 'defined' '(' variable ')' 1.45 + * | 'defined' variable 1.46 + * | # variable '(' variable-list ')' 1.47 + * | variable 1.48 + * | number 1.49 + * 1.50 + * BINOP := '*' | '/' | '%' 1.51 + * | '+' | '-' 1.52 + * | '<<' | '>>' 1.53 + * | '<' | '>' | '<=' | '>=' 1.54 + * | '==' | '!=' 1.55 + * | '&' | '^' | '|' 1.56 + * | '&&' | '||' 1.57 + * 1.58 + * The normal C order of precedence is supported. 1.59 + * 1.60 + * 1.61 + * External Entry Points: 1.62 + * 1.63 + * ParseIfExpression parse a string for #if 1.64 + */ 1.65 +/* $XFree86: xc/config/makedepend/ifparser.c,v 3.11 2002/09/23 01:48:08 tsi Exp $ */ 1.66 + 1.67 +#include "ifparser.h" 1.68 +#include <ctype.h> 1.69 +#include <stdlib.h> 1.70 +#include <string.h> 1.71 + 1.72 +/**************************************************************************** 1.73 + Internal Macros and Utilities for Parser 1.74 + ****************************************************************************/ 1.75 + 1.76 +#define DO(val) if (!(val)) return NULL 1.77 +#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff)) 1.78 +#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++ 1.79 +#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_') 1.80 + 1.81 + 1.82 +static const char * 1.83 +parse_variable (IfParser *g, const char *cp, const char **varp) 1.84 +{ 1.85 + SKIPSPACE (cp); 1.86 + 1.87 + if (!isvarfirstletter (*cp)) 1.88 + return CALLFUNC(g, handle_error) (g, cp, "variable name"); 1.89 + 1.90 + *varp = cp; 1.91 + /* EMPTY */ 1.92 + for (cp++; isalnum(*cp) || *cp == '_'; cp++) ; 1.93 + return cp; 1.94 +} 1.95 + 1.96 + 1.97 +static const char * 1.98 +parse_number (IfParser *g, const char *cp, long *valp) 1.99 +{ 1.100 + long base = 10; 1.101 + SKIPSPACE (cp); 1.102 + 1.103 + if (!isdigit(*cp)) 1.104 + return CALLFUNC(g, handle_error) (g, cp, "number"); 1.105 + 1.106 + *valp = 0; 1.107 + 1.108 + if (*cp == '0') { 1.109 + cp++; 1.110 + if ((*cp == 'x') || (*cp == 'X')) { 1.111 + base = 16; 1.112 + cp++; 1.113 + } else { 1.114 + base = 8; 1.115 + } 1.116 + } 1.117 + 1.118 + /* Ignore overflows and assume ASCII, what source is usually written in */ 1.119 + while (1) { 1.120 + int increment = -1; 1.121 + if (base == 8) { 1.122 + if ((*cp >= '0') && (*cp <= '7')) 1.123 + increment = *cp++ - '0'; 1.124 + } else if (base == 16) { 1.125 + if ((*cp >= '0') && (*cp <= '9')) 1.126 + increment = *cp++ - '0'; 1.127 + else if ((*cp >= 'A') && (*cp <= 'F')) 1.128 + increment = *cp++ - ('A' - 10); 1.129 + else if ((*cp >= 'a') && (*cp <= 'f')) 1.130 + increment = *cp++ - ('a' - 10); 1.131 + } else { /* Decimal */ 1.132 + if ((*cp >= '0') && (*cp <= '9')) 1.133 + increment = *cp++ - '0'; 1.134 + } 1.135 + if (increment < 0) 1.136 + break; 1.137 + *valp = (*valp * base) + increment; 1.138 + } 1.139 + 1.140 + /* Skip trailing qualifiers */ 1.141 + while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++; 1.142 + return cp; 1.143 +} 1.144 + 1.145 +static const char * 1.146 +parse_character (IfParser *g, const char *cp, long *valp) 1.147 +{ 1.148 + char val; 1.149 + 1.150 + SKIPSPACE (cp); 1.151 + if (*cp == '\\') 1.152 + switch (cp[1]) { 1.153 + case 'n': val = '\n'; break; 1.154 + case 't': val = '\t'; break; 1.155 + case 'v': val = '\v'; break; 1.156 + case 'b': val = '\b'; break; 1.157 + case 'r': val = '\r'; break; 1.158 + case 'f': val = '\f'; break; 1.159 + case 'a': val = '\a'; break; 1.160 + case '\\': val = '\\'; break; 1.161 + case '?': val = '\?'; break; 1.162 + case '\'': val = '\''; break; 1.163 + case '\"': val = '\"'; break; 1.164 + case 'x': val = (char) strtol (cp + 2, NULL, 16); break; 1.165 + default: val = (char) strtol (cp + 1, NULL, 8); break; 1.166 + } 1.167 + else 1.168 + val = *cp; 1.169 + while (*cp != '\'') cp++; 1.170 + *valp = (long) val; 1.171 + return cp; 1.172 +} 1.173 + 1.174 +static const char * 1.175 +parse_value (IfParser *g, const char *cp, long *valp) 1.176 +{ 1.177 + const char *var, *varend; 1.178 + 1.179 + *valp = 0; 1.180 + 1.181 + SKIPSPACE (cp); 1.182 + if (!*cp) 1.183 + return cp; 1.184 + 1.185 + switch (*cp) { 1.186 + case '(': 1.187 + DO (cp = ParseIfExpression (g, cp + 1, valp)); 1.188 + SKIPSPACE (cp); 1.189 + if (*cp != ')') 1.190 + return CALLFUNC(g, handle_error) (g, cp, ")"); 1.191 + 1.192 + return cp + 1; /* skip the right paren */ 1.193 + 1.194 + case '!': 1.195 + DO (cp = parse_value (g, cp + 1, valp)); 1.196 + *valp = !(*valp); 1.197 + return cp; 1.198 + 1.199 + case '-': 1.200 + DO (cp = parse_value (g, cp + 1, valp)); 1.201 + *valp = -(*valp); 1.202 + return cp; 1.203 + 1.204 + case '+': 1.205 + DO (cp = parse_value (g, cp + 1, valp)); 1.206 + return cp; 1.207 + 1.208 + case '~': 1.209 + DO (cp = parse_value (g, cp + 1, valp)); 1.210 + *valp = ~(*valp); 1.211 + return cp; 1.212 + 1.213 + case '#': 1.214 + DO (cp = parse_variable (g, cp + 1, &var)); 1.215 + SKIPSPACE (cp); 1.216 + if (*cp != '(') 1.217 + return CALLFUNC(g, handle_error) (g, cp, "("); 1.218 + do { 1.219 + DO (cp = parse_variable (g, cp + 1, &var)); 1.220 + SKIPSPACE (cp); 1.221 + } while (*cp && *cp != ')'); 1.222 + if (*cp != ')') 1.223 + return CALLFUNC(g, handle_error) (g, cp, ")"); 1.224 + *valp = 1; /* XXX */ 1.225 + return cp + 1; 1.226 + 1.227 + case '\'': 1.228 + DO (cp = parse_character (g, cp + 1, valp)); 1.229 + if (*cp != '\'') 1.230 + return CALLFUNC(g, handle_error) (g, cp, "'"); 1.231 + return cp + 1; 1.232 + 1.233 + case 'd': 1.234 + if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) { 1.235 + int paren = 0; 1.236 + int len; 1.237 + 1.238 + cp += 7; 1.239 + SKIPSPACE (cp); 1.240 + if (*cp == '(') { 1.241 + paren = 1; 1.242 + cp++; 1.243 + } 1.244 + DO (cp = parse_variable (g, cp, &var)); 1.245 + len = cp - var; 1.246 + SKIPSPACE (cp); 1.247 + if (paren && *cp != ')') 1.248 + return CALLFUNC(g, handle_error) (g, cp, ")"); 1.249 + *valp = (*(g->funcs.eval_defined)) (g, var, len); 1.250 + return cp + paren; /* skip the right paren */ 1.251 + } 1.252 + /* fall out */ 1.253 + } 1.254 + 1.255 + if (isdigit(*cp)) { 1.256 + DO (cp = parse_number (g, cp, valp)); 1.257 + } else if (!isvarfirstletter(*cp)) 1.258 + return CALLFUNC(g, handle_error) (g, cp, "variable or number"); 1.259 + else { 1.260 + DO (cp = parse_variable (g, cp, &var)); 1.261 + varend = cp; 1.262 + SKIPSPACE(cp); 1.263 + if (*cp != '(') { 1.264 + *valp = (*(g->funcs.eval_variable)) (g, var, varend - var); 1.265 + } else { 1.266 + do { 1.267 + long dummy; 1.268 + DO (cp = ParseIfExpression (g, cp + 1, &dummy)); 1.269 + SKIPSPACE(cp); 1.270 + if (*cp == ')') 1.271 + break; 1.272 + if (*cp != ',') 1.273 + return CALLFUNC(g, handle_error) (g, cp, ","); 1.274 + } while (1); 1.275 + 1.276 + *valp = 1; /* XXX */ 1.277 + cp++; 1.278 + } 1.279 + } 1.280 + 1.281 + return cp; 1.282 +} 1.283 + 1.284 + 1.285 + 1.286 +static const char * 1.287 +parse_product (IfParser *g, const char *cp, long *valp) 1.288 +{ 1.289 + long rightval; 1.290 + 1.291 + DO (cp = parse_value (g, cp, valp)); 1.292 + SKIPSPACE (cp); 1.293 + 1.294 + switch (*cp) { 1.295 + case '*': 1.296 + DO (cp = parse_product (g, cp + 1, &rightval)); 1.297 + *valp = (*valp * rightval); 1.298 + break; 1.299 + 1.300 + case '/': 1.301 + DO (cp = parse_product (g, cp + 1, &rightval)); 1.302 + if (rightval == 0) 1.303 + return CALLFUNC(g, handle_error) (g, cp, "0"); 1.304 + *valp = (*valp / rightval); 1.305 + break; 1.306 + 1.307 + case '%': 1.308 + DO (cp = parse_product (g, cp + 1, &rightval)); 1.309 + *valp = (*valp % rightval); 1.310 + break; 1.311 + } 1.312 + return cp; 1.313 +} 1.314 + 1.315 + 1.316 +static const char * 1.317 +parse_sum (IfParser *g, const char *cp, long *valp) 1.318 +{ 1.319 + long rightval; 1.320 + 1.321 + DO (cp = parse_product (g, cp, valp)); 1.322 + SKIPSPACE (cp); 1.323 + 1.324 + switch (*cp) { 1.325 + case '+': 1.326 + DO (cp = parse_sum (g, cp + 1, &rightval)); 1.327 + *valp = (*valp + rightval); 1.328 + break; 1.329 + 1.330 + case '-': 1.331 + DO (cp = parse_sum (g, cp + 1, &rightval)); 1.332 + *valp = (*valp - rightval); 1.333 + break; 1.334 + } 1.335 + return cp; 1.336 +} 1.337 + 1.338 + 1.339 +static const char * 1.340 +parse_shift (IfParser *g, const char *cp, long *valp) 1.341 +{ 1.342 + long rightval; 1.343 + 1.344 + DO (cp = parse_sum (g, cp, valp)); 1.345 + SKIPSPACE (cp); 1.346 + 1.347 + switch (*cp) { 1.348 + case '<': 1.349 + if (cp[1] == '<') { 1.350 + DO (cp = parse_shift (g, cp + 2, &rightval)); 1.351 + *valp = (*valp << rightval); 1.352 + } 1.353 + break; 1.354 + 1.355 + case '>': 1.356 + if (cp[1] == '>') { 1.357 + DO (cp = parse_shift (g, cp + 2, &rightval)); 1.358 + *valp = (*valp >> rightval); 1.359 + } 1.360 + break; 1.361 + } 1.362 + return cp; 1.363 +} 1.364 + 1.365 + 1.366 +static const char * 1.367 +parse_inequality (IfParser *g, const char *cp, long *valp) 1.368 +{ 1.369 + long rightval; 1.370 + 1.371 + DO (cp = parse_shift (g, cp, valp)); 1.372 + SKIPSPACE (cp); 1.373 + 1.374 + switch (*cp) { 1.375 + case '<': 1.376 + if (cp[1] == '=') { 1.377 + DO (cp = parse_inequality (g, cp + 2, &rightval)); 1.378 + *valp = (*valp <= rightval); 1.379 + } else { 1.380 + DO (cp = parse_inequality (g, cp + 1, &rightval)); 1.381 + *valp = (*valp < rightval); 1.382 + } 1.383 + break; 1.384 + 1.385 + case '>': 1.386 + if (cp[1] == '=') { 1.387 + DO (cp = parse_inequality (g, cp + 2, &rightval)); 1.388 + *valp = (*valp >= rightval); 1.389 + } else { 1.390 + DO (cp = parse_inequality (g, cp + 1, &rightval)); 1.391 + *valp = (*valp > rightval); 1.392 + } 1.393 + break; 1.394 + } 1.395 + return cp; 1.396 +} 1.397 + 1.398 + 1.399 +static const char * 1.400 +parse_equality (IfParser *g, const char *cp, long *valp) 1.401 +{ 1.402 + long rightval; 1.403 + 1.404 + DO (cp = parse_inequality (g, cp, valp)); 1.405 + SKIPSPACE (cp); 1.406 + 1.407 + switch (*cp) { 1.408 + case '=': 1.409 + if (cp[1] == '=') 1.410 + cp++; 1.411 + DO (cp = parse_equality (g, cp + 1, &rightval)); 1.412 + *valp = (*valp == rightval); 1.413 + break; 1.414 + 1.415 + case '!': 1.416 + if (cp[1] != '=') 1.417 + break; 1.418 + DO (cp = parse_equality (g, cp + 2, &rightval)); 1.419 + *valp = (*valp != rightval); 1.420 + break; 1.421 + } 1.422 + return cp; 1.423 +} 1.424 + 1.425 + 1.426 +static const char * 1.427 +parse_band (IfParser *g, const char *cp, long *valp) 1.428 +{ 1.429 + long rightval; 1.430 + 1.431 + DO (cp = parse_equality (g, cp, valp)); 1.432 + SKIPSPACE (cp); 1.433 + 1.434 + switch (*cp) { 1.435 + case '&': 1.436 + if (cp[1] != '&') { 1.437 + DO (cp = parse_band (g, cp + 1, &rightval)); 1.438 + *valp = (*valp & rightval); 1.439 + } 1.440 + break; 1.441 + } 1.442 + return cp; 1.443 +} 1.444 + 1.445 + 1.446 +static const char * 1.447 +parse_bxor (IfParser *g, const char *cp, long *valp) 1.448 +{ 1.449 + long rightval; 1.450 + 1.451 + DO (cp = parse_band (g, cp, valp)); 1.452 + SKIPSPACE (cp); 1.453 + 1.454 + switch (*cp) { 1.455 + case '^': 1.456 + DO (cp = parse_bxor (g, cp + 1, &rightval)); 1.457 + *valp = (*valp ^ rightval); 1.458 + break; 1.459 + } 1.460 + return cp; 1.461 +} 1.462 + 1.463 + 1.464 +static const char * 1.465 +parse_bor (IfParser *g, const char *cp, long *valp) 1.466 +{ 1.467 + long rightval; 1.468 + 1.469 + DO (cp = parse_bxor (g, cp, valp)); 1.470 + SKIPSPACE (cp); 1.471 + 1.472 + switch (*cp) { 1.473 + case '|': 1.474 + if (cp[1] != '|') { 1.475 + DO (cp = parse_bor (g, cp + 1, &rightval)); 1.476 + *valp = (*valp | rightval); 1.477 + } 1.478 + break; 1.479 + } 1.480 + return cp; 1.481 +} 1.482 + 1.483 + 1.484 +static const char * 1.485 +parse_land (IfParser *g, const char *cp, long *valp) 1.486 +{ 1.487 + long rightval; 1.488 + 1.489 + DO (cp = parse_bor (g, cp, valp)); 1.490 + SKIPSPACE (cp); 1.491 + 1.492 + switch (*cp) { 1.493 + case '&': 1.494 + if (cp[1] != '&') 1.495 + return CALLFUNC(g, handle_error) (g, cp, "&&"); 1.496 + DO (cp = parse_land (g, cp + 2, &rightval)); 1.497 + *valp = (*valp && rightval); 1.498 + break; 1.499 + } 1.500 + return cp; 1.501 +} 1.502 + 1.503 + 1.504 +static const char * 1.505 +parse_lor (IfParser *g, const char *cp, long *valp) 1.506 +{ 1.507 + long rightval; 1.508 + 1.509 + DO (cp = parse_land (g, cp, valp)); 1.510 + SKIPSPACE (cp); 1.511 + 1.512 + switch (*cp) { 1.513 + case '|': 1.514 + if (cp[1] != '|') 1.515 + return CALLFUNC(g, handle_error) (g, cp, "||"); 1.516 + DO (cp = parse_lor (g, cp + 2, &rightval)); 1.517 + *valp = (*valp || rightval); 1.518 + break; 1.519 + } 1.520 + return cp; 1.521 +} 1.522 + 1.523 + 1.524 +static const char * 1.525 +parse_cond(IfParser *g, const char *cp, long *valp) 1.526 +{ 1.527 + long trueval, falseval; 1.528 + 1.529 + DO (cp = parse_lor (g, cp, valp)); 1.530 + SKIPSPACE (cp); 1.531 + 1.532 + switch (*cp) { 1.533 + case '?': 1.534 + DO (cp = parse_cond (g, cp + 1, &trueval)); 1.535 + SKIPSPACE (cp); 1.536 + if (*cp != ':') 1.537 + return CALLFUNC(g, handle_error) (g, cp, ":"); 1.538 + DO (cp = parse_cond (g, cp + 1, &falseval)); 1.539 + *valp = (*valp ? trueval : falseval); 1.540 + break; 1.541 + } 1.542 + return cp; 1.543 +} 1.544 + 1.545 + 1.546 +/**************************************************************************** 1.547 + External Entry Points 1.548 + ****************************************************************************/ 1.549 + 1.550 +const char * 1.551 +ParseIfExpression (IfParser *g, const char *cp, long *valp) 1.552 +{ 1.553 + return parse_cond (g, cp, valp); 1.554 +}