Deleted Added
full compact
var.c (282740) var.c (289842)
1/* $NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $ */
1/* $NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $ */
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *

--- 54 unchanged lines hidden (view full) ---

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
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
68 * SUCH DAMAGE.
69 */
70
71#ifndef MAKE_NATIVE
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *

--- 54 unchanged lines hidden (view full) ---

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
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
68 * SUCH DAMAGE.
69 */
70
71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $";
72static char rcsid[] = "$NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $";
73#else
74#include <sys/cdefs.h>
75#ifndef lint
76#if 0
77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
78#else
73#else
74#include <sys/cdefs.h>
75#ifndef lint
76#if 0
77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
78#else
79__RCSID("$NetBSD: var.c,v 1.192 2015/05/05 21:51:09 sjg Exp $");
79__RCSID("$NetBSD: var.c,v 1.199 2015/10/20 21:30:57 sjg Exp $");
80#endif
81#endif /* not lint */
82#endif
83
84/*-
85 * var.c --
86 * Variable-handling functions
87 *

--- 45 unchanged lines hidden (view full) ---

133#include <stdlib.h>
134#include <limits.h>
135#include <time.h>
136
137#include "make.h"
138#include "buf.h"
139#include "dir.h"
140#include "job.h"
80#endif
81#endif /* not lint */
82#endif
83
84/*-
85 * var.c --
86 * Variable-handling functions
87 *

--- 45 unchanged lines hidden (view full) ---

133#include <stdlib.h>
134#include <limits.h>
135#include <time.h>
136
137#include "make.h"
138#include "buf.h"
139#include "dir.h"
140#include "job.h"
141#include "metachar.h"
141
142extern int makelevel;
143/*
144 * This lets us tell if we have replaced the original environ
145 * (which we cannot free).
146 */
147char **savedEnv = NULL;
148

--- 387 unchanged lines hidden (view full) ---

