| @@ -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 |
73 | static char rcsid[] = "$NetBSD: cond.c,v 1.131 2020/09/11 16:22:15 rillig Exp $"; | | 73 | static 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 |
78 | static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; | | 78 | static 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". */ |
550 | static Token | | 550 | static Token |
551 | EvalComparison(const char *lhs, Boolean lhsQuoted, const char *op, | | 551 | EvalComparison(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 | */ |
621 | static Token | | 611 | static Token |
622 | CondParser_Comparison(CondParser *par, Boolean doEval) | | 612 | CondParser_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 | |
689 | done: | | 673 | done: |
690 | free(lhsFree); | | 674 | free(lhsFree); |
691 | free(rhsFree); | | 675 | free(rhsFree); |
692 | return t; | | 676 | return t; |