Fri Sep 11 16:23:47 2020 UTC ()
make(1): clean up code for evaluating conditions


(rillig)
diff -r1.131 -r1.132 src/usr.bin/make/cond.c

cvs diff -r1.131 -r1.132 src/usr.bin/make/cond.c (expand / switch to unified diff)

--- src/usr.bin/make/cond.c 2020/09/11 16:22:15 1.131
+++ src/usr.bin/make/cond.c 2020/09/11 16:23:47 1.132
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: cond.c,v 1.131 2020/09/11 16:22:15 rillig Exp $ */ 1/* $NetBSD: cond.c,v 1.132 2020/09/11 16:23:47 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -60,34 +60,34 @@ @@ -60,34 +60,34 @@
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
70 */ 70 */
71 71
72#ifndef MAKE_NATIVE 72#ifndef MAKE_NATIVE
73static char rcsid[] = "$NetBSD: cond.c,v 1.131 2020/09/11 16:22:15 rillig Exp $"; 73static char rcsid[] = "$NetBSD: cond.c,v 1.132 2020/09/11 16:23:47 rillig Exp $";
74#else 74#else
75#include <sys/cdefs.h> 75#include <sys/cdefs.h>
76#ifndef lint 76#ifndef lint
77#if 0 77#if 0
78static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; 78static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
79#else 79#else
80__RCSID("$NetBSD: cond.c,v 1.131 2020/09/11 16:22:15 rillig Exp $"); 80__RCSID("$NetBSD: cond.c,v 1.132 2020/09/11 16:23:47 rillig Exp $");
81#endif 81#endif
82#endif /* not lint */ 82#endif /* not lint */
83#endif 83#endif
84 84
85/* Handling of conditionals in a makefile. 85/* Handling of conditionals in a makefile.
86 * 86 *
87 * Interface: 87 * Interface:
88 * Cond_Eval Evaluate the conditional in the passed line. 88 * Cond_Eval Evaluate the conditional in the passed line.
89 * 89 *
90 * Cond_EvalExpression 90 * Cond_EvalExpression
91 * Evaluate the conditional in the passed line, which 91 * Evaluate the conditional in the passed line, which
92 * is either the argument of one of the .if directives 92 * is either the argument of one of the .if directives
93 * or the condition in a :?true:false variable modifier. 93 * or the condition in a :?true:false variable modifier.
@@ -545,27 +545,27 @@ EvalNotEmpty(CondParser *par, const char @@ -545,27 +545,27 @@ EvalNotEmpty(CondParser *par, const char
545 /* Otherwise action default test ... */ 545 /* Otherwise action default test ... */
546 return par->if_info->defProc(strlen(lhs), lhs) != par->if_info->doNot; 546 return par->if_info->defProc(strlen(lhs), lhs) != par->if_info->doNot;
547} 547}
548 548
549/* Evaluate a comparison, such as "${VAR} == 12345". */ 549/* Evaluate a comparison, such as "${VAR} == 12345". */
550static Token 550static Token
551EvalComparison(const char *lhs, Boolean lhsQuoted, const char *op, 551EvalComparison(const char *lhs, Boolean lhsQuoted, const char *op,
552 const char *rhs, Boolean rhsQuoted) 552 const char *rhs, Boolean rhsQuoted)
553{ 553{
554 double left, right; 554 double left, right;
555 555
556 if (rhsQuoted || lhsQuoted) { 556 if (rhsQuoted || lhsQuoted) {
557 do_string_compare: 557 do_string_compare:
558 if (((*op != '!') && (*op != '=')) || (op[1] != '=')) { 558 if ((*op != '!' && *op != '=') || op[1] != '=') {
559 Parse_Error(PARSE_WARNING, 559 Parse_Error(PARSE_WARNING,
560 "String comparison operator should be either == or !="); 560 "String comparison operator should be either == or !=");
561 return TOK_ERROR; 561 return TOK_ERROR;
562 } 562 }
563 563
564 if (DEBUG(COND)) { 564 if (DEBUG(COND)) {
565 fprintf(debug_file, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", 565 fprintf(debug_file, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
566 lhs, rhs, op); 566 lhs, rhs, op);
567 } 567 }
568 return (*op == '=') == (strcmp(lhs, rhs) == 0); 568 return (*op == '=') == (strcmp(lhs, rhs) == 0);
569 } 569 }
570 570
571 /* 571 /*
@@ -573,74 +573,59 @@ EvalComparison(const char *lhs, Boolean  @@ -573,74 +573,59 @@ EvalComparison(const char *lhs, Boolean
573 * lhs and the rhs to a double and compare the two. 573 * lhs and the rhs to a double and compare the two.
574 */ 574 */
575 575
576 if (!TryParseNumber(lhs, &left) || !TryParseNumber(rhs, &right)) 576 if (!TryParseNumber(lhs, &left) || !TryParseNumber(rhs, &right))
577 goto do_string_compare; 577 goto do_string_compare;
578 578
579 if (DEBUG(COND)) { 579 if (DEBUG(COND)) {
580 fprintf(debug_file, "left = %f, right = %f, op = %.2s\n", left, 580 fprintf(debug_file, "left = %f, right = %f, op = %.2s\n", left,
581 right, op); 581 right, op);
582 } 582 }
583 switch (op[0]) { 583 switch (op[0]) {
584 case '!': 584 case '!':
585 if (op[1] != '=') { 585 if (op[1] != '=') {
586 Parse_Error(PARSE_WARNING, 586 Parse_Error(PARSE_WARNING, "Unknown operator");
587 "Unknown operator"); 
588 return TOK_ERROR; 587 return TOK_ERROR;
589 } 588 }
590 return left != right; 589 return left != right;
591 case '=': 590 case '=':
592 if (op[1] != '=') { 591 if (op[1] != '=') {
593 Parse_Error(PARSE_WARNING, 592 Parse_Error(PARSE_WARNING, "Unknown operator");
594 "Unknown operator"); 
595 return TOK_ERROR; 593 return TOK_ERROR;
596 } 594 }
597 return left == right; 595 return left == right;
598 case '<': 596 case '<':
599 if (op[1] == '=') { 597 return op[1] == '=' ? left <= right : left < right;
600 return left <= right; 
601 } else { 
602 return left < right; 
603 } 
604 case '>': 598 case '>':
605 if (op[1] == '=') { 599 return op[1] == '=' ? left >= right : left > right;
606 return left >= right; 
607 } else { 
608 return left > right; 
609 } 
610 } 600 }
611 return TOK_ERROR; 601 return TOK_ERROR;
612} 602}
613 603
614/* Parse a comparison condition such as: 604/* Parse a comparison condition such as:
615 * 605 *
616 * 0 606 * 0
617 * ${VAR:Mpattern} 607 * ${VAR:Mpattern}
618 * ${VAR} == value 608 * ${VAR} == value
619 * ${VAR:U0} < 12345 609 * ${VAR:U0} < 12345
620 */ 610 */
621static Token 611static Token
622CondParser_Comparison(CondParser *par, Boolean doEval) 612CondParser_Comparison(CondParser *par, Boolean doEval)
623{ 613{
624 Token t; 614 Token t = TOK_ERROR;
625 const char *lhs; 615 const char *lhs, *op, *rhs;
626 const char *rhs; 616 void *lhsFree, *rhsFree;
627 const char *op; 617 Boolean lhsQuoted, rhsQuoted;
628 void *lhsFree; 
629 void *rhsFree; 
630 Boolean lhsQuoted; 
631 Boolean rhsQuoted; 
632 618
633 t = TOK_ERROR; 
634 rhs = NULL; 619 rhs = NULL;
635 lhsFree = rhsFree = NULL; 620 lhsFree = rhsFree = NULL;
636 lhsQuoted = rhsQuoted = FALSE; 621 lhsQuoted = rhsQuoted = FALSE;
637 622
638 /* 623 /*
639 * Parse the variable spec and skip over it, saving its 624 * Parse the variable spec and skip over it, saving its
640 * value in lhs. 625 * value in lhs.
641 */ 626 */
642 lhs = CondParser_String(par, doEval, lhsStrict, &lhsQuoted, &lhsFree); 627 lhs = CondParser_String(par, doEval, lhsStrict, &lhsQuoted, &lhsFree);
643 if (!lhs) 628 if (!lhs)
644 goto done; 629 goto done;
645 630
646 CondParser_SkipWhitespace(par); 631 CondParser_SkipWhitespace(par);
@@ -660,33 +645,32 @@ CondParser_Comparison(CondParser *par, B @@ -660,33 +645,32 @@ CondParser_Comparison(CondParser *par, B
660 par->p += 2; 645 par->p += 2;
661 } else { 646 } else {
662 par->p += 1; 647 par->p += 1;
663 } 648 }
664 break; 649 break;
665 default: 650 default:
666 t = doEval ? EvalNotEmpty(par, lhs, lhsQuoted) : TOK_FALSE; 651 t = doEval ? EvalNotEmpty(par, lhs, lhsQuoted) : TOK_FALSE;
667 goto done; 652 goto done;
668 } 653 }
669 654
670 CondParser_SkipWhitespace(par); 655 CondParser_SkipWhitespace(par);
671 656
672 if (par->p[0] == '\0') { 657 if (par->p[0] == '\0') {
673 Parse_Error(PARSE_WARNING, 658 Parse_Error(PARSE_WARNING, "Missing right-hand-side of operator");
674 "Missing right-hand-side of operator"); 
675 goto done; 659 goto done;
676 } 660 }
677 661
678 rhs = CondParser_String(par, doEval, FALSE, &rhsQuoted, &rhsFree); 662 rhs = CondParser_String(par, doEval, FALSE, &rhsQuoted, &rhsFree);
679 if (!rhs) 663 if (rhs == NULL)
680 goto done; 664 goto done;
681 665
682 if (!doEval) { 666 if (!doEval) {
683 t = TOK_FALSE; 667 t = TOK_FALSE;
684 goto done; 668 goto done;
685 } 669 }
686 670
687 t = EvalComparison(lhs, lhsQuoted, op, rhs, rhsQuoted); 671 t = EvalComparison(lhs, lhsQuoted, op, rhs, rhsQuoted);
688 672
689done: 673done:
690 free(lhsFree); 674 free(lhsFree);
691 free(rhsFree); 675 free(rhsFree);
692 return t; 676 return t;