536 */
537void
538Var_Delete(const char *name, GNode *ctxt)
539{
540 Hash_Entry *ln;
541 char *cp;
542
543 if (strchr(name, '$')) {
142
143extern int makelevel;
144/*
145 * This lets us tell if we have replaced the original environ
146 * (which we cannot free).
147 */
148char **savedEnv = NULL;
149

--- 387 unchanged lines hidden (view full) ---

537 */
538void
539Var_Delete(const char *name, GNode *ctxt)
540{
541 Hash_Entry *ln;
542 char *cp;
543
544 if (strchr(name, '$')) {
544 cp = Var_Subst(NULL, name, VAR_GLOBAL, 0);
545 cp = Var_Subst(NULL, name, VAR_GLOBAL, FALSE, TRUE);
545 } else {
546 cp = (char *)name;
547 }
548 ln = Hash_FindEntry(&ctxt->context, cp);
549 if (DEBUG(VAR)) {
550 fprintf(debug_file, "%s:delete %s%s\n",
551 ctxt->name, cp, ln ? "" : " (not found)");
552 }

--- 74 unchanged lines hidden (view full) ---

627 /*
628 * We recursed while exporting in a child.
629 * This isn't going to end well, just skip it.
630 */
631 return 0;
632 }
633 n = snprintf(tmp, sizeof(tmp), "${%s}", name);
634 if (n < (int)sizeof(tmp)) {
546 } else {
547 cp = (char *)name;
548 }
549 ln = Hash_FindEntry(&ctxt->context, cp);
550 if (DEBUG(VAR)) {
551 fprintf(debug_file, "%s:delete %s%s\n",
552 ctxt->name, cp, ln ? "" : " (not found)");
553 }

--- 74 unchanged lines hidden (view full) ---

628 /*
629 * We recursed while exporting in a child.
630 * This isn't going to end well, just skip it.
631 */
632 return 0;
633 }
634 n = snprintf(tmp, sizeof(tmp), "${%s}", name);
635 if (n < (int)sizeof(tmp)) {
635 val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
636 val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
636 setenv(name, val, 1);
637 free(val);
638 }
639 } else {
640 if (parent) {
641 v->flags &= ~VAR_REEXPORT; /* once will do */
642 }
643 if (parent || !(v->flags & VAR_EXPORTED)) {

--- 51 unchanged lines hidden (view full) ---

695 */
696 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
697 if (n < (int)sizeof(tmp)) {
698 char **av;
699 char *as;
700 int ac;
701 int i;
702
637 setenv(name, val, 1);
638 free(val);
639 }
640 } else {
641 if (parent) {
642 v->flags &= ~VAR_REEXPORT; /* once will do */
643 }
644 if (parent || !(v->flags & VAR_EXPORTED)) {

--- 51 unchanged lines hidden (view full) ---

696 */
697 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
698 if (n < (int)sizeof(tmp)) {
699 char **av;
700 char *as;
701 int ac;
702 int i;
703
703 val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
704 val = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
704 av = brk_string(val, &ac, FALSE, &as);
705 for (i = 0; i < ac; i++) {
706 Var_Export1(av[i], 0);
707 }
708 free(val);
709 free(as);
710 free(av);
711 }

--- 21 unchanged lines hidden (view full) ---

733 }
734
735 if (strncmp(str, "-env", 4) == 0) {
736 track = 0;
737 str += 4;
738 } else {
739 track = VAR_EXPORT_PARENT;
740 }
705 av = brk_string(val, &ac, FALSE, &as);
706 for (i = 0; i < ac; i++) {
707 Var_Export1(av[i], 0);
708 }
709 free(val);
710 free(as);
711 free(av);
712 }

--- 21 unchanged lines hidden (view full) ---

734 }
735
736 if (strncmp(str, "-env", 4) == 0) {
737 track = 0;
738 str += 4;
739 } else {
740 track = VAR_EXPORT_PARENT;
741 }
741 val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
742 val = Var_Subst(NULL, str, VAR_GLOBAL, FALSE, TRUE);
742 av = brk_string(val, &ac, FALSE, &as);
743 for (i = 0; i < ac; i++) {
744 name = av[i];
745 if (!name[1]) {
746 /*
747 * A single char.
748 * If it is one of the vars that should only appear in
749 * local context, skip it, else we can get Var_Subst

--- 71 unchanged lines hidden (view full) ---

821 vlist = str;
822 }
823 }
824
825 if (!vlist) {
826 /* Using .MAKE.EXPORTED */
827 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
828 if (n < (int)sizeof(tmp)) {
743 av = brk_string(val, &ac, FALSE, &as);
744 for (i = 0; i < ac; i++) {
745 name = av[i];
746 if (!name[1]) {
747 /*
748 * A single char.
749 * If it is one of the vars that should only appear in
750 * local context, skip it, else we can get Var_Subst

--- 71 unchanged lines hidden (view full) ---

822 vlist = str;
823 }
824 }
825
826 if (!vlist) {
827 /* Using .MAKE.EXPORTED */
828 n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
829 if (n < (int)sizeof(tmp)) {
829 vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
830 vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
830 }
831 }
832 if (vlist) {
833 Var *v;
834 char **av;
835 char *as;
836 int ac;
837 int i;

--- 13 unchanged lines hidden (view full) ---

851 * remove each one from .MAKE.EXPORTED.
852 * If we are removing them all,
853 * just delete .MAKE.EXPORTED below.
854 */
855 if (vlist == str) {
856 n = snprintf(tmp, sizeof(tmp),
857 "${" MAKE_EXPORTED ":N%s}", v->name);
858 if (n < (int)sizeof(tmp)) {
831 }
832 }
833 if (vlist) {
834 Var *v;
835 char **av;
836 char *as;
837 int ac;
838 int i;

--- 13 unchanged lines hidden (view full) ---

852 * remove each one from .MAKE.EXPORTED.
853 * If we are removing them all,
854 * just delete .MAKE.EXPORTED below.
855 */
856 if (vlist == str) {
857 n = snprintf(tmp, sizeof(tmp),
858 "${" MAKE_EXPORTED ":N%s}", v->name);
859 if (n < (int)sizeof(tmp)) {
859 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
860 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, FALSE, TRUE);
860 Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
861 free(cp);
862 }
863 }
864 }
865 free(as);
866 free(av);
867 if (vlist != str) {

--- 38 unchanged lines hidden (view full) ---

906 char *expanded_name = NULL;
907
908 /*
909 * We only look for a variable in the given context since anything set
910 * here will override anything in a lower context, so there's not much
911 * point in searching them all just to save a bit of memory...
912 */
913 if (strchr(name, '$') != NULL) {
861 Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
862 free(cp);
863 }
864 }
865 }
866 free(as);
867 free(av);
868 if (vlist != str) {

--- 38 unchanged lines hidden (view full) ---

907 char *expanded_name = NULL;
908
909 /*
910 * We only look for a variable in the given context since anything set
911 * here will override anything in a lower context, so there's not much
912 * point in searching them all just to save a bit of memory...
913 */
914 if (strchr(name, '$') != NULL) {
914 expanded_name = Var_Subst(NULL, name, ctxt, 0);
915 expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
915 if (expanded_name[0] == 0) {
916 if (DEBUG(VAR)) {
917 fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
918 "name expands to empty string - ignored\n",
919 name, val);
920 }
921 free(expanded_name);
922 return;

--- 54 unchanged lines hidden (view full) ---

977 if (varNoExportEnv != TRUE)
978 setenv(name, val, 1);
979
980 Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
981 }
982
983
984 out:
916 if (expanded_name[0] == 0) {
917 if (DEBUG(VAR)) {
918 fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
919 "name expands to empty string - ignored\n",
920 name, val);
921 }
922 free(expanded_name);
923 return;

--- 54 unchanged lines hidden (view full) ---

978 if (varNoExportEnv != TRUE)
979 setenv(name, val, 1);
980
981 Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
982 }
983
984
985 out:
985 if (expanded_name != NULL)
986 free(expanded_name);
986 free(expanded_name);
987 if (v != NULL)
988 VarFreeEnv(v, TRUE);
989}
990
991/*-
992 *-----------------------------------------------------------------------
993 * Var_Append --
994 * The variable of the given name has the given value appended to it in

--- 23 unchanged lines hidden (view full) ---

1018void
1019Var_Append(const char *name, const char *val, GNode *ctxt)
1020{
1021 Var *v;
1022 Hash_Entry *h;
1023 char *expanded_name = NULL;
1024
1025 if (strchr(name, '$') != NULL) {
987 if (v != NULL)
988 VarFreeEnv(v, TRUE);
989}
990
991/*-
992 *-----------------------------------------------------------------------
993 * Var_Append --
994 * The variable of the given name has the given value appended to it in

--- 23 unchanged lines hidden (view full) ---

1018void
1019Var_Append(const char *name, const char *val, GNode *ctxt)
1020{
1021 Var *v;
1022 Hash_Entry *h;
1023 char *expanded_name = NULL;
1024
1025 if (strchr(name, '$') != NULL) {
1026 expanded_name = Var_Subst(NULL, name, ctxt, 0);
1026 expanded_name = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
1027 if (expanded_name[0] == 0) {
1028 if (DEBUG(VAR)) {
1029 fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
1030 "name expands to empty string - ignored\n",
1031 name, val);
1032 }
1033 free(expanded_name);
1034 return;

--- 21 unchanged lines hidden (view full) ---

1056 * it in the environment, but then we should provide a way to
1057 * export other variables...)
1058 */
1059 v->flags &= ~VAR_FROM_ENV;
1060 h = Hash_CreateEntry(&ctxt->context, name, NULL);
1061 Hash_SetValue(h, v);
1062 }
1063 }
1027 if (expanded_name[0] == 0) {
1028 if (DEBUG(VAR)) {
1029 fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
1030 "name expands to empty string - ignored\n",
1031 name, val);
1032 }
1033 free(expanded_name);
1034 return;

--- 21 unchanged lines hidden (view full) ---

1056 * it in the environment, but then we should provide a way to
1057 * export other variables...)
1058 */
1059 v->flags &= ~VAR_FROM_ENV;
1060 h = Hash_CreateEntry(&ctxt->context, name, NULL);
1061 Hash_SetValue(h, v);
1062 }
1063 }
1064 if (expanded_name != NULL)
1065 free(expanded_name);
1064 free(expanded_name);
1066}
1067
1068/*-
1069 *-----------------------------------------------------------------------
1070 * Var_Exists --
1071 * See if the given variable exists.
1072 *
1073 * Input:

--- 10 unchanged lines hidden (view full) ---

1084 */
1085Boolean
1086Var_Exists(const char *name, GNode *ctxt)
1087{
1088 Var *v;
1089 char *cp;
1090
1091 if ((cp = strchr(name, '$')) != NULL) {
1065}
1066
1067/*-
1068 *-----------------------------------------------------------------------
1069 * Var_Exists --
1070 * See if the given variable exists.
1071 *
1072 * Input:

--- 10 unchanged lines hidden (view full) ---

1083 */
1084Boolean
1085Var_Exists(const char *name, GNode *ctxt)
1086{
1087 Var *v;
1088 char *cp;
1089
1090 if ((cp = strchr(name, '$')) != NULL) {
1092 cp = Var_Subst(NULL, name, ctxt, FALSE);
1091 cp = Var_Subst(NULL, name, ctxt, FALSE, TRUE);
1093 }
1094 v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
1092 }
1093 v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
1095 if (cp != NULL) {
1096 free(cp);
1097 }
1094 free(cp);
1098 if (v == NULL) {
1099 return(FALSE);
1100 } else {
1101 (void)VarFreeEnv(v, TRUE);
1102 }
1103 return(TRUE);
1104}
1105

