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