cond.c revision 49938
1/* 2 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 3 * Copyright (c) 1988, 1989 by Adam de Boor 4 * Copyright (c) 1989 by Berkeley Softworks 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id: cond.c,v 1.9 1999/08/12 13:30:08 hoek Exp $ 39 */ 40 41#ifndef lint 42#if 0 43static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; 44#else 45static const char rcsid[] = 46 "$Id"; 47#endif 48#endif /* not lint */ 49 50/*- 51 * cond.c -- 52 * Functions to handle conditionals in a makefile. 53 * 54 * Interface: 55 * Cond_Eval Evaluate the conditional in the passed line. 56 * 57 */ 58 59#include <ctype.h> 60#include <math.h> 61#include "make.h" 62#include "hash.h" 63#include "dir.h" 64#include "buf.h" 65 66/* 67 * The parsing of conditional expressions is based on this grammar: 68 * E -> F || E 69 * E -> F 70 * F -> T && F 71 * F -> T 72 * T -> defined(variable) 73 * T -> make(target) 74 * T -> exists(file) 75 * T -> empty(varspec) 76 * T -> target(name) 77 * T -> symbol 78 * T -> $(varspec) op value 79 * T -> $(varspec) == "string" 80 * T -> $(varspec) != "string" 81 * T -> ( E ) 82 * T -> ! T 83 * op -> == | != | > | < | >= | <= 84 * 85 * 'symbol' is some other symbol to which the default function (condDefProc) 86 * is applied. 87 * 88 * Tokens are scanned from the 'condExpr' string. The scanner (CondToken) 89 * will return And for '&' and '&&', Or for '|' and '||', Not for '!', 90 * LParen for '(', RParen for ')' and will evaluate the other terminal 91 * symbols, using either the default function or the function given in the 92 * terminal, and return the result as either True or False. 93 * 94 * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. 95 */ 96typedef enum { 97 And, Or, Not, True, False, LParen, RParen, EndOfFile, None, Err 98} Token; 99 100/*- 101 * Structures to handle elegantly the different forms of #if's. The 102 * last two fields are stored in condInvert and condDefProc, respectively. 103 */ 104static void CondPushBack __P((Token)); 105static int CondGetArg __P((char **, char **, char *, Boolean)); 106static Boolean CondDoDefined __P((int, char *)); 107static int CondStrMatch __P((ClientData, ClientData)); 108static Boolean CondDoMake __P((int, char *)); 109static Boolean CondDoExists __P((int, char *)); 110static Boolean CondDoTarget __P((int, char *)); 111static char * CondCvtArg __P((char *, double *)); 112static Token CondToken __P((Boolean)); 113static Token CondT __P((Boolean)); 114static Token CondF __P((Boolean)); 115static Token CondE __P((Boolean)); 116 117static struct If { 118 char *form; /* Form of if */ 119 int formlen; /* Length of form */ 120 Boolean doNot; /* TRUE if default function should be negated */ 121 Boolean (*defProc) __P((int, char *)); /* Default function to apply */ 122} ifs[] = { 123 { "ifdef", 5, FALSE, CondDoDefined }, 124 { "ifndef", 6, TRUE, CondDoDefined }, 125 { "ifmake", 6, FALSE, CondDoMake }, 126 { "ifnmake", 7, TRUE, CondDoMake }, 127 { "if", 2, FALSE, CondDoDefined }, 128 { NULL, 0, FALSE, NULL } 129}; 130 131static Boolean condInvert; /* Invert the default function */ 132static Boolean (*condDefProc) /* Default function to apply */ 133 __P((int, char *)); 134static char *condExpr; /* The expression to parse */ 135static Token condPushBack=None; /* Single push-back token used in 136 * parsing */ 137 138#define MAXIF 30 /* greatest depth of #if'ing */ 139 140static Boolean condStack[MAXIF]; /* Stack of conditionals's values */ 141static int condTop = MAXIF; /* Top-most conditional */ 142static int skipIfLevel=0; /* Depth of skipped conditionals */ 143static Boolean skipLine = FALSE; /* Whether the parse module is skipping 144 * lines */ 145 146/*- 147 *----------------------------------------------------------------------- 148 * CondPushBack -- 149 * Push back the most recent token read. We only need one level of 150 * this, so the thing is just stored in 'condPushback'. 151 * 152 * Results: 153 * None. 154 * 155 * Side Effects: 156 * condPushback is overwritten. 157 * 158 *----------------------------------------------------------------------- 159 */ 160static void 161CondPushBack (t) 162 Token t; /* Token to push back into the "stream" */ 163{ 164 condPushBack = t; 165} 166 167/*- 168 *----------------------------------------------------------------------- 169 * CondGetArg -- 170 * Find the argument of a built-in function. 171 * 172 * Results: 173 * The length of the argument and the address of the argument. 174 * 175 * Side Effects: 176 * The pointer is set to point to the closing parenthesis of the 177 * function call. 178 * 179 *----------------------------------------------------------------------- 180 */ 181static int 182CondGetArg (linePtr, argPtr, func, parens) 183 char **linePtr; 184 char **argPtr; 185 char *func; 186 Boolean parens; /* TRUE if arg should be bounded by parens */ 187{ 188 register char *cp; 189 int argLen; 190 register Buffer buf; 191 192 cp = *linePtr; 193 if (parens) { 194 while (*cp != '(' && *cp != '\0') { 195 cp++; 196 } 197 if (*cp == '(') { 198 cp++; 199 } 200 } 201 202 if (*cp == '\0') { 203 /* 204 * No arguments whatsoever. Because 'make' and 'defined' aren't really 205 * "reserved words", we don't print a message. I think this is better 206 * than hitting the user with a warning message every time s/he uses 207 * the word 'make' or 'defined' at the beginning of a symbol... 208 */ 209 *argPtr = cp; 210 return (0); 211 } 212 213 while (*cp == ' ' || *cp == '\t') { 214 cp++; 215 } 216 217 /* 218 * Create a buffer for the argument and start it out at 16 characters 219 * long. Why 16? Why not? 220 */ 221 buf = Buf_Init(16); 222 223 while ((strchr(" \t)&|", *cp) == (char *)NULL) && (*cp != '\0')) { 224 if (*cp == '$') { 225 /* 226 * Parse the variable spec and install it as part of the argument 227 * if it's valid. We tell Var_Parse to complain on an undefined 228 * variable, so we don't do it too. Nor do we return an error, 229 * though perhaps we should... 230 */ 231 char *cp2; 232 int len; 233 Boolean doFree; 234 235 cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree); 236 237 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 238 if (doFree) { 239 free(cp2); 240 } 241 cp += len; 242 } else { 243 Buf_AddByte(buf, (Byte)*cp); 244 cp++; 245 } 246 } 247 248 Buf_AddByte(buf, (Byte)'\0'); 249 *argPtr = (char *)Buf_GetAll(buf, &argLen); 250 Buf_Destroy(buf, FALSE); 251 252 while (*cp == ' ' || *cp == '\t') { 253 cp++; 254 } 255 if (parens && *cp != ')') { 256 Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()", 257 func); 258 return (0); 259 } else if (parens) { 260 /* 261 * Advance pointer past close parenthesis. 262 */ 263 cp++; 264 } 265 266 *linePtr = cp; 267 return (argLen); 268} 269 270/*- 271 *----------------------------------------------------------------------- 272 * CondDoDefined -- 273 * Handle the 'defined' function for conditionals. 274 * 275 * Results: 276 * TRUE if the given variable is defined. 277 * 278 * Side Effects: 279 * None. 280 * 281 *----------------------------------------------------------------------- 282 */ 283static Boolean 284CondDoDefined (argLen, arg) 285 int argLen; 286 char *arg; 287{ 288 char savec = arg[argLen]; 289 char *p1; 290 Boolean result; 291 292 arg[argLen] = '\0'; 293 if (Var_Value (arg, VAR_CMD, &p1) != (char *)NULL) { 294 result = TRUE; 295 } else { 296 result = FALSE; 297 } 298 efree(p1); 299 arg[argLen] = savec; 300 return (result); 301} 302 303/*- 304 *----------------------------------------------------------------------- 305 * CondStrMatch -- 306 * Front-end for Str_Match so it returns 0 on match and non-zero 307 * on mismatch. Callback function for CondDoMake via Lst_Find 308 * 309 * Results: 310 * 0 if string matches pattern 311 * 312 * Side Effects: 313 * None 314 * 315 *----------------------------------------------------------------------- 316 */ 317static int 318CondStrMatch(string, pattern) 319 ClientData string; 320 ClientData pattern; 321{ 322 return(!Str_Match((char *) string,(char *) pattern)); 323} 324 325/*- 326 *----------------------------------------------------------------------- 327 * CondDoMake -- 328 * Handle the 'make' function for conditionals. 329 * 330 * Results: 331 * TRUE if the given target is being made. 332 * 333 * Side Effects: 334 * None. 335 * 336 *----------------------------------------------------------------------- 337 */ 338static Boolean 339CondDoMake (argLen, arg) 340 int argLen; 341 char *arg; 342{ 343 char savec = arg[argLen]; 344 Boolean result; 345 346 arg[argLen] = '\0'; 347 if (Lst_Find (create, (ClientData)arg, CondStrMatch) == NILLNODE) { 348 result = FALSE; 349 } else { 350 result = TRUE; 351 } 352 arg[argLen] = savec; 353 return (result); 354} 355 356/*- 357 *----------------------------------------------------------------------- 358 * CondDoExists -- 359 * See if the given file exists. 360 * 361 * Results: 362 * TRUE if the file exists and FALSE if it does not. 363 * 364 * Side Effects: 365 * None. 366 * 367 *----------------------------------------------------------------------- 368 */ 369static Boolean 370CondDoExists (argLen, arg) 371 int argLen; 372 char *arg; 373{ 374 char savec = arg[argLen]; 375 Boolean result; 376 char *path; 377 378 arg[argLen] = '\0'; 379 path = Dir_FindFile(arg, dirSearchPath); 380 if (path != (char *)NULL) { 381 result = TRUE; 382 free(path); 383 } else { 384 result = FALSE; 385 } 386 arg[argLen] = savec; 387 return (result); 388} 389 390/*- 391 *----------------------------------------------------------------------- 392 * CondDoTarget -- 393 * See if the given node exists and is an actual target. 394 * 395 * Results: 396 * TRUE if the node exists as a target and FALSE if it does not. 397 * 398 * Side Effects: 399 * None. 400 * 401 *----------------------------------------------------------------------- 402 */ 403static Boolean 404CondDoTarget (argLen, arg) 405 int argLen; 406 char *arg; 407{ 408 char savec = arg[argLen]; 409 Boolean result; 410 GNode *gn; 411 412 arg[argLen] = '\0'; 413 gn = Targ_FindNode(arg, TARG_NOCREATE); 414 if ((gn != NILGNODE) && !OP_NOP(gn->type)) { 415 result = TRUE; 416 } else { 417 result = FALSE; 418 } 419 arg[argLen] = savec; 420 return (result); 421} 422 423 424/*- 425 *----------------------------------------------------------------------- 426 * CondCvtArg -- 427 * Convert the given number into a double. If the number begins 428 * with 0x, it is interpreted as a hexadecimal integer 429 * and converted to a double from there. All other strings just have 430 * strtod called on them. 431 * 432 * Results: 433 * Sets 'value' to double value of string. 434 * Returns address of the first character after the last valid 435 * character of the converted number. 436 * 437 * Side Effects: 438 * Can change 'value' even if string is not a valid number. 439 * 440 * 441 *----------------------------------------------------------------------- 442 */ 443static char * 444CondCvtArg(str, value) 445 register char *str; 446 double *value; 447{ 448 if ((*str == '0') && (str[1] == 'x')) { 449 register long i; 450 451 for (str += 2, i = 0; ; str++) { 452 int x; 453 if (isdigit((unsigned char) *str)) 454 x = *str - '0'; 455 else if (isxdigit((unsigned char) *str)) 456 x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a'; 457 else { 458 *value = (double) i; 459 return str; 460 } 461 i = (i << 4) + x; 462 } 463 } 464 else { 465 char *eptr; 466 *value = strtod(str, &eptr); 467 return eptr; 468 } 469} 470 471/*- 472 *----------------------------------------------------------------------- 473 * CondToken -- 474 * Return the next token from the input. 475 * 476 * Results: 477 * A Token for the next lexical token in the stream. 478 * 479 * Side Effects: 480 * condPushback will be set back to None if it is used. 481 * 482 *----------------------------------------------------------------------- 483 */ 484static Token 485CondToken(doEval) 486 Boolean doEval; 487{ 488 Token t; 489 490 if (condPushBack == None) { 491 while (*condExpr == ' ' || *condExpr == '\t') { 492 condExpr++; 493 } 494 switch (*condExpr) { 495 case '(': 496 t = LParen; 497 condExpr++; 498 break; 499 case ')': 500 t = RParen; 501 condExpr++; 502 break; 503 case '|': 504 if (condExpr[1] == '|') { 505 condExpr++; 506 } 507 condExpr++; 508 t = Or; 509 break; 510 case '&': 511 if (condExpr[1] == '&') { 512 condExpr++; 513 } 514 condExpr++; 515 t = And; 516 break; 517 case '!': 518 t = Not; 519 condExpr++; 520 break; 521 case '\n': 522 case '\0': 523 t = EndOfFile; 524 break; 525 case '$': { 526 char *lhs; 527 char *rhs; 528 char *op; 529 int varSpecLen; 530 Boolean doFree; 531 532 /* 533 * Parse the variable spec and skip over it, saving its 534 * value in lhs. 535 */ 536 t = Err; 537 lhs = Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree); 538 if (lhs == var_Error) { 539 /* 540 * Even if !doEval, we still report syntax errors, which 541 * is what getting var_Error back with !doEval means. 542 */ 543 return(Err); 544 } 545 condExpr += varSpecLen; 546 547 if (!isspace((unsigned char) *condExpr) && 548 strchr("!=><", *condExpr) == NULL) { 549 Buffer buf; 550 char *cp; 551 552 buf = Buf_Init(0); 553 554 for (cp = lhs; *cp; cp++) 555 Buf_AddByte(buf, (Byte)*cp); 556 557 if (doFree) 558 free(lhs); 559 560 for (;*condExpr && !isspace((unsigned char) *condExpr); 561 condExpr++) 562 Buf_AddByte(buf, (Byte)*condExpr); 563 564 Buf_AddByte(buf, (Byte)'\0'); 565 lhs = (char *)Buf_GetAll(buf, &varSpecLen); 566 Buf_Destroy(buf, FALSE); 567 568 doFree = TRUE; 569 } 570 571 /* 572 * Skip whitespace to get to the operator 573 */ 574 while (isspace((unsigned char) *condExpr)) 575 condExpr++; 576 577 /* 578 * Make sure the operator is a valid one. If it isn't a 579 * known relational operator, pretend we got a 580 * != 0 comparison. 581 */ 582 op = condExpr; 583 switch (*condExpr) { 584 case '!': 585 case '=': 586 case '<': 587 case '>': 588 if (condExpr[1] == '=') { 589 condExpr += 2; 590 } else { 591 condExpr += 1; 592 } 593 break; 594 default: 595 op = "!="; 596 rhs = "0"; 597 598 goto do_compare; 599 } 600 while (isspace((unsigned char) *condExpr)) { 601 condExpr++; 602 } 603 if (*condExpr == '\0') { 604 Parse_Error(PARSE_WARNING, 605 "Missing right-hand-side of operator"); 606 goto error; 607 } 608 rhs = condExpr; 609do_compare: 610 if (*rhs == '"') { 611 /* 612 * Doing a string comparison. Only allow == and != for 613 * operators. 614 */ 615 char *string; 616 char *cp, *cp2; 617 int qt; 618 Buffer buf; 619 620do_string_compare: 621 if (((*op != '!') && (*op != '=')) || (op[1] != '=')) { 622 Parse_Error(PARSE_WARNING, 623 "String comparison operator should be either == or !="); 624 goto error; 625 } 626 627 buf = Buf_Init(0); 628 qt = *rhs == '"' ? 1 : 0; 629 630 for (cp = &rhs[qt]; 631 ((qt && (*cp != '"')) || 632 (!qt && strchr(" \t)", *cp) == NULL)) && 633 (*cp != '\0'); cp++) { 634 if ((*cp == '\\') && (cp[1] != '\0')) { 635 /* 636 * Backslash escapes things -- skip over next 637 * character, if it exists. 638 */ 639 cp++; 640 Buf_AddByte(buf, (Byte)*cp); 641 } else if (*cp == '$') { 642 int len; 643 Boolean freeIt; 644 645 cp2 = Var_Parse(cp, VAR_CMD, doEval,&len, &freeIt); 646 if (cp2 != var_Error) { 647 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 648 if (freeIt) { 649 free(cp2); 650 } 651 cp += len - 1; 652 } else { 653 Buf_AddByte(buf, (Byte)*cp); 654 } 655 } else { 656 Buf_AddByte(buf, (Byte)*cp); 657 } 658 } 659 660 Buf_AddByte(buf, (Byte)0); 661 662 string = (char *)Buf_GetAll(buf, (int *)0); 663 Buf_Destroy(buf, FALSE); 664 665 if (DEBUG(COND)) { 666 printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n", 667 lhs, string, op); 668 } 669 /* 670 * Null-terminate rhs and perform the comparison. 671 * t is set to the result. 672 */ 673 if (*op == '=') { 674 t = strcmp(lhs, string) ? False : True; 675 } else { 676 t = strcmp(lhs, string) ? True : False; 677 } 678 free(string); 679 if (rhs == condExpr) { 680 if (!qt && *cp == ')') 681 condExpr = cp; 682 else 683 condExpr = cp + 1; 684 } 685 } else { 686 /* 687 * rhs is either a float or an integer. Convert both the 688 * lhs and the rhs to a double and compare the two. 689 */ 690 double left, right; 691 char *string; 692 693 if (*CondCvtArg(lhs, &left) != '\0') 694 goto do_string_compare; 695 if (*rhs == '$') { 696 int len; 697 Boolean freeIt; 698 699 string = Var_Parse(rhs, VAR_CMD, doEval,&len,&freeIt); 700 if (string == var_Error) { 701 right = 0.0; 702 } else { 703 if (*CondCvtArg(string, &right) != '\0') { 704 if (freeIt) 705 free(string); 706 goto do_string_compare; 707 } 708 if (freeIt) 709 free(string); 710 if (rhs == condExpr) 711 condExpr += len; 712 } 713 } else { 714 char *c = CondCvtArg(rhs, &right); 715 if (*c != '\0' && !isspace(*c)) 716 goto do_string_compare; 717 if (rhs == condExpr) { 718 /* 719 * Skip over the right-hand side 720 */ 721 while(!isspace((unsigned char) *condExpr) && 722 (*condExpr != '\0')) { 723 condExpr++; 724 } 725 } 726 } 727 728 if (DEBUG(COND)) { 729 printf("left = %f, right = %f, op = %.2s\n", left, 730 right, op); 731 } 732 switch(op[0]) { 733 case '!': 734 if (op[1] != '=') { 735 Parse_Error(PARSE_WARNING, 736 "Unknown operator"); 737 goto error; 738 } 739 t = (left != right ? True : False); 740 break; 741 case '=': 742 if (op[1] != '=') { 743 Parse_Error(PARSE_WARNING, 744 "Unknown operator"); 745 goto error; 746 } 747 t = (left == right ? True : False); 748 break; 749 case '<': 750 if (op[1] == '=') { 751 t = (left <= right ? True : False); 752 } else { 753 t = (left < right ? True : False); 754 } 755 break; 756 case '>': 757 if (op[1] == '=') { 758 t = (left >= right ? True : False); 759 } else { 760 t = (left > right ? True : False); 761 } 762 break; 763 } 764 } 765error: 766 if (doFree) 767 free(lhs); 768 break; 769 } 770 default: { 771 Boolean (*evalProc) __P((int, char *)); 772 Boolean invert = FALSE; 773 char *arg; 774 int arglen; 775 776 if (strncmp (condExpr, "defined", 7) == 0) { 777 /* 778 * Use CondDoDefined to evaluate the argument and 779 * CondGetArg to extract the argument from the 'function 780 * call'. 781 */ 782 evalProc = CondDoDefined; 783 condExpr += 7; 784 arglen = CondGetArg (&condExpr, &arg, "defined", TRUE); 785 if (arglen == 0) { 786 condExpr -= 7; 787 goto use_default; 788 } 789 } else if (strncmp (condExpr, "make", 4) == 0) { 790 /* 791 * Use CondDoMake to evaluate the argument and 792 * CondGetArg to extract the argument from the 'function 793 * call'. 794 */ 795 evalProc = CondDoMake; 796 condExpr += 4; 797 arglen = CondGetArg (&condExpr, &arg, "make", TRUE); 798 if (arglen == 0) { 799 condExpr -= 4; 800 goto use_default; 801 } 802 } else if (strncmp (condExpr, "exists", 6) == 0) { 803 /* 804 * Use CondDoExists to evaluate the argument and 805 * CondGetArg to extract the argument from the 806 * 'function call'. 807 */ 808 evalProc = CondDoExists; 809 condExpr += 6; 810 arglen = CondGetArg(&condExpr, &arg, "exists", TRUE); 811 if (arglen == 0) { 812 condExpr -= 6; 813 goto use_default; 814 } 815 } else if (strncmp(condExpr, "empty", 5) == 0) { 816 /* 817 * Use Var_Parse to parse the spec in parens and return 818 * True if the resulting string is empty. 819 */ 820 int length; 821 Boolean doFree; 822 char *val; 823 824 condExpr += 5; 825 826 for (arglen = 0; 827 condExpr[arglen] != '(' && condExpr[arglen] != '\0'; 828 arglen += 1) 829 continue; 830 831 if (condExpr[arglen] != '\0') { 832 val = Var_Parse(&condExpr[arglen - 1], VAR_CMD, 833 doEval, &length, &doFree); 834 if (val == var_Error) { 835 t = Err; 836 } else { 837 /* 838 * A variable is empty when it just contains 839 * spaces... 4/15/92, christos 840 */ 841 char *p; 842 for (p = val; *p && isspace((unsigned char)*p); p++) 843 continue; 844 t = (*p == '\0') ? True : False; 845 } 846 if (doFree) { 847 free(val); 848 } 849 /* 850 * Advance condExpr to beyond the closing ). Note that 851 * we subtract one from arglen + length b/c length 852 * is calculated from condExpr[arglen - 1]. 853 */ 854 condExpr += arglen + length - 1; 855 } else { 856 condExpr -= 5; 857 goto use_default; 858 } 859 break; 860 } else if (strncmp (condExpr, "target", 6) == 0) { 861 /* 862 * Use CondDoTarget to evaluate the argument and 863 * CondGetArg to extract the argument from the 864 * 'function call'. 865 */ 866 evalProc = CondDoTarget; 867 condExpr += 6; 868 arglen = CondGetArg(&condExpr, &arg, "target", TRUE); 869 if (arglen == 0) { 870 condExpr -= 6; 871 goto use_default; 872 } 873 } else { 874 /* 875 * The symbol is itself the argument to the default 876 * function. We advance condExpr to the end of the symbol 877 * by hand (the next whitespace, closing paren or 878 * binary operator) and set to invert the evaluation 879 * function if condInvert is TRUE. 880 */ 881 use_default: 882 invert = condInvert; 883 evalProc = condDefProc; 884 arglen = CondGetArg(&condExpr, &arg, "", FALSE); 885 } 886 887 /* 888 * Evaluate the argument using the set function. If invert 889 * is TRUE, we invert the sense of the function. 890 */ 891 t = (!doEval || (* evalProc) (arglen, arg) ? 892 (invert ? False : True) : 893 (invert ? True : False)); 894 free(arg); 895 break; 896 } 897 } 898 } else { 899 t = condPushBack; 900 condPushBack = None; 901 } 902 return (t); 903} 904 905/*- 906 *----------------------------------------------------------------------- 907 * CondT -- 908 * Parse a single term in the expression. This consists of a terminal 909 * symbol or Not and a terminal symbol (not including the binary 910 * operators): 911 * T -> defined(variable) | make(target) | exists(file) | symbol 912 * T -> ! T | ( E ) 913 * 914 * Results: 915 * True, False or Err. 916 * 917 * Side Effects: 918 * Tokens are consumed. 919 * 920 *----------------------------------------------------------------------- 921 */ 922static Token 923CondT(doEval) 924 Boolean doEval; 925{ 926 Token t; 927 928 t = CondToken(doEval); 929 930 if (t == EndOfFile) { 931 /* 932 * If we reached the end of the expression, the expression 933 * is malformed... 934 */ 935 t = Err; 936 } else if (t == LParen) { 937 /* 938 * T -> ( E ) 939 */ 940 t = CondE(doEval); 941 if (t != Err) { 942 if (CondToken(doEval) != RParen) { 943 t = Err; 944 } 945 } 946 } else if (t == Not) { 947 t = CondT(doEval); 948 if (t == True) { 949 t = False; 950 } else if (t == False) { 951 t = True; 952 } 953 } 954 return (t); 955} 956 957/*- 958 *----------------------------------------------------------------------- 959 * CondF -- 960 * Parse a conjunctive factor (nice name, wot?) 961 * F -> T && F | T 962 * 963 * Results: 964 * True, False or Err 965 * 966 * Side Effects: 967 * Tokens are consumed. 968 * 969 *----------------------------------------------------------------------- 970 */ 971static Token 972CondF(doEval) 973 Boolean doEval; 974{ 975 Token l, o; 976 977 l = CondT(doEval); 978 if (l != Err) { 979 o = CondToken(doEval); 980 981 if (o == And) { 982 /* 983 * F -> T && F 984 * 985 * If T is False, the whole thing will be False, but we have to 986 * parse the r.h.s. anyway (to throw it away). 987 * If T is True, the result is the r.h.s., be it an Err or no. 988 */ 989 if (l == True) { 990 l = CondF(doEval); 991 } else { 992 (void) CondF(FALSE); 993 } 994 } else { 995 /* 996 * F -> T 997 */ 998 CondPushBack (o); 999 } 1000 } 1001 return (l); 1002} 1003 1004/*- 1005 *----------------------------------------------------------------------- 1006 * CondE -- 1007 * Main expression production. 1008 * E -> F || E | F 1009 * 1010 * Results: 1011 * True, False or Err. 1012 * 1013 * Side Effects: 1014 * Tokens are, of course, consumed. 1015 * 1016 *----------------------------------------------------------------------- 1017 */ 1018static Token 1019CondE(doEval) 1020 Boolean doEval; 1021{ 1022 Token l, o; 1023 1024 l = CondF(doEval); 1025 if (l != Err) { 1026 o = CondToken(doEval); 1027 1028 if (o == Or) { 1029 /* 1030 * E -> F || E 1031 * 1032 * A similar thing occurs for ||, except that here we make sure 1033 * the l.h.s. is False before we bother to evaluate the r.h.s. 1034 * Once again, if l is False, the result is the r.h.s. and once 1035 * again if l is True, we parse the r.h.s. to throw it away. 1036 */ 1037 if (l == False) { 1038 l = CondE(doEval); 1039 } else { 1040 (void) CondE(FALSE); 1041 } 1042 } else { 1043 /* 1044 * E -> F 1045 */ 1046 CondPushBack (o); 1047 } 1048 } 1049 return (l); 1050} 1051 1052/*- 1053 *----------------------------------------------------------------------- 1054 * Cond_Eval -- 1055 * Evaluate the conditional in the passed line. The line 1056 * looks like this: 1057 * #<cond-type> <expr> 1058 * where <cond-type> is any of if, ifmake, ifnmake, ifdef, 1059 * ifndef, elif, elifmake, elifnmake, elifdef, elifndef 1060 * and <expr> consists of &&, ||, !, make(target), defined(variable) 1061 * and parenthetical groupings thereof. 1062 * 1063 * Results: 1064 * COND_PARSE if should parse lines after the conditional 1065 * COND_SKIP if should skip lines after the conditional 1066 * COND_INVALID if not a valid conditional. 1067 * 1068 * Side Effects: 1069 * None. 1070 * 1071 *----------------------------------------------------------------------- 1072 */ 1073int 1074Cond_Eval (line) 1075 char *line; /* Line to parse */ 1076{ 1077 struct If *ifp; 1078 Boolean isElse; 1079 Boolean value = FALSE; 1080 int level; /* Level at which to report errors. */ 1081 1082 level = PARSE_FATAL; 1083 1084 for (line++; *line == ' ' || *line == '\t'; line++) { 1085 continue; 1086 } 1087 1088 /* 1089 * Find what type of if we're dealing with. The result is left 1090 * in ifp and isElse is set TRUE if it's an elif line. 1091 */ 1092 if (line[0] == 'e' && line[1] == 'l') { 1093 line += 2; 1094 isElse = TRUE; 1095 } else if (strncmp (line, "endif", 5) == 0) { 1096 /* 1097 * End of a conditional section. If skipIfLevel is non-zero, that 1098 * conditional was skipped, so lines following it should also be 1099 * skipped. Hence, we return COND_SKIP. Otherwise, the conditional 1100 * was read so succeeding lines should be parsed (think about it...) 1101 * so we return COND_PARSE, unless this endif isn't paired with 1102 * a decent if. 1103 */ 1104 if (skipIfLevel != 0) { 1105 skipIfLevel -= 1; 1106 return (COND_SKIP); 1107 } else { 1108 if (condTop == MAXIF) { 1109 Parse_Error (level, "if-less endif"); 1110 return (COND_INVALID); 1111 } else { 1112 skipLine = FALSE; 1113 condTop += 1; 1114 return (COND_PARSE); 1115 } 1116 } 1117 } else { 1118 isElse = FALSE; 1119 } 1120 1121 /* 1122 * Figure out what sort of conditional it is -- what its default 1123 * function is, etc. -- by looking in the table of valid "ifs" 1124 */ 1125 for (ifp = ifs; ifp->form != (char *)0; ifp++) { 1126 if (strncmp (ifp->form, line, ifp->formlen) == 0) { 1127 break; 1128 } 1129 } 1130 1131 if (ifp->form == (char *) 0) { 1132 /* 1133 * Nothing fit. If the first word on the line is actually 1134 * "else", it's a valid conditional whose value is the inverse 1135 * of the previous if we parsed. 1136 */ 1137 if (isElse && (line[0] == 's') && (line[1] == 'e')) { 1138 if (condTop == MAXIF) { 1139 Parse_Error (level, "if-less else"); 1140 return (COND_INVALID); 1141 } else if (skipIfLevel == 0) { 1142 value = !condStack[condTop]; 1143 } else { 1144 return (COND_SKIP); 1145 } 1146 } else { 1147 /* 1148 * Not a valid conditional type. No error... 1149 */ 1150 return (COND_INVALID); 1151 } 1152 } else { 1153 if (isElse) { 1154 if (condTop == MAXIF) { 1155 Parse_Error (level, "if-less elif"); 1156 return (COND_INVALID); 1157 } else if (skipIfLevel != 0) { 1158 /* 1159 * If skipping this conditional, just ignore the whole thing. 1160 * If we don't, the user might be employing a variable that's 1161 * undefined, for which there's an enclosing ifdef that 1162 * we're skipping... 1163 */ 1164 return(COND_SKIP); 1165 } 1166 } else if (skipLine) { 1167 /* 1168 * Don't even try to evaluate a conditional that's not an else if 1169 * we're skipping things... 1170 */ 1171 skipIfLevel += 1; 1172 return(COND_SKIP); 1173 } 1174 1175 /* 1176 * Initialize file-global variables for parsing 1177 */ 1178 condDefProc = ifp->defProc; 1179 condInvert = ifp->doNot; 1180 1181 line += ifp->formlen; 1182 1183 while (*line == ' ' || *line == '\t') { 1184 line++; 1185 } 1186 1187 condExpr = line; 1188 condPushBack = None; 1189 1190 switch (CondE(TRUE)) { 1191 case True: 1192 if (CondToken(TRUE) == EndOfFile) { 1193 value = TRUE; 1194 break; 1195 } 1196 goto err; 1197 /*FALLTHRU*/ 1198 case False: 1199 if (CondToken(TRUE) == EndOfFile) { 1200 value = FALSE; 1201 break; 1202 } 1203 /*FALLTHRU*/ 1204 case Err: 1205 err: 1206 Parse_Error (level, "Malformed conditional (%s)", 1207 line); 1208 return (COND_INVALID); 1209 default: 1210 break; 1211 } 1212 } 1213 if (!isElse) { 1214 condTop -= 1; 1215 } else if ((skipIfLevel != 0) || condStack[condTop]) { 1216 /* 1217 * If this is an else-type conditional, it should only take effect 1218 * if its corresponding if was evaluated and FALSE. If its if was 1219 * TRUE or skipped, we return COND_SKIP (and start skipping in case 1220 * we weren't already), leaving the stack unmolested so later elif's 1221 * don't screw up... 1222 */ 1223 skipLine = TRUE; 1224 return (COND_SKIP); 1225 } 1226 1227 if (condTop < 0) { 1228 /* 1229 * This is the one case where we can definitely proclaim a fatal 1230 * error. If we don't, we're hosed. 1231 */ 1232 Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF); 1233 return (COND_INVALID); 1234 } else { 1235 condStack[condTop] = value; 1236 skipLine = !value; 1237 return (value ? COND_PARSE : COND_SKIP); 1238 } 1239} 1240 1241/*- 1242 *----------------------------------------------------------------------- 1243 * Cond_End -- 1244 * Make sure everything's clean at the end of a makefile. 1245 * 1246 * Results: 1247 * None. 1248 * 1249 * Side Effects: 1250 * Parse_Error will be called if open conditionals are around. 1251 * 1252 *----------------------------------------------------------------------- 1253 */ 1254void 1255Cond_End() 1256{ 1257 if (condTop != MAXIF) { 1258 Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop, 1259 MAXIF-condTop == 1 ? "" : "s"); 1260 } 1261 condTop = MAXIF; 1262} 1263