--- 278 unchanged lines hidden (view full) ---

1384 char *varexp;
1385
1386 if (addSpace && vpstate->varSpace)
1387 Buf_AddByte(buf, vpstate->varSpace);
1388
1389 addSpace = TRUE;
1390
1391 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
1095 if (v == NULL) {
1096 return(FALSE);
1097 } else {
1098 (void)VarFreeEnv(v, TRUE);
1099 }
1100 return(TRUE);
1101}
1102

--- 278 unchanged lines hidden (view full) ---

1381 char *varexp;
1382
1383 if (addSpace && vpstate->varSpace)
1384 Buf_AddByte(buf, vpstate->varSpace);
1385
1386 addSpace = TRUE;
1387
1388 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
1392 varexp = Var_Subst(NULL, pat->rhs, ctx, 0);
1389 varexp = Var_Subst(NULL, pat->rhs, ctx, FALSE, TRUE);
1393 Str_SYSVSubst(buf, varexp, ptr, len);
1394 free(varexp);
1395 } else {
1396 Buf_AddBytes(buf, strlen(word), word);
1397 }
1398
1399 return(addSpace);
1400}

--- 403 unchanged lines hidden (view full) ---

1804 void *loopp)
1805{
1806 VarLoop_t *loop = (VarLoop_t *)loopp;
1807 char *s;
1808 int slen;
1809
1810 if (word && *word) {
1811 Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
1390 Str_SYSVSubst(buf, varexp, ptr, len);
1391 free(varexp);
1392 } else {
1393 Buf_AddBytes(buf, strlen(word), word);
1394 }
1395
1396 return(addSpace);
1397}

--- 403 unchanged lines hidden (view full) ---

1801 void *loopp)
1802{
1803 VarLoop_t *loop = (VarLoop_t *)loopp;
1804 char *s;
1805 int slen;
1806
1807 if (word && *word) {
1808 Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
1812 s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum);
1809 s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum, TRUE);
1813 if (s != NULL && *s != '\0') {
1814 if (addSpace && *s != '\n')
1815 Buf_AddByte(buf, ' ');
1816 Buf_AddBytes(buf, (slen = strlen(s)), s);
1817 addSpace = (slen > 0 && s[slen - 1] != '\n');
1818 free(s);
1819 }
1820 }

--- 364 unchanged lines hidden (view full) ---

2185 int len;
2186 void *freeIt;
2187
2188 /*
2189 * If unescaped dollar sign not before the
2190 * delimiter, assume it's a variable
2191 * substitution and recurse.
2192 */
1810 if (s != NULL && *s != '\0') {
1811 if (addSpace && *s != '\n')
1812 Buf_AddByte(buf, ' ');
1813 Buf_AddBytes(buf, (slen = strlen(s)), s);
1814 addSpace = (slen > 0 && s[slen - 1] != '\n');
1815 free(s);
1816 }
1817 }

--- 364 unchanged lines hidden (view full) ---

