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.

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

mercurial