| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.482 2020/08/31 19:09:19 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.483 2020/09/02 06:19:11 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990, 1993 | | 4 | * Copyright (c) 1988, 1989, 1990, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. 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. |
| @@ -59,34 +59,34 @@ | | | @@ -59,34 +59,34 @@ |
59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
68 | * SUCH DAMAGE. | | 68 | * SUCH DAMAGE. |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #ifndef MAKE_NATIVE | | 71 | #ifndef MAKE_NATIVE |
72 | static char rcsid[] = "$NetBSD: var.c,v 1.482 2020/08/31 19:09:19 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.483 2020/09/02 06:19:11 rillig Exp $"; |
73 | #else | | 73 | #else |
74 | #include <sys/cdefs.h> | | 74 | #include <sys/cdefs.h> |
75 | #ifndef lint | | 75 | #ifndef lint |
76 | #if 0 | | 76 | #if 0 |
77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; | | 77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: var.c,v 1.482 2020/08/31 19:09:19 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.483 2020/09/02 06:19:11 rillig Exp $"); |
80 | #endif | | 80 | #endif |
81 | #endif /* not lint */ | | 81 | #endif /* not lint */ |
82 | #endif | | 82 | #endif |
83 | | | 83 | |
84 | /*- | | 84 | /*- |
85 | * var.c -- | | 85 | * var.c -- |
86 | * Variable-handling functions | | 86 | * Variable-handling functions |
87 | * | | 87 | * |
88 | * Interface: | | 88 | * Interface: |
89 | * Var_Set Set the value of a variable in the given | | 89 | * Var_Set Set the value of a variable in the given |
90 | * context. The variable is created if it doesn't | | 90 | * context. The variable is created if it doesn't |
91 | * yet exist. | | 91 | * yet exist. |
92 | * | | 92 | * |
| @@ -284,29 +284,26 @@ typedef enum { | | | @@ -284,29 +284,26 @@ typedef enum { |
284 | * Find the given variable in the given context and any other contexts | | 284 | * Find the given variable in the given context and any other contexts |
285 | * indicated. | | 285 | * indicated. |
286 | * | | 286 | * |
287 | * Input: | | 287 | * Input: |
288 | * name name to find | | 288 | * name name to find |
289 | * ctxt context in which to find it | | 289 | * ctxt context in which to find it |
290 | * flags FIND_GLOBAL look in VAR_GLOBAL as well | | 290 | * flags FIND_GLOBAL look in VAR_GLOBAL as well |
291 | * FIND_CMD look in VAR_CMD as well | | 291 | * FIND_CMD look in VAR_CMD as well |
292 | * FIND_ENV look in the environment as well | | 292 | * FIND_ENV look in the environment as well |
293 | * | | 293 | * |
294 | * Results: | | 294 | * Results: |
295 | * A pointer to the structure describing the desired variable or | | 295 | * A pointer to the structure describing the desired variable or |
296 | * NULL if the variable does not exist. | | 296 | * NULL if the variable does not exist. |
297 | * | | | |
298 | * Side Effects: | | | |
299 | * None | | | |
300 | *----------------------------------------------------------------------- | | 297 | *----------------------------------------------------------------------- |
301 | */ | | 298 | */ |
302 | static Var * | | 299 | static Var * |
303 | VarFind(const char *name, GNode *ctxt, VarFindFlags flags) | | 300 | VarFind(const char *name, GNode *ctxt, VarFindFlags flags) |
304 | { | | 301 | { |
305 | Hash_Entry *var; | | 302 | Hash_Entry *var; |
306 | | | 303 | |
307 | /* | | 304 | /* |
308 | * If the variable name begins with a '.', it could very well be one of | | 305 | * If the variable name begins with a '.', it could very well be one of |
309 | * the local ones. We check the name against all the local variables | | 306 | * the local ones. We check the name against all the local variables |
310 | * and substitute the short version in for 'name' if it matches one of | | 307 | * and substitute the short version in for 'name' if it matches one of |
311 | * them. | | 308 | * them. |
312 | */ | | 309 | */ |
| @@ -846,67 +843,65 @@ Var_Set_with_flags(const char *name, con | | | @@ -846,67 +843,65 @@ Var_Set_with_flags(const char *name, con |
846 | save_dollars = s2Boolean(val, save_dollars); | | 843 | save_dollars = s2Boolean(val, save_dollars); |
847 | | | 844 | |
848 | out: | | 845 | out: |
849 | free(name_freeIt); | | 846 | free(name_freeIt); |
850 | if (v != NULL) | | 847 | if (v != NULL) |
851 | VarFreeEnv(v, TRUE); | | 848 | VarFreeEnv(v, TRUE); |
852 | } | | 849 | } |
853 | | | 850 | |
854 | /*- | | 851 | /*- |
855 | *----------------------------------------------------------------------- | | 852 | *----------------------------------------------------------------------- |
856 | * Var_Set -- | | 853 | * Var_Set -- |
857 | * Set the variable name to the value val in the given context. | | 854 | * Set the variable name to the value val in the given context. |
858 | * | | 855 | * |
| | | 856 | * If the variable doesn't yet exist, it is created. |
| | | 857 | * Otherwise the new value overwrites and replaces the old value. |
| | | 858 | * |
859 | * Input: | | 859 | * Input: |
860 | * name name of variable to set | | 860 | * name name of variable to set |
861 | * val value to give to the variable | | 861 | * val value to give to the variable |
862 | * ctxt context in which to set it | | 862 | * ctxt context in which to set it |
863 | * | | 863 | * |
864 | * Side Effects: | | | |
865 | * If the variable doesn't yet exist, it is created. | | | |
866 | * Otherwise the new value overwrites and replaces the old value. | | | |
867 | * | | | |
868 | * Notes: | | 864 | * Notes: |
869 | * The variable is searched for only in its context before being | | 865 | * The variable is searched for only in its context before being |
870 | * created in that context. I.e. if the context is VAR_GLOBAL, | | 866 | * created in that context. I.e. if the context is VAR_GLOBAL, |
871 | * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only | | 867 | * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only |
872 | * VAR_CMD->context is searched. This is done to avoid the literally | | 868 | * VAR_CMD->context is searched. This is done to avoid the literally |
873 | * thousands of unnecessary strcmp's that used to be done to | | 869 | * thousands of unnecessary strcmp's that used to be done to |
874 | * set, say, $(@) or $(<). | | 870 | * set, say, $(@) or $(<). |
875 | * If the context is VAR_GLOBAL though, we check if the variable | | 871 | * If the context is VAR_GLOBAL though, we check if the variable |
876 | * was set in VAR_CMD from the command line and skip it if so. | | 872 | * was set in VAR_CMD from the command line and skip it if so. |
877 | *----------------------------------------------------------------------- | | 873 | *----------------------------------------------------------------------- |
878 | */ | | 874 | */ |
879 | void | | 875 | void |
880 | Var_Set(const char *name, const char *val, GNode *ctxt) | | 876 | Var_Set(const char *name, const char *val, GNode *ctxt) |
881 | { | | 877 | { |
882 | Var_Set_with_flags(name, val, ctxt, 0); | | 878 | Var_Set_with_flags(name, val, ctxt, 0); |
883 | } | | 879 | } |
884 | | | 880 | |
885 | /*- | | 881 | /*- |
886 | *----------------------------------------------------------------------- | | 882 | *----------------------------------------------------------------------- |
887 | * Var_Append -- | | 883 | * Var_Append -- |
888 | * The variable of the given name has the given value appended to it in | | 884 | * The variable of the given name has the given value appended to it in |
889 | * the given context. | | 885 | * the given context. |
890 | * | | 886 | * |
| | | 887 | * If the variable doesn't exist, it is created. Otherwise the strings |
| | | 888 | * are concatenated, with a space in between. |
| | | 889 | * |
891 | * Input: | | 890 | * Input: |
892 | * name name of variable to modify | | 891 | * name name of variable to modify |
893 | * val string to append to it | | 892 | * val string to append to it |
894 | * ctxt context in which this should occur | | 893 | * ctxt context in which this should occur |
895 | * | | 894 | * |
896 | * Side Effects: | | | |
897 | * If the variable doesn't exist, it is created. Otherwise the strings | | | |
898 | * are concatenated, with a space in between. | | | |
899 | * | | | |
900 | * Notes: | | 895 | * Notes: |
901 | * Only if the variable is being sought in the global context is the | | 896 | * Only if the variable is being sought in the global context is the |
902 | * environment searched. | | 897 | * environment searched. |
903 | * XXX: Knows its calling circumstances in that if called with ctxt | | 898 | * XXX: Knows its calling circumstances in that if called with ctxt |
904 | * an actual target, it will only search that context since only | | 899 | * an actual target, it will only search that context since only |
905 | * a local variable could be being appended to. This is actually | | 900 | * a local variable could be being appended to. This is actually |
906 | * a big win and must be tolerated. | | 901 | * a big win and must be tolerated. |
907 | *----------------------------------------------------------------------- | | 902 | *----------------------------------------------------------------------- |
908 | */ | | 903 | */ |
909 | void | | 904 | void |
910 | Var_Append(const char *name, const char *val, GNode *ctxt) | | 905 | Var_Append(const char *name, const char *val, GNode *ctxt) |
911 | { | | 906 | { |
912 | char *name_freeIt = NULL; | | 907 | char *name_freeIt = NULL; |
| @@ -944,42 +939,32 @@ Var_Append(const char *name, const char | | | @@ -944,42 +939,32 @@ Var_Append(const char *name, const char |
944 | * If the original variable came from the environment, we | | 939 | * If the original variable came from the environment, we |
945 | * have to install it in the global context (we could place | | 940 | * have to install it in the global context (we could place |
946 | * it in the environment, but then we should provide a way to | | 941 | * it in the environment, but then we should provide a way to |
947 | * export other variables...) | | 942 | * export other variables...) |
948 | */ | | 943 | */ |
949 | v->flags &= ~(unsigned)VAR_FROM_ENV; | | 944 | v->flags &= ~(unsigned)VAR_FROM_ENV; |
950 | h = Hash_CreateEntry(&ctxt->context, name, NULL); | | 945 | h = Hash_CreateEntry(&ctxt->context, name, NULL); |
951 | Hash_SetValue(h, v); | | 946 | Hash_SetValue(h, v); |
952 | } | | 947 | } |
953 | } | | 948 | } |
954 | free(name_freeIt); | | 949 | free(name_freeIt); |
955 | } | | 950 | } |
956 | | | 951 | |
957 | /*- | | 952 | /* See if the given variable exists, in the given context or in other |
958 | *----------------------------------------------------------------------- | | 953 | * fallback contexts. |
959 | * Var_Exists -- | | | |
960 | * See if the given variable exists. | | | |
961 | * | | 954 | * |
962 | * Input: | | 955 | * Input: |
963 | * name Variable to find | | 956 | * name Variable to find |
964 | * ctxt Context in which to start search | | 957 | * ctxt Context in which to start search |
965 | * | | | |
966 | * Results: | | | |
967 | * TRUE if it does, FALSE if it doesn't | | | |
968 | * | | | |
969 | * Side Effects: | | | |
970 | * None. | | | |
971 | * | | | |
972 | *----------------------------------------------------------------------- | | | |
973 | */ | | 958 | */ |
974 | Boolean | | 959 | Boolean |
975 | Var_Exists(const char *name, GNode *ctxt) | | 960 | Var_Exists(const char *name, GNode *ctxt) |
976 | { | | 961 | { |
977 | char *name_freeIt = NULL; | | 962 | char *name_freeIt = NULL; |
978 | Var *v; | | 963 | Var *v; |
979 | | | 964 | |
980 | if (strchr(name, '$') != NULL) | | 965 | if (strchr(name, '$') != NULL) |
981 | name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); | | 966 | name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); |
982 | | | 967 | |
983 | v = VarFind(name, ctxt, FIND_CMD | FIND_GLOBAL | FIND_ENV); | | 968 | v = VarFind(name, ctxt, FIND_CMD | FIND_GLOBAL | FIND_ENV); |
984 | free(name_freeIt); | | 969 | free(name_freeIt); |
985 | if (v == NULL) | | 970 | if (v == NULL) |
| @@ -1745,64 +1730,53 @@ ParseModifierPart( | | | @@ -1745,64 +1730,53 @@ ParseModifierPart( |
1745 | *pp = p; | | 1730 | *pp = p; |
1746 | return NULL; | | 1731 | return NULL; |
1747 | } | | 1732 | } |
1748 | | | 1733 | |
1749 | *pp = ++p; | | 1734 | *pp = ++p; |
1750 | if (out_length != NULL) | | 1735 | if (out_length != NULL) |
1751 | *out_length = Buf_Size(&buf); | | 1736 | *out_length = Buf_Size(&buf); |
1752 | | | 1737 | |
1753 | rstr = Buf_Destroy(&buf, FALSE); | | 1738 | rstr = Buf_Destroy(&buf, FALSE); |
1754 | VAR_DEBUG("Modifier part: \"%s\"\n", rstr); | | 1739 | VAR_DEBUG("Modifier part: \"%s\"\n", rstr); |
1755 | return rstr; | | 1740 | return rstr; |
1756 | } | | 1741 | } |
1757 | | | 1742 | |
1758 | /*- | | 1743 | /* Quote shell meta-characters and space characters in the string. |
1759 | *----------------------------------------------------------------------- | | 1744 | * If quoteDollar is set, also quote and double any '$' characters. */ |
1760 | * VarQuote -- | | | |
1761 | * Quote shell meta-characters and space characters in the string | | | |
1762 | * if quoteDollar is set, also quote and double any '$' characters. | | | |
1763 | * | | | |
1764 | * Results: | | | |
1765 | * The quoted string | | | |
1766 | * | | | |
1767 | * Side Effects: | | | |
1768 | * None. | | | |
1769 | * | | | |
1770 | *----------------------------------------------------------------------- | | | |
1771 | */ | | | |
1772 | static char * | | 1745 | static char * |
1773 | VarQuote(char *str, Boolean quoteDollar) | | 1746 | VarQuote(const char *str, Boolean quoteDollar) |
1774 | { | | 1747 | { |
| | | 1748 | char *res; |
1775 | Buffer buf; | | 1749 | Buffer buf; |
1776 | Buf_Init(&buf, 0); | | 1750 | Buf_Init(&buf, 0); |
1777 | | | 1751 | |
1778 | for (; *str != '\0'; str++) { | | 1752 | for (; *str != '\0'; str++) { |
1779 | if (*str == '\n') { | | 1753 | if (*str == '\n') { |
1780 | const char *newline = Shell_GetNewline(); | | 1754 | const char *newline = Shell_GetNewline(); |
1781 | if (newline == NULL) | | 1755 | if (newline == NULL) |
1782 | newline = "\\\n"; | | 1756 | newline = "\\\n"; |
1783 | Buf_AddStr(&buf, newline); | | 1757 | Buf_AddStr(&buf, newline); |
1784 | continue; | | 1758 | continue; |
1785 | } | | 1759 | } |
1786 | if (isspace((unsigned char)*str) || ismeta((unsigned char)*str)) | | 1760 | if (isspace((unsigned char)*str) || ismeta((unsigned char)*str)) |
1787 | Buf_AddByte(&buf, '\\'); | | 1761 | Buf_AddByte(&buf, '\\'); |
1788 | Buf_AddByte(&buf, *str); | | 1762 | Buf_AddByte(&buf, *str); |
1789 | if (quoteDollar && *str == '$') | | 1763 | if (quoteDollar && *str == '$') |
1790 | Buf_AddStr(&buf, "\\$"); | | 1764 | Buf_AddStr(&buf, "\\$"); |
1791 | } | | 1765 | } |
1792 | | | 1766 | |
1793 | str = Buf_Destroy(&buf, FALSE); | | 1767 | res = Buf_Destroy(&buf, FALSE); |
1794 | VAR_DEBUG("QuoteMeta: [%s]\n", str); | | 1768 | VAR_DEBUG("QuoteMeta: [%s]\n", res); |
1795 | return str; | | 1769 | return res; |
1796 | } | | 1770 | } |
1797 | | | 1771 | |
1798 | /* Compute the 32-bit hash of the given string, using the MurmurHash3 | | 1772 | /* Compute the 32-bit hash of the given string, using the MurmurHash3 |
1799 | * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */ | | 1773 | * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */ |
1800 | static char * | | 1774 | static char * |
1801 | VarHash(const char *str) | | 1775 | VarHash(const char *str) |
1802 | { | | 1776 | { |
1803 | static const char hexdigits[16] = "0123456789abcdef"; | | 1777 | static const char hexdigits[16] = "0123456789abcdef"; |
1804 | const unsigned char *ustr = (const unsigned char *)str; | | 1778 | const unsigned char *ustr = (const unsigned char *)str; |
1805 | | | 1779 | |
1806 | uint32_t h = 0x971e137bU; | | 1780 | uint32_t h = 0x971e137bU; |
1807 | uint32_t c1 = 0x95543787U; | | 1781 | uint32_t c1 = 0x95543787U; |
1808 | uint32_t c2 = 0x2ad7eb25U; | | 1782 | uint32_t c2 = 0x2ad7eb25U; |