2182 int len;
2183 void *freeIt;
2184
2185 /*
2186 * If unescaped dollar sign not before the
2187 * delimiter, assume it's a variable
2188 * substitution and recurse.
2189 */
2193 cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
2190 cp2 = Var_Parse(cp, ctxt, errnum, TRUE, &len, &freeIt);
2194 Buf_AddBytes(&buf, strlen(cp2), cp2);
2191 Buf_AddBytes(&buf, strlen(cp2), cp2);
2195 if (freeIt)
2196 free(freeIt);
2192 free(freeIt);
2197 cp += len - 1;
2198 } else {
2199 const char *cp2 = &cp[1];
2200
2201 if (*cp2 == PROPEN || *cp2 == BROPEN) {
2202 /*
2203 * Find the end of this variable reference
2204 * and suck it in without further ado.

--- 36 unchanged lines hidden (view full) ---

2241 if (DEBUG(VAR))
2242 fprintf(debug_file, "Modifier pattern: \"%s\"\n", rstr);
2243 return rstr;
2244}
2245
2246/*-
2247 *-----------------------------------------------------------------------
2248 * VarQuote --
2193 cp += len - 1;
2194 } else {
2195 const char *cp2 = &cp[1];
2196
2197 if (*cp2 == PROPEN || *cp2 == BROPEN) {
2198 /*
2199 * Find the end of this variable reference
2200 * and suck it in without further ado.

--- 36 unchanged lines hidden (view full) ---

2237 if (DEBUG(VAR))
2238 fprintf(debug_file, "Modifier pattern: \"%s\"\n", rstr);
2239 return rstr;
2240}
2241
2242/*-
2243 *-----------------------------------------------------------------------
2244 * VarQuote --
2249 * Quote shell meta-characters in the string
2245 * Quote shell meta-characters and space characters in the string
2250 *
2251 * Results:
2252 * The quoted string
2253 *
2254 * Side Effects:
2255 * None.
2256 *
2257 *-----------------------------------------------------------------------
2258 */
2259static char *
2260VarQuote(char *str)
2261{
2262
2263 Buffer buf;
2246 *
2247 * Results:
2248 * The quoted string
2249 *
2250 * Side Effects:
2251 * None.
2252 *
2253 *-----------------------------------------------------------------------
2254 */
2255static char *
2256VarQuote(char *str)
2257{
2258
2259 Buffer buf;
2264 /* This should cover most shells :-( */
2265 static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
2266 const char *newline;
2260 const char *newline;
2267 size_t len, nlen;
2261 size_t nlen;
2268
2269 if ((newline = Shell_GetNewline()) == NULL)
2270 newline = "\\\n";
2271 nlen = strlen(newline);
2272
2273 Buf_Init(&buf, 0);
2262
2263 if ((newline = Shell_GetNewline()) == NULL)
2264 newline = "\\\n";
2265 nlen = strlen(newline);
2266
2267 Buf_Init(&buf, 0);
2274 while (*str != '\0') {
2275 if ((len = strcspn(str, meta)) != 0) {
2276 Buf_AddBytes(&buf, len, str);
2277 str += len;
2278 } else if (*str == '\n') {
2268
2269 for (; *str != '\0'; str++) {
2270 if (*str == '\n') {
2279 Buf_AddBytes(&buf, nlen, newline);
2271 Buf_AddBytes(&buf, nlen, newline);
2280 ++str;
2281 } else {
2282 Buf_AddByte(&buf, '\\');
2283 Buf_AddByte(&buf, *str);
2284 ++str;
2272 continue;
2285 }
2273 }
2274 if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
2275 Buf_AddByte(&buf, '\\');
2276 Buf_AddByte(&buf, *str);
2286 }
2277 }
2278
2287 str = Buf_Destroy(&buf, FALSE);
2288 if (DEBUG(VAR))
2289 fprintf(debug_file, "QuoteMeta: [%s]\n", str);
2290 return str;
2291}
2292
2293/*-
2294 *-----------------------------------------------------------------------

--- 168 unchanged lines hidden (view full) ---

2463
2464/* we now have some modifiers with long names */
2465#define STRMOD_MATCH(s, want, n) \
2466 (strncmp(s, want, n) == 0 && (s[n] == endc || s[n] == ':'))
2467
2468static char *
2469ApplyModifiers(char *nstr, const char *tstr,
2470 int startc, int endc,
2279 str = Buf_Destroy(&buf, FALSE);
2280 if (DEBUG(VAR))
2281 fprintf(debug_file, "QuoteMeta: [%s]\n", str);
2282 return str;
2283}
2284
2285/*-
2286 *-----------------------------------------------------------------------

--- 168 unchanged lines hidden (view full) ---

2455
2456/* we now have some modifiers with long names */
2457#define STRMOD_MATCH(s, want, n) \
2458 (strncmp(s, want, n) == 0 && (s[n] == endc || s[n] == ':'))
2459
2460static char *
2461ApplyModifiers(char *nstr, const char *tstr,
2462 int startc, int endc,
2471 Var *v, GNode *ctxt, Boolean errnum,
2463 Var *v, GNode *ctxt, Boolean errnum, Boolean wantit,
2472 int *lengthPtr, void **freePtr)
2473{
2474 const char *start;
2475 const char *cp; /* Secondary pointer into str (place marker
2476 * for tstr) */
2477 char *newStr; /* New value to return */
2478 char termc; /* Character which terminated scan */
2479 int cnt; /* Used to count brace pairs when variable in

--- 14 unchanged lines hidden (view full) ---

2494 /*
2495 * We may have some complex modifiers in a variable.
2496 */
2497 void *freeIt;
2498 char *rval;
2499 int rlen;
2500 int c;
2501
2464 int *lengthPtr, void **freePtr)
2465{
2466 const char *start;
2467 const char *cp; /* Secondary pointer into str (place marker
2468 * for tstr) */
2469 char *newStr; /* New value to return */
2470 char termc; /* Character which terminated scan */
2471 int cnt; /* Used to count brace pairs when variable in

--- 14 unchanged lines hidden (view full) ---

2486 /*
2487 * We may have some complex modifiers in a variable.
2488 */
2489 void *freeIt;
2490 char *rval;
2491 int rlen;
2492 int c;
2493
2502 rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
2494 rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
2503
2504 /*
2505 * If we have not parsed up to endc or ':',
2506 * we are not interested.
2507 */
2508 if (rval != NULL && *rval &&
2509 (c = tstr[rlen]) != '\0' &&
2510 c != ':' &&
2511 c != endc) {
2495
2496 /*
2497 * If we have not parsed up to endc or ':',
2498 * we are not interested.
2499 */
2500 if (rval != NULL && *rval &&
2501 (c = tstr[rlen]) != '\0' &&
2502 c != ':' &&
2503 c != endc) {
2512 if (freeIt)
2513 free(freeIt);
2504 free(freeIt);
2514 goto apply_mods;
2515 }
2516
2517 if (DEBUG(VAR)) {
2518 fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
2519 rval, rlen, tstr, rlen, tstr + rlen);
2520 }
2521
2522 tstr += rlen;
2523
2524 if (rval != NULL && *rval) {
2525 int used;
2526
2527 nstr = ApplyModifiers(nstr, rval,
2528 0, 0,
2505 goto apply_mods;
2506 }
2507
2508 if (DEBUG(VAR)) {
2509 fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
2510 rval, rlen, tstr, rlen, tstr + rlen);
2511 }
2512
2513 tstr += rlen;
2514
2515 if (rval != NULL && *rval) {
2516 int used;
2517
2518 nstr = ApplyModifiers(nstr, rval,
2519 0, 0,
2529 v, ctxt, errnum, &used, freePtr);
2520 v, ctxt, errnum, wantit, &used, freePtr);
2530 if (nstr == var_Error
2531 || (nstr == varNoError && errnum == 0)
2532 || strlen(rval) != (size_t) used) {
2521 if (nstr == var_Error
2522 || (nstr == varNoError && errnum == 0)
2523 || strlen(rval) != (size_t) used) {
2533 if (freeIt)
2534 free(freeIt);
2524 free(freeIt);
2535 goto out; /* error already reported */
2536 }
2537 }
2525 goto out; /* error already reported */
2526 }
2527 }
2538 if (freeIt)
2539 free(freeIt);
2528 free(freeIt);
2540 if (*tstr == ':')
2541 tstr++;
2542 else if (!*tstr && endc) {
2543 Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc, v->name);
2544 goto out;
2545 }
2546 continue;
2547 }

--- 12 unchanged lines hidden (view full) ---

2560 /*
2561 * "::=", "::!=", "::+=", or "::?="
2562 */
2563 GNode *v_ctxt; /* context where v belongs */
2564 const char *emsg;
2565 char *sv_name;
2566 VarPattern pattern;
2567 int how;
2529 if (*tstr == ':')
2530 tstr++;
2531 else if (!*tstr && endc) {
2532 Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc, v->name);
2533 goto out;
2534 }
2535 continue;
2536 }

--- 12 unchanged lines hidden (view full) ---

2549 /*
2550 * "::=", "::!=", "::+=", or "::?="
2551 */
2552 GNode *v_ctxt; /* context where v belongs */
2553 const char *emsg;
2554 char *sv_name;
2555 VarPattern pattern;
2556 int how;
2557 int flags;
2568
2569 if (v->name[0] == 0)
2570 goto bad_modifier;
2571
2572 v_ctxt = ctxt;
2573 sv_name = NULL;
2574 ++tstr;
2575 if (v->flags & VAR_JUNK) {

--- 19 unchanged lines hidden (view full) ---

2595 break;
2596 default:
2597 cp = ++tstr;
2598 break;
2599 }
2600 delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
2601 pattern.flags = 0;
2602
2558
2559 if (v->name[0] == 0)
2560 goto bad_modifier;
2561
2562 v_ctxt = ctxt;
2563 sv_name = NULL;
2564 ++tstr;
2565 if (v->flags & VAR_JUNK) {

--- 19 unchanged lines hidden (view full) ---

2585 break;
2586 default:
2587 cp = ++tstr;
2588 break;
2589 }
2590 delim = startc == PROPEN ? PRCLOSE : BRCLOSE;
2591 pattern.flags = 0;
2592
2593 flags = (wantit) ? 0 : VAR_NOSUBST;
2603 pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2594 pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2604 &cp, delim, NULL,
2595 &cp, delim, &flags,
2605 &pattern.rightLen,
2606 NULL);
2607 if (v->flags & VAR_JUNK) {
2608 /* restore original name */
2609 free(v->name);
2610 v->name = sv_name;
2611 }
2612 if (pattern.rhs == NULL)
2613 goto cleanup;
2614
2615 termc = *--cp;
2616 delim = '\0';
2617
2596 &pattern.rightLen,
2597 NULL);
2598 if (v->flags & VAR_JUNK) {
2599 /* restore original name */
2600 free(v->name);
2601 v->name = sv_name;
2602 }
2603 if (pattern.rhs == NULL)
2604 goto cleanup;
2605
2606 termc = *--cp;
2607 delim = '\0';
2608
2618 switch (how) {
2619 case '+':
2620 Var_Append(v->name, pattern.rhs, v_ctxt);
2621 break;
2622 case '!':
2623 newStr = Cmd_Exec(pattern.rhs, &emsg);
2624 if (emsg)
2625 Error(emsg, nstr);
2626 else
2627 Var_Set(v->name, newStr, v_ctxt, 0);
2628 if (newStr)
2609 if (wantit) {
2610 switch (how) {
2611 case '+':
2612 Var_Append(v->name, pattern.rhs, v_ctxt);
2613 break;
2614 case '!':
2615 newStr = Cmd_Exec(pattern.rhs, &emsg);
2616 if (emsg)
2617 Error(emsg, nstr);
2618 else
2619 Var_Set(v->name, newStr, v_ctxt, 0);
2629 free(newStr);
2620 free(newStr);
2630 break;
2631 case '?':
2632 if ((v->flags & VAR_JUNK) == 0)
2633 break;
2621 break;
2634 /* FALLTHROUGH */
2635 default:
2636 Var_Set(v->name, pattern.rhs, v_ctxt, 0);
2637 break;
2622 case '?':
2623 if ((v->flags & VAR_JUNK) == 0)
2624 break;
2625 /* FALLTHROUGH */
2626 default:
2627 Var_Set(v->name, pattern.rhs, v_ctxt, 0);
2628 break;
2629 }
2638 }
2639 free(UNCONST(pattern.rhs));
2640 newStr = varNoError;
2641 break;
2642 }
2643 goto default_case; /* "::<unrecognised>" */
2644 }
2645 case '@':

--- 25 unchanged lines hidden (view full) ---

2671 free(loop.tvar);
2672 free(loop.str);
2673 break;
2674 }
2675 case 'D':
2676 case 'U':
2677 {
2678 Buffer buf; /* Buffer for patterns */
2630 }
2631 free(UNCONST(pattern.rhs));
2632 newStr = varNoError;
2633 break;
2634 }
2635 goto default_case; /* "::<unrecognised>" */
2636 }
2637 case '@':

--- 25 unchanged lines hidden (view full) ---

2663 free(loop.tvar);
2664 free(loop.str);
2665 break;
2666 }
2667 case 'D':
2668 case 'U':
2669 {
2670 Buffer buf; /* Buffer for patterns */
2679 int wantit; /* want data in buffer */
2671 int wantit_; /* want data in buffer */
2680
2672
2673 if (wantit) {
2674 if (*tstr == 'U')
2675 wantit_ = ((v->flags & VAR_JUNK) != 0);
2676 else
2677 wantit_ = ((v->flags & VAR_JUNK) == 0);
2678 } else
2679 wantit_ = wantit;
2681 /*
2682 * Pass through tstr looking for 1) escaped delimiters,
2683 * '$'s and backslashes (place the escaped character in
2684 * uninterpreted) and 2) unescaped $'s that aren't before
2685 * the delimiter (expand the variable substitution).
2686 * The result is left in the Buffer buf.
2687 */
2688 Buf_Init(&buf, 0);

--- 12 unchanged lines hidden (view full) ---

2701 /*
2702 * If unescaped dollar sign, assume it's a
2703 * variable substitution and recurse.
2704 */
2705 char *cp2;
2706 int len;
2707 void *freeIt;
2708
2680 /*
2681 * Pass through tstr looking for 1) escaped delimiters,
2682 * '$'s and backslashes (place the escaped character in
2683 * uninterpreted) and 2) unescaped $'s that aren't before
2684 * the delimiter (expand the variable substitution).
2685 * The result is left in the Buffer buf.
2686 */
2687 Buf_Init(&buf, 0);

--- 12 unchanged lines hidden (view full) ---

2700 /*
2701 * If unescaped dollar sign, assume it's a
2702 * variable substitution and recurse.
2703 */
2704 char *cp2;
2705 int len;
2706 void *freeIt;
2707
2709 cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt);
2708 cp2 = Var_Parse(cp, ctxt, errnum, wantit_, &len, &freeIt);
2710 Buf_AddBytes(&buf, strlen(cp2), cp2);
2709 Buf_AddBytes(&buf, strlen(cp2), cp2);
2711 if (freeIt)
2712 free(freeIt);
2710 free(freeIt);
2713 cp += len - 1;
2714 } else {
2715 Buf_AddByte(&buf, *cp);
2716 }
2717 }
2718
2719 termc = *cp;
2720
2711 cp += len - 1;
2712 } else {
2713 Buf_AddByte(&buf, *cp);
2714 }
2715 }
2716
2717 termc = *cp;
2718
2721 if (*tstr == 'U')
2722 wantit = ((v->flags & VAR_JUNK) != 0);
2723 else
2724 wantit = ((v->flags & VAR_JUNK) == 0);
2725 if ((v->flags & VAR_JUNK) != 0)
2726 v->flags |= VAR_KEEP;
2719 if ((v->flags & VAR_JUNK) != 0)
2720 v->flags |= VAR_KEEP;
2727 if (wantit) {
2721 if (wantit_) {
2728 newStr = Buf_Destroy(&buf, FALSE);
2729 } else {
2730 newStr = nstr;
2731 Buf_Destroy(&buf, TRUE);
2732 }
2733 break;
2734 }
2735 case 'L':

--- 28 unchanged lines hidden (view full) ---

2764 }
2765 case '!':
2766 {
2767 const char *emsg;
2768 VarPattern pattern;
2769 pattern.flags = 0;
2770
2771 delim = '!';
2722 newStr = Buf_Destroy(&buf, FALSE);
2723 } else {
2724 newStr = nstr;
2725 Buf_Destroy(&buf, TRUE);
2726 }
2727 break;
2728 }
2729 case 'L':

--- 28 unchanged lines hidden (view full) ---

2758 }
2759 case '!':
2760 {
2761 const char *emsg;
2762 VarPattern pattern;
2763 pattern.flags = 0;
2764
2765 delim = '!';
2772
2766 emsg = NULL;
2773 cp = ++tstr;
2774 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2775 &cp, delim,
2776 NULL, &pattern.rightLen,
2777 NULL)) == NULL)
2778 goto cleanup;
2767 cp = ++tstr;
2768 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
2769 &cp, delim,
2770 NULL, &pattern.rightLen,
2771 NULL)) == NULL)
2772 goto cleanup;
2779 newStr = Cmd_Exec(pattern.rhs, &emsg);
2773 if (wantit)
2774 newStr = Cmd_Exec(pattern.rhs, &emsg);
2775 else
2776 newStr = varNoError;
2780 free(UNCONST(pattern.rhs));
2781 if (emsg)
2782 Error(emsg, nstr);
2783 termc = *cp;
2784 delim = '\0';
2785 if (v->flags & VAR_JUNK) {
2786 v->flags |= VAR_KEEP;
2787 }

--- 359 unchanged lines hidden (view full) ---

3147 pattern = bmake_strndup(tstr+1, endpat - (tstr + 1));
3148 }
3149 if (needSubst) {
3150 /*
3151 * pattern contains embedded '$', so use Var_Subst to
3152 * expand it.
3153 */
3154 cp2 = pattern;
2777 free(UNCONST(pattern.rhs));
2778 if (emsg)
2779 Error(emsg, nstr);
2780 termc = *cp;
2781 delim = '\0';
2782 if (v->flags & VAR_JUNK) {
2783 v->flags |= VAR_KEEP;
2784 }

--- 359 unchanged lines hidden (view full) ---

3144 pattern = bmake_strndup(tstr+1, endpat - (tstr + 1));
3145 }
3146 if (needSubst) {
3147 /*
3148 * pattern contains embedded '$', so use Var_Subst to
3149 * expand it.
3150 */
3151 cp2 = pattern;
3155 pattern = Var_Subst(NULL, cp2, ctxt, errnum);
3152 pattern = Var_Subst(NULL, cp2, ctxt, errnum, TRUE);
3156 free(cp2);
3157 }
3158 if (DEBUG(VAR))
3159 fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
3160 v->name, nstr, pattern);
3161 if (*tstr == 'M') {
3162 newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
3163 pattern);

--- 69 unchanged lines hidden (view full) ---

3233 free(UNCONST(pattern.rhs));
3234 delim = '\0';
3235 break;
3236 }
3237 case '?':
3238 {
3239 VarPattern pattern;
3240 Boolean value;
3153 free(cp2);
3154 }
3155 if (DEBUG(VAR))
3156 fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
3157 v->name, nstr, pattern);
3158 if (*tstr == 'M') {
3159 newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
3160 pattern);

--- 69 unchanged lines hidden (view full) ---

3230 free(UNCONST(pattern.rhs));
3231 delim = '\0';
3232 break;
3233 }
3234 case '?':
3235 {
3236 VarPattern pattern;
3237 Boolean value;
3241
3238 int cond_rc;
3239 int lhs_flags, rhs_flags;
3240
3242 /* find ':', and then substitute accordingly */
3241 /* find ':', and then substitute accordingly */
3243
3242 if (wantit) {
3243 cond_rc = Cond_EvalExpression(NULL, v->name, &value, 0, FALSE);
3244 if (cond_rc == COND_INVALID) {
3245 lhs_flags = rhs_flags = VAR_NOSUBST;
3246 } else if (value) {
3247 lhs_flags = 0;
3248 rhs_flags = VAR_NOSUBST;
3249 } else {
3250 lhs_flags = VAR_NOSUBST;
3251 rhs_flags = 0;
3252 }
3253 } else {
3254 /* we are just consuming and discarding */
3255 cond_rc = value = 0;
3256 lhs_flags = rhs_flags = VAR_NOSUBST;
3257 }
3244 pattern.flags = 0;
3245
3246 cp = ++tstr;
3247 delim = ':';
3248 if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
3258 pattern.flags = 0;
3259
3260 cp = ++tstr;
3261 delim = ':';
3262 if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum,
3249 &cp, delim, NULL,
3263 &cp, delim, &lhs_flags,
3250 &pattern.leftLen,
3251 NULL)) == NULL)
3252 goto cleanup;
3253
3254 /* BROPEN or PROPEN */
3255 delim = endc;
3256 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
3264 &pattern.leftLen,
3265 NULL)) == NULL)
3266 goto cleanup;
3267
3268 /* BROPEN or PROPEN */
3269 delim = endc;
3270 if ((pattern.rhs = VarGetPattern(ctxt, &parsestate, errnum,
3257 &cp, delim, NULL,
3271 &cp, delim, &rhs_flags,
3258 &pattern.rightLen,
3259 NULL)) == NULL)
3260 goto cleanup;
3261
3262 termc = *--cp;
3263 delim = '\0';
3272 &pattern.rightLen,
3273 NULL)) == NULL)
3274 goto cleanup;
3275
3276 termc = *--cp;
3277 delim = '\0';
3264 if (Cond_EvalExpression(NULL, v->name, &value, 0, FALSE)
3265 == COND_INVALID) {
3278 if (cond_rc == COND_INVALID) {
3266 Error("Bad conditional expression `%s' in %s?%s:%s",
3267 v->name, v->name, pattern.lhs, pattern.rhs);
3268 goto cleanup;
3269 }
3270
3271 if (value) {
3272 newStr = UNCONST(pattern.lhs);
3273 free(UNCONST(pattern.rhs));

--- 145 unchanged lines hidden (view full) ---

3419 termc = *cp;
3420 break;
3421 }
3422 goto default_case;
3423#ifdef SUNSHCMD
3424 case 's':
3425 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
3426 const char *emsg;
3279 Error("Bad conditional expression `%s' in %s?%s:%s",
3280 v->name, v->name, pattern.lhs, pattern.rhs);
3281 goto cleanup;
3282 }
3283
3284 if (value) {
3285 newStr = UNCONST(pattern.lhs);
3286 free(UNCONST(pattern.rhs));

--- 145 unchanged lines hidden (view full) ---

3432 termc = *cp;
3433 break;
3434 }
3435 goto default_case;
3436#ifdef SUNSHCMD
3437 case 's':
3438 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
3439 const char *emsg;
3427 newStr = Cmd_Exec(nstr, &emsg);
3428 if (emsg)
3429 Error(emsg, nstr);
3440 if (wantit) {
3441 newStr = Cmd_Exec(nstr, &emsg);
3442 if (emsg)
3443 Error(emsg, nstr);
3444 } else
3445 newStr = varNoError;
3430 cp = tstr + 2;
3431 termc = *cp;
3432 break;
3433 }
3434 goto default_case;
3435#endif
3436 default:
3437 default_case:

--- 104 unchanged lines hidden (view full) ---

3542 Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr, ":)}"), tstr,
3543 v->name);
3544
3545 cleanup:
3546 *lengthPtr = cp - start;
3547 if (delim != '\0')
3548 Error("Unclosed substitution for %s (%c missing)",
3549 v->name, delim);
3446 cp = tstr + 2;
3447 termc = *cp;
3448 break;
3449 }
3450 goto default_case;
3451#endif
3452 default:
3453 default_case:

--- 104 unchanged lines hidden (view full) ---

3558 Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr, ":)}"), tstr,
3559 v->name);
3560
3561 cleanup:
3562 *lengthPtr = cp - start;
3563 if (delim != '\0')
3564 Error("Unclosed substitution for %s (%c missing)",
3565 v->name, delim);
3550 if (*freePtr) {
3551 free(*freePtr);
3552 *freePtr = NULL;
3553 }
3566 free(*freePtr);
3567 *freePtr = NULL;
3554 return (var_Error);
3555}
3556
3557/*-
3558 *-----------------------------------------------------------------------
3559 * Var_Parse --
3560 * Given the start of a variable invocation, extract the variable
3561 * name and find its value, then modify it according to the
3562 * specification.
3563 *
3564 * Input:
3565 * str The string to parse
3566 * ctxt The context for the variable
3567 * errnum TRUE if undefined variables are an error
3568 return (var_Error);
3569}
3570
3571/*-
3572 *-----------------------------------------------------------------------
3573 * Var_Parse --
3574 * Given the start of a variable invocation, extract the variable
3575 * name and find its value, then modify it according to the
3576 * specification.
3577 *
3578 * Input:
3579 * str The string to parse
3580 * ctxt The context for the variable
3581 * errnum TRUE if undefined variables are an error
3582 * wantit TRUE if we actually want the result
3568 * lengthPtr OUT: The length of the specification
3569 * freePtr OUT: Non-NULL if caller should free *freePtr
3570 *
3571 * Results:
3572 * The (possibly-modified) value of the variable or var_Error if the
3573 * specification is invalid. The length of the specification is
3574 * placed in *lengthPtr (for invalid specifications, this is just
3575 * 2...?).
3576 * If *freePtr is non-NULL then it's a pointer that the caller
3577 * should pass to free() to free memory used by the result.
3578 *
3579 * Side Effects:
3580 * None.
3581 *
3582 *-----------------------------------------------------------------------
3583 */
3584/* coverity[+alloc : arg-*4] */
3585char *
3583 * lengthPtr OUT: The length of the specification
3584 * freePtr OUT: Non-NULL if caller should free *freePtr
3585 *
3586 * Results:
3587 * The (possibly-modified) value of the variable or var_Error if the
3588 * specification is invalid. The length of the specification is
3589 * placed in *lengthPtr (for invalid specifications, this is just
3590 * 2...?).
3591 * If *freePtr is non-NULL then it's a pointer that the caller
3592 * should pass to free() to free memory used by the result.
3593 *
3594 * Side Effects:
3595 * None.
3596 *
3597 *-----------------------------------------------------------------------
3598 */
3599/* coverity[+alloc : arg-*4] */
3600char *
3586Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
3587 void **freePtr)
3601Var_Parse(const char *str, GNode *ctxt,
3602 Boolean errnum, Boolean wantit,
3603 int *lengthPtr, void **freePtr)
3588{
3589 const char *tstr; /* Pointer into str */
3590 Var *v; /* Variable in invocation */
3591 Boolean haveModifier;/* TRUE if have modifiers for the variable */
3592 char endc; /* Ending character when variable in parens
3593 * or braces */
3594 char startc; /* Starting character when variable in parens
3595 * or braces */

--- 88 unchanged lines hidden (view full) ---

3684 break;
3685 }
3686 /*
3687 * A variable inside a variable, expand
3688 */
3689 if (*tstr == '$') {
3690 int rlen;
3691 void *freeIt;
3604{
3605 const char *tstr; /* Pointer into str */
3606 Var *v; /* Variable in invocation */
3607 Boolean haveModifier;/* TRUE if have modifiers for the variable */
3608 char endc; /* Ending character when variable in parens
3609 * or braces */
3610 char startc; /* Starting character when variable in parens
3611 * or braces */

--- 88 unchanged lines hidden (view full) ---

3700 break;
3701 }
3702 /*
3703 * A variable inside a variable, expand
3704 */
3705 if (*tstr == '$') {
3706 int rlen;
3707 void *freeIt;
3692 char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
3708 char *rval = Var_Parse(tstr, ctxt, errnum, wantit, &rlen, &freeIt);
3693 if (rval != NULL) {
3694 Buf_AddBytes(&buf, strlen(rval), rval);
3695 }
3709 if (rval != NULL) {
3710 Buf_AddBytes(&buf, strlen(rval), rval);
3711 }
3696 if (freeIt)
3697 free(freeIt);
3712 free(freeIt);
3698 tstr += rlen - 1;
3699 }
3700 else
3701 Buf_AddByte(&buf, *tstr);
3702 }
3703 if (*tstr == ':') {
3704 haveModifier = TRUE;
3705 } else if (*tstr == endc) {

--- 126 unchanged lines hidden (view full) ---

3832 * necessary (there's a dollar sign somewhere in the variable's value)
3833 * we just call Var_Subst to do any other substitutions that are
3834 * necessary. Note that the value returned by Var_Subst will have
3835 * been dynamically-allocated, so it will need freeing when we
3836 * return.
3837 */
3838 nstr = Buf_GetAll(&v->val, NULL);
3839 if (strchr(nstr, '$') != NULL) {
3713 tstr += rlen - 1;
3714 }
3715 else
3716 Buf_AddByte(&buf, *tstr);
3717 }
3718 if (*tstr == ':') {
3719 haveModifier = TRUE;
3720 } else if (*tstr == endc) {

--- 126 unchanged lines hidden (view full) ---

3847 * necessary (there's a dollar sign somewhere in the variable's value)
3848 * we just call Var_Subst to do any other substitutions that are
3849 * necessary. Note that the value returned by Var_Subst will have
3850 * been dynamically-allocated, so it will need freeing when we
3851 * return.
3852 */
3853 nstr = Buf_GetAll(&v->val, NULL);
3854 if (strchr(nstr, '$') != NULL) {
3840 nstr = Var_Subst(NULL, nstr, ctxt, errnum);
3855 nstr = Var_Subst(NULL, nstr, ctxt, errnum, wantit);
3841 *freePtr = nstr;
3842 }
3843
3844 v->flags &= ~VAR_IN_USE;
3845
3846 if ((nstr != NULL) && (haveModifier || extramodifiers != NULL)) {
3847 void *extraFree;
3848 int used;
3849
3850 extraFree = NULL;
3851 if (extramodifiers != NULL) {
3852 nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
3856 *freePtr = nstr;
3857 }
3858
3859 v->flags &= ~VAR_IN_USE;
3860
3861 if ((nstr != NULL) && (haveModifier || extramodifiers != NULL)) {
3862 void *extraFree;
3863 int used;
3864
3865 extraFree = NULL;
3866 if (extramodifiers != NULL) {
3867 nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
3853 v, ctxt, errnum, &used, &extraFree);
3868 v, ctxt, errnum, wantit, &used, &extraFree);
3854 }
3855
3856 if (haveModifier) {
3857 /* Skip initial colon. */
3858 tstr++;
3859
3860 nstr = ApplyModifiers(nstr, tstr, startc, endc,
3869 }
3870
3871 if (haveModifier) {
3872 /* Skip initial colon. */
3873 tstr++;
3874
3875 nstr = ApplyModifiers(nstr, tstr, startc, endc,
3861 v, ctxt, errnum, &used, freePtr);
3876 v, ctxt, errnum, wantit, &used, freePtr);
3862 tstr += used;
3877 tstr += used;
3863 if (extraFree) {
3864 free(extraFree);
3865 }
3878 free(extraFree);
3866 } else {
3867 *freePtr = extraFree;
3868 }
3869 }
3870 if (*tstr) {
3871 *lengthPtr = tstr - start + 1;
3872 } else {
3873 *lengthPtr = tstr - start;

--- 45 unchanged lines hidden (view full) ---

3919 * If undefErr is TRUE, Parse_Error will be called when an undefined
3920 * variable is encountered.
3921 *
3922 * Input:
3923 * var Named variable || NULL for all
3924 * str the string which to substitute
3925 * ctxt the context wherein to find variables
3926 * undefErr TRUE if undefineds are an error
3879 } else {
3880 *freePtr = extraFree;
3881 }
3882 }
3883 if (*tstr) {
3884 *lengthPtr = tstr - start + 1;
3885 } else {
3886 *lengthPtr = tstr - start;

--- 45 unchanged lines hidden (view full) ---

3932 * If undefErr is TRUE, Parse_Error will be called when an undefined
3933 * variable is encountered.
3934 *
3935 * Input:
3936 * var Named variable || NULL for all
3937 * str the string which to substitute
3938 * ctxt the context wherein to find variables
3939 * undefErr TRUE if undefineds are an error
3940 * wantit TRUE if we actually want the result
3927 *
3928 * Results:
3929 * The resulting string.
3930 *
3931 * Side Effects:
3932 * None. The old string must be freed by the caller
3933 *-----------------------------------------------------------------------
3934 */
3935char *
3941 *
3942 * Results:
3943 * The resulting string.
3944 *
3945 * Side Effects:
3946 * None. The old string must be freed by the caller
3947 *-----------------------------------------------------------------------
3948 */
3949char *
3936Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
3950Var_Subst(const char *var, const char *str, GNode *ctxt,
3951 Boolean undefErr, Boolean wantit)
3937{
3938 Buffer buf; /* Buffer for forming things */
3939 char *val; /* Value to substitute for a variable */
3940 int length; /* Length of the variable invocation */
3941 Boolean trailingBslash; /* variable ends in \ */
3942 void *freeIt = NULL; /* Set if it should be freed */
3943 static Boolean errorReported; /* Set true if an error has already
3944 * been reported to prevent a plethora

--- 81 unchanged lines hidden (view full) ---

4026 expand = TRUE;
4027 break;
4028 }
4029 }
4030 if (!expand)
4031 continue;
4032 }
4033
3952{
3953 Buffer buf; /* Buffer for forming things */
3954 char *val; /* Value to substitute for a variable */
3955 int length; /* Length of the variable invocation */
3956 Boolean trailingBslash; /* variable ends in \ */
3957 void *freeIt = NULL; /* Set if it should be freed */
3958 static Boolean errorReported; /* Set true if an error has already
3959 * been reported to prevent a plethora

--- 81 unchanged lines hidden (view full) ---

4041 expand = TRUE;
4042 break;
4043 }
4044 }
4045 if (!expand)
4046 continue;
4047 }
4048
4034 val = Var_Parse(str, ctxt, undefErr, &length, &freeIt);
4049 val = Var_Parse(str, ctxt, undefErr, wantit, &length, &freeIt);
4035
4036 /*
4037 * When we come down here, val should either point to the
4038 * value of this variable, suitably modified, or be NULL.
4039 * Length should be the total length of the potential
4040 * variable invocation (from $ to end character...)
4041 */
4042 if (val == var_Error || val == varNoError) {

--- 31 unchanged lines hidden (view full) ---

4074 /*
4075 * Copy all the characters from the variable value straight
4076 * into the new string.
4077 */
4078 length = strlen(val);
4079 Buf_AddBytes(&buf, length, val);
4080 trailingBslash = length > 0 && val[length - 1] == '\\';
4081 }
4050
4051 /*
4052 * When we come down here, val should either point to the
4053 * value of this variable, suitably modified, or be NULL.
4054 * Length should be the total length of the potential
4055 * variable invocation (from $ to end character...)
4056 */
4057 if (val == var_Error || val == varNoError) {

--- 31 unchanged lines hidden (view full) ---

4089 /*
4090 * Copy all the characters from the variable value straight
4091 * into the new string.
4092 */
4093 length = strlen(val);
4094 Buf_AddBytes(&buf, length, val);
4095 trailingBslash = length > 0 && val[length - 1] == '\\';
4096 }
4082 if (freeIt) {
4083 free(freeIt);
4084 freeIt = NULL;
4085 }
4097 free(freeIt);
4098 freeIt = NULL;
4086 }
4087 }
4088
4089 return Buf_DestroyCompact(&buf);
4090}
4091
4092/*-
4093 *-----------------------------------------------------------------------

--- 101 unchanged lines hidden ---
4099 }
4100 }
4101
4102 return Buf_DestroyCompact(&buf);
4103}
4104
4105/*-
4106 *-----------------------------------------------------------------------

--- 101 unchanged lines hidden ---