diff options
author | joerg <joerg@pkgsrc.org> | 2009-09-18 20:55:21 +0000 |
---|---|---|
committer | joerg <joerg@pkgsrc.org> | 2009-09-18 20:55:21 +0000 |
commit | 1869e779310e24b43754c694c616566fa8eca3d7 (patch) | |
tree | 46c780c45309611e0cafd1ae55a8046d1a4b07eb /devel/bmake/files/var.c | |
parent | b952f7758718bf9fea8dc11ba8a00727a9a8cc6f (diff) | |
download | pkgsrc-1869e779310e24b43754c694c616566fa8eca3d7.tar.gz |
Import bmake-20090909:
- .MAKE.LEVEL, -C, SIGINFO support
- fixes for :M and \:
- vfork signal handling fixes e.g. for Solaris
Diffstat (limited to 'devel/bmake/files/var.c')
-rw-r--r-- | devel/bmake/files/var.c | 824 |
1 files changed, 418 insertions, 406 deletions
diff --git a/devel/bmake/files/var.c b/devel/bmake/files/var.c index 1df6a575405..9744fae5747 100644 --- a/devel/bmake/files/var.c +++ b/devel/bmake/files/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1.1.4 2008/11/11 19:32:29 joerg Exp $ */ +/* $NetBSD: var.c,v 1.1.1.5 2009/09/18 20:55:32 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: var.c,v 1.1.1.4 2008/11/11 19:32:29 joerg Exp $"; +static char rcsid[] = "$NetBSD: var.c,v 1.1.1.5 2009/09/18 20:55:32 joerg Exp $"; #else #include <sys/cdefs.h> #ifndef lint #if 0 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: var.c,v 1.1.1.4 2008/11/11 19:32:29 joerg Exp $"); +__RCSID("$NetBSD: var.c,v 1.1.1.5 2009/09/18 20:55:32 joerg Exp $"); #endif #endif /* not lint */ #endif @@ -86,31 +86,31 @@ __RCSID("$NetBSD: var.c,v 1.1.1.4 2008/11/11 19:32:29 joerg Exp $"); * Variable-handling functions * * Interface: - * Var_Set Set the value of a variable in the given - * context. The variable is created if it doesn't - * yet exist. The value and variable name need not - * be preserved. + * Var_Set Set the value of a variable in the given + * context. The variable is created if it doesn't + * yet exist. The value and variable name need not + * be preserved. * * Var_Append Append more characters to an existing variable - * in the given context. The variable needn't - * exist already -- it will be created if it doesn't. - * A space is placed between the old value and the - * new one. + * in the given context. The variable needn't + * exist already -- it will be created if it doesn't. + * A space is placed between the old value and the + * new one. * * Var_Exists See if a variable exists. * * Var_Value Return the value of a variable in a context or - * NULL if the variable is undefined. + * NULL if the variable is undefined. * * Var_Subst Substitute named variable, or all variables if * NULL in a string using - * the given context as the top-most one. If the - * third argument is non-zero, Parse_Error is - * called if any variables are undefined. + * the given context as the top-most one. If the + * third argument is non-zero, Parse_Error is + * called if any variables are undefined. * * Var_Parse Parse a variable expansion from a string and - * return the result and the number of characters - * consumed. + * return the result and the number of characters + * consumed. * * Var_Delete Delete a variable in a context. * @@ -118,7 +118,7 @@ __RCSID("$NetBSD: var.c,v 1.1.1.4 2008/11/11 19:32:29 joerg Exp $"); * * Debugging: * Var_Dump Print out all variables defined in the given - * context. + * context. * * XXX: There's a lot of duplication in these functions. */ @@ -175,8 +175,8 @@ GNode *VAR_CMD; /* variables defined on the command-line */ typedef struct Var { char *name; /* the variable's name */ - Buffer val; /* its value */ - int flags; /* miscellaneous status flags */ + Buffer val; /* its value */ + int flags; /* miscellaneous status flags */ #define VAR_IN_USE 1 /* Variable's value currently being used. * Used to avoid recursion */ #define VAR_FROM_ENV 2 /* Variable comes from the environment */ @@ -205,7 +205,7 @@ static int var_exportedVars = VAR_EXPORTED_NONE; * We pass this to Var_Export when doing the initial export * or after updating an exported var. */ -#define VAR_EXPORT_FORCE 1 +#define VAR_EXPORT_PARENT 1 /* Var*Pattern flags */ #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */ @@ -232,28 +232,28 @@ typedef struct { * several space-separated words). */ } Var_Parse_State; -/* struct passed as ClientData to VarSubstitute() for ":S/lhs/rhs/", +/* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/", * to VarSYSVMatch() for ":lhs=rhs". */ typedef struct { const char *lhs; /* String to match */ - int leftLen; /* Length of string */ + int leftLen; /* Length of string */ const char *rhs; /* Replacement string (w/ &'s removed) */ - int rightLen; /* Length of replacement */ - int flags; + int rightLen; /* Length of replacement */ + int flags; } VarPattern; -/* struct passed as ClientData to VarLoopExpand() for ":@tvar@str@" */ +/* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */ typedef struct { GNode *ctxt; /* variable context */ char *tvar; /* name of temp var */ - int tvarLen; + int tvarLen; char *str; /* string to expand */ - int strLen; + int strLen; int errnum; /* errnum for not defined */ } VarLoop_t; #ifndef NO_REGEX -/* struct passed as ClientData to VarRESubstitute() for ":C///" */ +/* struct passed as 'void *' to VarRESubstitute() for ":C///" */ typedef struct { regex_t re; int nsub; @@ -272,30 +272,30 @@ typedef struct { static Var *VarFind(const char *, GNode *, int); static void VarAdd(const char *, const char *, GNode *); static Boolean VarHead(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static Boolean VarTail(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static Boolean VarSuffix(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static Boolean VarRoot(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static Boolean VarMatch(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); #ifdef SYSVVARSUB static Boolean VarSYSVMatch(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); #endif static Boolean VarNoMatch(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); #ifndef NO_REGEX static void VarREError(int, regex_t *, const char *); static Boolean VarRESubstitute(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); #endif static Boolean VarSubstitute(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static Boolean VarLoopExpand(GNode *, Var_Parse_State *, - char *, Boolean, Buffer, ClientData); + char *, Boolean, Buffer *, void *); static char *VarGetPattern(GNode *, Var_Parse_State *, int, const char **, int, int *, int *, VarPattern *); @@ -303,12 +303,12 @@ static char *VarQuote(char *); static char *VarChangeCase(char *, int); static char *VarModify(GNode *, Var_Parse_State *, const char *, - Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer, ClientData), - ClientData); + Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer *, void *), + void *); static char *VarOrder(const char *, const char); static char *VarUniq(const char *); static int VarWordCompare(const void *, const void *); -static void VarPrintVar(ClientData); +static void VarPrintVar(void *); #define BROPEN '{' #define BRCLOSE '}' @@ -331,7 +331,7 @@ static void VarPrintVar(ClientData); * * Results: * A pointer to the structure describing the desired variable or - * NIL if the variable does not exist. + * NULL if the variable does not exist. * * Side Effects: * None @@ -341,7 +341,7 @@ static Var * VarFind(const char *name, GNode *ctxt, int flags) { Hash_Entry *var; - Var *v; + Var *v; /* * If the variable name begins with a '.', it could very well be one of @@ -397,15 +397,15 @@ VarFind(const char *name, GNode *ctxt, int flags) char *env; if ((env = getenv(name)) != NULL) { - int len; + int len; v = bmake_malloc(sizeof(Var)); v->name = bmake_strdup(name); len = strlen(env); - v->val = Buf_Init(len + 1); - Buf_AddBytes(v->val, len, (Byte *)env); + Buf_Init(&v->val, len + 1); + Buf_AddBytes(&v->val, len, env); v->flags = VAR_FROM_ENV; return (v); @@ -414,15 +414,15 @@ VarFind(const char *name, GNode *ctxt, int flags) { var = Hash_FindEntry(&VAR_GLOBAL->context, name); if (var == NULL) { - return ((Var *)NIL); + return NULL; } else { return ((Var *)Hash_GetValue(var)); } } else { - return((Var *)NIL); + return NULL; } } else if (var == NULL) { - return ((Var *)NIL); + return NULL; } else { return ((Var *)Hash_GetValue(var)); } @@ -450,7 +450,7 @@ VarFreeEnv(Var *v, Boolean destroy) if ((v->flags & VAR_FROM_ENV) == 0) return FALSE; free(v->name); - Buf_Destroy(v->val, destroy); + Buf_Destroy(&v->val, destroy); free(v); return TRUE; } @@ -478,14 +478,14 @@ static void VarAdd(const char *name, const char *val, GNode *ctxt) { Var *v; - int len; + int len; Hash_Entry *h; v = bmake_malloc(sizeof(Var)); len = val ? strlen(val) : 0; - v->val = Buf_Init(len+1); - Buf_AddBytes(v->val, len, (const Byte *)val); + Buf_Init(&v->val, len+1); + Buf_AddBytes(&v->val, len, val); v->flags = 0; @@ -530,7 +530,7 @@ Var_Delete(const char *name, GNode *ctxt) if (v->name != ln->name) free(v->name); Hash_DeleteEntry(&ctxt->context, ln); - Buf_Destroy(v->val, TRUE); + Buf_Destroy(&v->val, TRUE); free(v); } } @@ -541,9 +541,10 @@ Var_Delete(const char *name, GNode *ctxt) * We ignore make internal variables (those which start with '.') * Also we jump through some hoops to avoid calling setenv * more than necessary since it can leak. + * We only manipulate flags of vars if 'parent' is set. */ static int -Var_Export1(const char *name, int force) +Var_Export1(const char *name, int parent) { char tmp[BUFSIZ]; Var *v; @@ -568,40 +569,44 @@ Var_Export1(const char *name, int force) } } v = VarFind(name, VAR_GLOBAL, 0); - if (v == (Var *)NIL) { + if (v == NULL) { return 0; } - if (!force && + if (!parent && (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) { return 0; /* nothing to do */ } - val = (char *)Buf_GetAll(v->val, NULL); + val = Buf_GetAll(&v->val, NULL); if (strchr(val, '$')) { - /* Flag this as something we need to re-export */ - v->flags |= (VAR_EXPORTED|VAR_REEXPORT); - if (force) { + if (parent) { /* + * Flag this as something we need to re-export. * No point actually exporting it now though, * the child can do it at the last minute. */ + v->flags |= (VAR_EXPORTED|VAR_REEXPORT); return 1; } n = snprintf(tmp, sizeof(tmp), "${%s}", name); - if (n < sizeof(tmp)) { + if (n < (int)sizeof(tmp)) { val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0); setenv(name, val, 1); free(val); } } else { - v->flags &= ~VAR_REEXPORT; /* once will do */ - if (force || !(v->flags & VAR_EXPORTED)) { + if (parent) { + v->flags &= ~VAR_REEXPORT; /* once will do */ + } + if (parent || !(v->flags & VAR_EXPORTED)) { setenv(name, val, 1); } } /* * This is so Var_Set knows to call Var_Export again... */ - v->flags |= VAR_EXPORTED; + if (parent) { + v->flags |= VAR_EXPORTED; + } return 1; } @@ -637,12 +642,12 @@ Var_ExportVars(void) * We have a number of exported vars, */ n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}"); - if (n < sizeof(tmp)) { + if (n < (int)sizeof(tmp)) { char **av; char *as; int ac; int i; - + val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0); av = brk_string(val, &ac, FALSE, &as); for (i = 0; i < ac; i++) { @@ -693,7 +698,7 @@ Var_Export(char *str, int isExport) continue; } } - if (Var_Export1(name, VAR_EXPORT_FORCE)) { + if (Var_Export1(name, VAR_EXPORT_PARENT)) { if (VAR_EXPORTED_ALL != var_exportedVars) var_exportedVars = VAR_EXPORTED_YES; if (isExport) { @@ -738,20 +743,29 @@ void Var_Set(const char *name, const char *val, GNode *ctxt, int flags) { Var *v; - const char *cp = name; - + char *expanded_name = NULL; + /* * We only look for a variable in the given context since anything set * here will override anything in a lower context, so there's not much * point in searching them all just to save a bit of memory... */ - if ((name = strchr(cp, '$'))) { - name = Var_Subst(NULL, cp, ctxt, 0); - } else - name = cp; + if (strchr(name, '$') != NULL) { + expanded_name = Var_Subst(NULL, name, ctxt, 0); + if (expanded_name[0] == 0) { + if (DEBUG(VAR)) { + fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) " + "name expands to empty string - ignored\n", + name, val); + } + free(expanded_name); + return; + } + name = expanded_name; + } if (ctxt == VAR_GLOBAL) { v = VarFind(name, VAR_CMD, 0); - if (v != (Var *)NIL) { + if (v != NULL) { if ((v->flags & VAR_FROM_CMD)) { if (DEBUG(VAR)) { fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val); @@ -762,17 +776,17 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags) } } v = VarFind(name, ctxt, 0); - if (v == (Var *)NIL) { + if (v == NULL) { VarAdd(name, val, ctxt); } else { - Buf_Discard(v->val, Buf_Size(v->val)); - Buf_AddBytes(v->val, strlen(val), (const Byte *)val); + Buf_Empty(&v->val); + Buf_AddBytes(&v->val, strlen(val), val); if (DEBUG(VAR)) { fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val); } if ((v->flags & VAR_EXPORTED)) { - Var_Export1(name, VAR_EXPORT_FORCE); + Var_Export1(name, VAR_EXPORT_PARENT); } } /* @@ -780,11 +794,12 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags) * to the environment (as per POSIX standard) */ if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) { - if (v == (Var *)NIL) { + if (v == NULL) { /* we just added it */ v = VarFind(name, ctxt, 0); } - v->flags |= VAR_FROM_CMD; + if (v != NULL) + v->flags |= VAR_FROM_CMD; /* * If requested, don't export these in the environment * individually. We still put them in MAKEOVERRIDES so @@ -796,10 +811,27 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags) Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL); } + /* + * Another special case. + * Several make's support this sort of mechanism for tracking + * recursion - but each uses a different name. + * We allow the makefiles to update .MAKE.LEVEL and ensure + * children see a correctly incremented value. + */ + if (ctxt == VAR_GLOBAL && strcmp(MAKE_LEVEL, name) == 0) { + char tmp[64]; + int level; + + level = atoi(val); + snprintf(tmp, sizeof(tmp), "%u", level + 1); + setenv(MAKE_LEVEL, tmp, 1); + } + + out: - if (name != cp) - free(UNCONST(name)); - if (v != (Var *)NIL) + if (expanded_name != NULL) + free(expanded_name); + if (v != NULL) VarFreeEnv(v, TRUE); } @@ -835,24 +867,33 @@ Var_Append(const char *name, const char *val, GNode *ctxt) { Var *v; Hash_Entry *h; - const char *cp = name; + char *expanded_name = NULL; + + if (strchr(name, '$') != NULL) { + expanded_name = Var_Subst(NULL, name, ctxt, 0); + if (expanded_name[0] == 0) { + if (DEBUG(VAR)) { + fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) " + "name expands to empty string - ignored\n", + name, val); + } + free(expanded_name); + return; + } + name = expanded_name; + } - if ((name = strchr(cp, '$'))) { - name = Var_Subst(NULL, cp, ctxt, 0); - } else - name = cp; - v = VarFind(name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0); - if (v == (Var *)NIL) { + if (v == NULL) { VarAdd(name, val, ctxt); } else { - Buf_AddByte(v->val, (Byte)' '); - Buf_AddBytes(v->val, strlen(val), (const Byte *)val); + Buf_AddByte(&v->val, ' '); + Buf_AddBytes(&v->val, strlen(val), val); if (DEBUG(VAR)) { fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, - (char *)Buf_GetAll(v->val, NULL)); + Buf_GetAll(&v->val, NULL)); } if (v->flags & VAR_FROM_ENV) { @@ -867,8 +908,8 @@ Var_Append(const char *name, const char *val, GNode *ctxt) Hash_SetValue(h, v); } } - if (name != cp) - free(UNCONST(name)); + if (expanded_name != NULL) + free(expanded_name); } /*- @@ -891,7 +932,7 @@ Var_Append(const char *name, const char *val, GNode *ctxt) Boolean Var_Exists(const char *name, GNode *ctxt) { - Var *v; + Var *v; char *cp; if ((cp = strchr(name, '$')) != NULL) { @@ -901,7 +942,7 @@ Var_Exists(const char *name, GNode *ctxt) if (cp != NULL) { free(cp); } - if (v == (Var *)NIL) { + if (v == NULL) { return(FALSE); } else { (void)VarFreeEnv(v, TRUE); @@ -932,13 +973,13 @@ Var_Value(const char *name, GNode *ctxt, char **frp) v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); *frp = NULL; - if (v != (Var *)NIL) { - char *p = ((char *)Buf_GetAll(v->val, NULL)); + if (v != NULL) { + char *p = (Buf_GetAll(&v->val, NULL)); if (VarFreeEnv(v, FALSE)) *frp = p; return p; } else { - return (NULL); + return NULL; } } @@ -965,8 +1006,8 @@ Var_Value(const char *name, GNode *ctxt, char **frp) */ static Boolean VarHead(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData dummy) + char *word, Boolean addSpace, Buffer *buf, + void *dummy) { char *slash; @@ -976,7 +1017,7 @@ VarHead(GNode *ctx __unused, Var_Parse_State *vpstate, Buf_AddByte(buf, vpstate->varSpace); } *slash = '\0'; - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); *slash = '/'; return (TRUE); } else { @@ -985,7 +1026,7 @@ VarHead(GNode *ctx __unused, Var_Parse_State *vpstate, */ if (addSpace && vpstate->varSpace) Buf_AddByte(buf, vpstate->varSpace); - Buf_AddByte(buf, (Byte)'.'); + Buf_AddByte(buf, '.'); } return(dummy ? TRUE : TRUE); } @@ -1013,8 +1054,8 @@ VarHead(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarTail(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData dummy) + char *word, Boolean addSpace, Buffer *buf, + void *dummy) { char *slash; @@ -1025,10 +1066,10 @@ VarTail(GNode *ctx __unused, Var_Parse_State *vpstate, slash = strrchr(word, '/'); if (slash != NULL) { *slash++ = '\0'; - Buf_AddBytes(buf, strlen(slash), (Byte *)slash); + Buf_AddBytes(buf, strlen(slash), slash); slash[-1] = '/'; } else { - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); } return (dummy ? TRUE : TRUE); } @@ -1055,8 +1096,8 @@ VarTail(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData dummy) + char *word, Boolean addSpace, Buffer *buf, + void *dummy) { char *dot; @@ -1066,7 +1107,7 @@ VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate, Buf_AddByte(buf, vpstate->varSpace); } *dot++ = '\0'; - Buf_AddBytes(buf, strlen(dot), (Byte *)dot); + Buf_AddBytes(buf, strlen(dot), dot); dot[-1] = '.'; addSpace = TRUE; } @@ -1096,8 +1137,8 @@ VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData dummy) + char *word, Boolean addSpace, Buffer *buf, + void *dummy) { char *dot; @@ -1108,10 +1149,10 @@ VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate, dot = strrchr(word, '.'); if (dot != NULL) { *dot = '\0'; - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); *dot = '.'; } else { - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); } return (dummy ? TRUE : TRUE); } @@ -1140,15 +1181,17 @@ VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarMatch(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData pattern) + char *word, Boolean addSpace, Buffer *buf, + void *pattern) { + if (DEBUG(VAR)) + fprintf(debug_file, "VarMatch [%s] [%s]\n", word, (char *)pattern); if (Str_Match(word, (char *)pattern)) { if (addSpace && vpstate->varSpace) { Buf_AddByte(buf, vpstate->varSpace); } addSpace = TRUE; - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); } return(addSpace); } @@ -1179,8 +1222,8 @@ VarMatch(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData patp) + char *word, Boolean addSpace, Buffer *buf, + void *patp) { int len; char *ptr; @@ -1197,7 +1240,7 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate, Str_SYSVSubst(buf, varexp, ptr, len); free(varexp); } else { - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); } return(addSpace); @@ -1229,15 +1272,15 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate, */ static Boolean VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData pattern) + char *word, Boolean addSpace, Buffer *buf, + void *pattern) { if (!Str_Match(word, (char *)pattern)) { if (addSpace && vpstate->varSpace) { Buf_AddByte(buf, vpstate->varSpace); } addSpace = TRUE; - Buf_AddBytes(buf, strlen(word), (Byte *)word); + Buf_AddBytes(buf, strlen(word), word); } return(addSpace); } @@ -1266,8 +1309,8 @@ VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate, */ static Boolean VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, - char *word, Boolean addSpace, Buffer buf, - ClientData patternp) + char *word, Boolean addSpace, Buffer *buf, + void *patternp) { int wordLen; /* Length of word */ char *cp; /* General pointer */ @@ -1297,8 +1340,7 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, Buf_AddByte(buf, vpstate->varSpace); } addSpace = TRUE; - Buf_AddBytes(buf, pattern->rightLen, - (const Byte *)pattern->rhs); + Buf_AddBytes(buf, pattern->rightLen, pattern->rhs); } pattern->flags |= VAR_SUB_MATCHED; } else if (pattern->flags & VAR_MATCH_END) { @@ -1316,10 +1358,9 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, } addSpace = TRUE; } - Buf_AddBytes(buf, pattern->rightLen, - (const Byte *)pattern->rhs); + Buf_AddBytes(buf, pattern->rightLen, pattern->rhs); Buf_AddBytes(buf, wordLen - pattern->leftLen, - (Byte *)(word + pattern->leftLen)); + (word + pattern->leftLen)); pattern->flags |= VAR_SUB_MATCHED; } } else if (pattern->flags & VAR_MATCH_START) { @@ -1349,9 +1390,8 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, } addSpace = TRUE; } - Buf_AddBytes(buf, cp - word, (const Byte *)word); - Buf_AddBytes(buf, pattern->rightLen, - (const Byte *)pattern->rhs); + Buf_AddBytes(buf, cp - word, word); + Buf_AddBytes(buf, pattern->rightLen, pattern->rhs); pattern->flags |= VAR_SUB_MATCHED; } else { /* @@ -1383,9 +1423,8 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, Buf_AddByte(buf, vpstate->varSpace); addSpace = FALSE; } - Buf_AddBytes(buf, cp-word, (const Byte *)word); - Buf_AddBytes(buf, pattern->rightLen, - (const Byte *)pattern->rhs); + Buf_AddBytes(buf, cp-word, word); + Buf_AddBytes(buf, pattern->rightLen, pattern->rhs); wordLen -= (cp - word) + pattern->leftLen; word = cp + pattern->leftLen; if (wordLen == 0) { @@ -1403,7 +1442,7 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, if (addSpace && vpstate->varSpace) { Buf_AddByte(buf, vpstate->varSpace); } - Buf_AddBytes(buf, wordLen, (Byte *)word); + Buf_AddBytes(buf, wordLen, word); } /* * If added characters to the buffer, need to add a space @@ -1418,7 +1457,7 @@ VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate, if (addSpace && vpstate->varSpace) { Buf_AddByte(buf, vpstate->varSpace); } - Buf_AddBytes(buf, wordLen, (Byte *)word); + Buf_AddBytes(buf, wordLen, word); return(TRUE); } @@ -1466,8 +1505,8 @@ VarREError(int errnum, regex_t *pat, const char *str) */ static Boolean VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused, - char *word, Boolean addSpace, Buffer buf, - ClientData patternp) + char *word, Boolean addSpace, Buffer *buf, + void *patternp) { VarREPattern *pat; int xrv; @@ -1606,8 +1645,8 @@ VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused, */ static Boolean VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused, - char *word, Boolean addSpace, Buffer buf, - ClientData loopp) + char *word, Boolean addSpace, Buffer *buf, + void *loopp) { VarLoop_t *loop = (VarLoop_t *)loopp; char *s; @@ -1619,7 +1658,7 @@ VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused, if (s != NULL && *s != '\0') { if (addSpace && *s != '\n') Buf_AddByte(buf, ' '); - Buf_AddBytes(buf, (slen = strlen(s)), (Byte *)s); + Buf_AddBytes(buf, (slen = strlen(s)), s); addSpace = (slen > 0 && s[slen - 1] != '\n'); free(s); } @@ -1651,7 +1690,7 @@ static char * VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate, const char *str, VarSelectWords_t *seldata) { - Buffer buf; /* Buffer for the new string */ + Buffer buf; /* Buffer for the new string */ Boolean addSpace; /* TRUE if need to add a space to the * buffer before adding the trimmed * word */ @@ -1659,8 +1698,8 @@ VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate, char *as; /* word list memory */ int ac, i; int start, end, step; - - buf = Buf_Init(0); + + Buf_Init(&buf, 0); addSpace = FALSE; if (vpstate->oneBigWord) { @@ -1703,9 +1742,9 @@ VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate, i += step) { if (av[i] && *av[i]) { if (addSpace && vpstate->varSpace) { - Buf_AddByte(buf, vpstate->varSpace); + Buf_AddByte(&buf, vpstate->varSpace); } - Buf_AddBytes(buf, strlen(av[i]), (Byte *)av[i]); + Buf_AddBytes(&buf, strlen(av[i]), av[i]); addSpace = TRUE; } } @@ -1713,10 +1752,7 @@ VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate, free(as); free(av); - Buf_AddByte(buf, '\0'); - as = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return (as); + return Buf_Destroy(&buf, FALSE); } /*- @@ -1742,10 +1778,10 @@ static char * VarModify(GNode *ctx, Var_Parse_State *vpstate, const char *str, Boolean (*modProc)(GNode *, Var_Parse_State *, char *, - Boolean, Buffer, ClientData), - ClientData datum) + Boolean, Buffer *, void *), + void *datum) { - Buffer buf; /* Buffer for the new string */ + Buffer buf; /* Buffer for the new string */ Boolean addSpace; /* TRUE if need to add a space to the * buffer before adding the trimmed * word */ @@ -1753,7 +1789,7 @@ VarModify(GNode *ctx, Var_Parse_State *vpstate, char *as; /* word list memory */ int ac, i; - buf = Buf_Init(0); + Buf_Init(&buf, 0); addSpace = FALSE; if (vpstate->oneBigWord) { @@ -1768,16 +1804,13 @@ VarModify(GNode *ctx, Var_Parse_State *vpstate, } for (i = 0; i < ac; i++) { - addSpace = (*modProc)(ctx, vpstate, av[i], addSpace, buf, datum); + addSpace = (*modProc)(ctx, vpstate, av[i], addSpace, &buf, datum); } free(as); free(av); - Buf_AddByte(buf, '\0'); - as = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return (as); + return Buf_Destroy(&buf, FALSE); } @@ -1808,12 +1841,12 @@ VarWordCompare(const void *a, const void *b) static char * VarOrder(const char *str, const char otype) { - Buffer buf; /* Buffer for the new string */ + Buffer buf; /* Buffer for the new string */ char **av; /* word list [first word does not count] */ char *as; /* word list memory */ int ac, i; - buf = Buf_Init(0); + Buf_Init(&buf, 0); av = brk_string(str, &ac, FALSE, &as); @@ -1845,18 +1878,15 @@ VarOrder(const char *str, const char otype) } /* end of switch */ for (i = 0; i < ac; i++) { - Buf_AddBytes(buf, strlen(av[i]), (Byte *)av[i]); + Buf_AddBytes(&buf, strlen(av[i]), av[i]); if (i != ac - 1) - Buf_AddByte(buf, ' '); + Buf_AddByte(&buf, ' '); } free(as); free(av); - Buf_AddByte(buf, '\0'); - as = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return (as); + return Buf_Destroy(&buf, FALSE); } @@ -1879,12 +1909,12 @@ VarOrder(const char *str, const char otype) static char * VarUniq(const char *str) { - Buffer buf; /* Buffer for new string */ + Buffer buf; /* Buffer for new string */ char **av; /* List of words to affect */ char *as; /* Word list memory */ int ac, i, j; - buf = Buf_Init(0); + Buf_Init(&buf, 0); av = brk_string(str, &ac, FALSE, &as); if (ac > 1) { @@ -1895,18 +1925,15 @@ VarUniq(const char *str) } for (i = 0; i < ac; i++) { - Buf_AddBytes(buf, strlen(av[i]), (Byte *)av[i]); + Buf_AddBytes(&buf, strlen(av[i]), av[i]); if (i != ac - 1) - Buf_AddByte(buf, ' '); + Buf_AddByte(&buf, ' '); } free(as); free(av); - Buf_AddByte(buf, '\0'); - as = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return as; + return Buf_Destroy(&buf, FALSE); } @@ -1938,8 +1965,11 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused, int *length, VarPattern *pattern) { const char *cp; - Buffer buf = Buf_Init(0); + char *rstr; + Buffer buf; int junk; + + Buf_Init(&buf, 0); if (length == NULL) length = &junk; @@ -1955,12 +1985,12 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused, */ for (cp = *tstr; *cp && (*cp != delim); cp++) { if (IS_A_MATCH(cp, delim)) { - Buf_AddByte(buf, (Byte)cp[1]); + Buf_AddByte(&buf, cp[1]); cp++; } else if (*cp == '$') { if (cp[1] == delim) { if (flags == NULL) - Buf_AddByte(buf, (Byte)*cp); + Buf_AddByte(&buf, *cp); else /* * Unescaped $ at end of pattern => anchor @@ -1979,7 +2009,7 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused, * substitution and recurse. */ cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt); - Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); + Buf_AddBytes(&buf, strlen(cp2), cp2); if (freeIt) free(freeIt); cp += len - 1; @@ -2004,34 +2034,31 @@ VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused, --depth; } } - Buf_AddBytes(buf, cp2 - cp, (const Byte *)cp); + Buf_AddBytes(&buf, cp2 - cp, cp); cp = --cp2; } else - Buf_AddByte(buf, (Byte)*cp); + Buf_AddByte(&buf, *cp); } } } else if (pattern && *cp == '&') - Buf_AddBytes(buf, pattern->leftLen, (const Byte *)pattern->lhs); + Buf_AddBytes(&buf, pattern->leftLen, pattern->lhs); else - Buf_AddByte(buf, (Byte)*cp); + Buf_AddByte(&buf, *cp); } - Buf_AddByte(buf, (Byte)'\0'); - if (*cp != delim) { *tstr = cp; *length = 0; return NULL; } - else { - char *rstr; - *tstr = ++cp; - rstr = (char *)Buf_GetAll(buf, length); - *length -= 1; /* Don't count the NULL */ - Buf_Destroy(buf, FALSE); - return rstr; - } + + *tstr = ++cp; + *length = Buf_Size(&buf); + rstr = Buf_Destroy(&buf, FALSE); + if (DEBUG(VAR)) + fprintf(debug_file, "Modifier pattern: \"%s\"\n", rstr); + return rstr; } /*- @@ -2061,23 +2088,23 @@ VarQuote(char *str) newline = "\\\n"; nlen = strlen(newline); - buf = Buf_Init(0); + Buf_Init(&buf, 0); while (*str != '\0') { if ((len = strcspn(str, meta)) != 0) { - Buf_AddBytes(buf, len, str); + Buf_AddBytes(&buf, len, str); str += len; } else if (*str == '\n') { - Buf_AddBytes(buf, nlen, newline); + Buf_AddBytes(&buf, nlen, newline); ++str; } else { - Buf_AddByte(buf, (Byte)'\\'); - Buf_AddByte(buf, (Byte)*str); + Buf_AddByte(&buf, '\\'); + Buf_AddByte(&buf, *str); ++str; } } - Buf_AddByte(buf, (Byte)'\0'); - str = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); + str = Buf_Destroy(&buf, FALSE); + if (DEBUG(VAR)) + fprintf(debug_file, "QuoteMeta: [%s]\n", str); return str; } @@ -2105,99 +2132,96 @@ VarChangeCase(char *str, int upper) int (*modProc)(int); modProc = (upper ? toupper : tolower); - buf = Buf_Init(0); + Buf_Init(&buf, 0); for (; *str ; str++) { - Buf_AddByte(buf, (Byte)modProc(*str)); + Buf_AddByte(&buf, modProc(*str)); } - Buf_AddByte(buf, (Byte)'\0'); - str = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return str; + return Buf_Destroy(&buf, FALSE); } /* * Now we need to apply any modifiers the user wants applied. * These are: * :M<pattern> words which match the given <pattern>. - * <pattern> is of the standard file - * wildcarding form. + * <pattern> is of the standard file + * wildcarding form. * :N<pattern> words which do not match the given <pattern>. * :S<d><pat1><d><pat2><d>[1gW] - * Substitute <pat2> for <pat1> in the value + * Substitute <pat2> for <pat1> in the value * :C<d><pat1><d><pat2><d>[1gW] - * Substitute <pat2> for regex <pat1> in the value - * :H Substitute the head of each word - * :T Substitute the tail of each word - * :E Substitute the extension (minus '.') of - * each word - * :R Substitute the root of each word - * (pathname minus the suffix). - * :O ("Order") Alphabeticaly sort words in variable. - * :Ox ("intermiX") Randomize words in variable. - * :u ("uniq") Remove adjacent duplicate words. - * :tu Converts the variable contents to uppercase. - * :tl Converts the variable contents to lowercase. - * :ts[c] Sets varSpace - the char used to - * separate words to 'c'. If 'c' is - * omitted then no separation is used. - * :tW Treat the variable contents as a single - * word, even if it contains spaces. - * (Mnemonic: one big 'W'ord.) - * :tw Treat the variable contents as multiple - * space-separated words. - * (Mnemonic: many small 'w'ords.) - * :[index] Select a single word from the value. - * :[start..end] Select multiple words from the value. - * :[*] or :[0] Select the entire value, as a single - * word. Equivalent to :tW. - * :[@] Select the entire value, as multiple - * words. Undoes the effect of :[*]. - * Equivalent to :tw. - * :[#] Returns the number of words in the value. - * - * :?<true-value>:<false-value> - * If the variable evaluates to true, return - * true value, else return the second value. - * :lhs=rhs Like :S, but the rhs goes to the end of - * the invocation. - * :sh Treat the current value as a command - * to be run, new value is its output. + * Substitute <pat2> for regex <pat1> in the value + * :H Substitute the head of each word + * :T Substitute the tail of each word + * :E Substitute the extension (minus '.') of + * each word + * :R Substitute the root of each word + * (pathname minus the suffix). + * :O ("Order") Alphabeticaly sort words in variable. + * :Ox ("intermiX") Randomize words in variable. + * :u ("uniq") Remove adjacent duplicate words. + * :tu Converts the variable contents to uppercase. + * :tl Converts the variable contents to lowercase. + * :ts[c] Sets varSpace - the char used to + * separate words to 'c'. If 'c' is + * omitted then no separation is used. + * :tW Treat the variable contents as a single + * word, even if it contains spaces. + * (Mnemonic: one big 'W'ord.) + * :tw Treat the variable contents as multiple + * space-separated words. + * (Mnemonic: many small 'w'ords.) + * :[index] Select a single word from the value. + * :[start..end] Select multiple words from the value. + * :[*] or :[0] Select the entire value, as a single + * word. Equivalent to :tW. + * :[@] Select the entire value, as multiple + * words. Undoes the effect of :[*]. + * Equivalent to :tw. + * :[#] Returns the number of words in the value. + * + * :?<true-value>:<false-value> + * If the variable evaluates to true, return + * true value, else return the second value. + * :lhs=rhs Like :S, but the rhs goes to the end of + * the invocation. + * :sh Treat the current value as a command + * to be run, new value is its output. * The following added so we can handle ODE makefiles. - * :@<tmpvar>@<newval>@ - * Assign a temporary local variable <tmpvar> - * to the current value of each word in turn - * and replace each word with the result of - * evaluating <newval> - * :D<newval> Use <newval> as value if variable defined - * :U<newval> Use <newval> as value if variable undefined - * :L Use the name of the variable as the value. - * :P Use the path of the node that has the same - * name as the variable as the value. This - * basically includes an implied :L so that - * the common method of refering to the path - * of your dependent 'x' in a rule is to use - * the form '${x:P}'. - * :!<cmd>! Run cmd much the same as :sh run's the - * current value of the variable. + * :@<tmpvar>@<newval>@ + * Assign a temporary local variable <tmpvar> + * to the current value of each word in turn + * and replace each word with the result of + * evaluating <newval> + * :D<newval> Use <newval> as value if variable defined + * :U<newval> Use <newval> as value if variable undefined + * :L Use the name of the variable as the value. + * :P Use the path of the node that has the same + * name as the variable as the value. This + * basically includes an implied :L so that + * the common method of refering to the path + * of your dependent 'x' in a rule is to use + * the form '${x:P}'. + * :!<cmd>! Run cmd much the same as :sh run's the + * current value of the variable. * The ::= modifiers, actually assign a value to the variable. * Their main purpose is in supporting modifiers of .for loop * iterators and other obscure uses. They always expand to * nothing. In a target rule that would otherwise expand to an * empty line they can be preceded with @: to keep make happy. * Eg. - * + * * foo: .USE * .for i in ${.TARGET} ${.TARGET:R}.gz - * @: ${t::=$i} - * @echo blah ${t:T} + * @: ${t::=$i} + * @echo blah ${t:T} * .endfor - * - * ::=<str> Assigns <str> as the new value of variable. - * ::?=<str> Assigns <str> as value of variable if - * it was not already set. - * ::+=<str> Appends <str> to variable. - * ::!=<cmd> Assigns output of <cmd> as the new value of - * variable. + * + * ::=<str> Assigns <str> as the new value of variable. + * ::?=<str> Assigns <str> as value of variable if + * it was not already set. + * ::+=<str> Appends <str> to variable. + * ::!=<cmd> Assigns output of <cmd> as the new value of + * variable. */ static char * @@ -2222,11 +2246,11 @@ ApplyModifiers(char *nstr, const char *tstr, parsestate.varSpace = ' '; /* word separator */ start = cp = tstr; - + while (*tstr && *tstr != endc) { if (*tstr == '$') { - /* + /* * We have some complex modifiers in a variable. */ void *freeIt; @@ -2261,7 +2285,7 @@ ApplyModifiers(char *nstr, const char *tstr, if (*tstr == ':') tstr++; else if (!*tstr && endc) { - Error("Unclosed variable specification for %s", v->name); + Error("Unclosed variable specification after complex modifier (expecting '%c') for %s", endc, v->name); goto out; } continue; @@ -2285,6 +2309,9 @@ ApplyModifiers(char *nstr, const char *tstr, VarPattern pattern; int how; + if (v->name[0] == 0) + goto bad_modifier; + v_ctxt = ctxt; sv_name = NULL; ++tstr; @@ -2297,12 +2324,12 @@ ApplyModifiers(char *nstr, const char *tstr, v->name = bmake_strdup(v->name); } else if (ctxt != VAR_GLOBAL) { Var *gv = VarFind(v->name, ctxt, 0); - if (gv == (Var *)NIL) + if (gv == NULL) v_ctxt = VAR_GLOBAL; else VarFreeEnv(gv, TRUE); } - + switch ((how = *tstr)) { case '+': case '?': @@ -2401,7 +2428,7 @@ ApplyModifiers(char *nstr, const char *tstr, * the delimiter (expand the variable substitution). * The result is left in the Buffer buf. */ - buf = Buf_Init(0); + Buf_Init(&buf, 0); for (cp = tstr + 1; *cp != endc && *cp != ':' && *cp != '\0'; cp++) { @@ -2411,7 +2438,7 @@ ApplyModifiers(char *nstr, const char *tstr, (cp[1] == endc) || (cp[1] == '\\'))) { - Buf_AddByte(buf, (Byte)cp[1]); + Buf_AddByte(&buf, cp[1]); cp++; } else if (*cp == '$') { /* @@ -2423,15 +2450,14 @@ ApplyModifiers(char *nstr, const char *tstr, void *freeIt; cp2 = Var_Parse(cp, ctxt, errnum, &len, &freeIt); - Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); + Buf_AddBytes(&buf, strlen(cp2), cp2); if (freeIt) free(freeIt); cp += len - 1; } else { - Buf_AddByte(buf, (Byte)*cp); + Buf_AddByte(&buf, *cp); } } - Buf_AddByte(buf, (Byte)'\0'); termc = *cp; @@ -2442,11 +2468,10 @@ ApplyModifiers(char *nstr, const char *tstr, if ((v->flags & VAR_JUNK) != 0) v->flags |= VAR_KEEP; if (wantit) { - newStr = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); + newStr = Buf_Destroy(&buf, FALSE); } else { newStr = nstr; - Buf_Destroy(buf, TRUE); + Buf_Destroy(&buf, TRUE); } break; } @@ -2462,11 +2487,11 @@ ApplyModifiers(char *nstr, const char *tstr, case 'P': { GNode *gn; - + if ((v->flags & VAR_JUNK) != 0) v->flags |= VAR_KEEP; gn = Targ_FindNode(v->name, TARG_NOCREATE); - if (gn == NILGNODE || gn->type & OP_NOPATH) { + if (gn == NULL || gn->type & OP_NOPATH) { newStr = NULL; } else if (gn->path) { newStr = bmake_strdup(gn->path); @@ -2515,7 +2540,7 @@ ApplyModifiers(char *nstr, const char *tstr, * which we must free(). */ char *estr; - + cp = tstr+1; /* point to char after '[' */ delim = ']'; /* look for closing ']' */ estr = VarGetPattern(ctxt, &parsestate, @@ -2678,7 +2703,7 @@ ApplyModifiers(char *nstr, const char *tstr, default: if (isdigit((unsigned char)tstr[3])) { char *ep; - + parsestate.varSpace = strtoul(&tstr[3], &ep, 0); if (*ep != ':' && *ep != endc) @@ -2755,9 +2780,11 @@ ApplyModifiers(char *nstr, const char *tstr, const char *endpat; /* points just after end of pattern */ char *cp2; Boolean copy; /* pattern should be, or has been, copied */ + Boolean needSubst; int nest; copy = FALSE; + needSubst = FALSE; nest = 1; /* * In the loop below, ignore ':' unless we are at @@ -2772,13 +2799,18 @@ ApplyModifiers(char *nstr, const char *tstr, if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc || cp[1] == startc)) { - copy = TRUE; + if (!needSubst) { + copy = TRUE; + } cp++; continue; } - if (*cp == startc) + if (*cp == '$') { + needSubst = TRUE; + } + if (*cp == '(' || *cp == '{') ++nest; - if (*cp == endc) { + if (*cp == ')' || *cp == '}') { --nest; if (nest == 0) break; @@ -2813,29 +2845,27 @@ ApplyModifiers(char *nstr, const char *tstr, * nul-terminated string soon, so construct one now. */ pattern = bmake_strndup(tstr+1, endpat - (tstr + 1)); - copy = TRUE; } - if (strchr(pattern, '$') != NULL) { + if (needSubst) { /* * pattern contains embedded '$', so use Var_Subst to * expand it. */ cp2 = pattern; pattern = Var_Subst(NULL, cp2, ctxt, errnum); - if (copy) - free(cp2); - copy = TRUE; + free(cp2); } - if (*tstr == 'M' || *tstr == 'm') { + if (DEBUG(VAR)) + fprintf(debug_file, "Pattern for [%s] is [%s]\n", nstr, + pattern); + if (*tstr == 'M') { newStr = VarModify(ctxt, &parsestate, nstr, VarMatch, pattern); } else { newStr = VarModify(ctxt, &parsestate, nstr, VarNoMatch, pattern); } - if (copy) { - free(pattern); - } + free(pattern); break; } case 'S': @@ -2903,7 +2933,7 @@ ApplyModifiers(char *nstr, const char *tstr, free(UNCONST(pattern.rhs)); delim = '\0'; break; - } + } case '?': { VarPattern pattern; @@ -2931,7 +2961,7 @@ ApplyModifiers(char *nstr, const char *tstr, termc = *--cp; delim = '\0'; - if (Cond_EvalExpression(1, v->name, &value, 0) + if (Cond_EvalExpression(NULL, v->name, &value, 0) == COND_INVALID) { Error("Bad conditional expression `%s' in %s?%s:%s", v->name, v->name, pattern.lhs, pattern.rhs); @@ -3104,7 +3134,7 @@ ApplyModifiers(char *nstr, const char *tstr, goto default_case; #endif default: - default_case: + default_case: { #ifdef SYSVVARSUB /* @@ -3143,7 +3173,7 @@ ApplyModifiers(char *nstr, const char *tstr, */ delim='='; cp = tstr; - if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, + if ((pattern.lhs = VarGetPattern(ctxt, &parsestate, errnum, &cp, delim, &pattern.flags, &pattern.leftLen, NULL)) == NULL) goto cleanup; @@ -3192,7 +3222,7 @@ ApplyModifiers(char *nstr, const char *tstr, } } if (termc == '\0' && endc != '\0') { - Error("Unclosed variable specification for %s", v->name); + Error("Unclosed variable specification (expecting '%c') for \"%s\" (value \"%s\") modifier %c", endc, v->name, nstr, modifier); } else if (termc == ':') { cp++; } @@ -3252,11 +3282,11 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, void **freePtr) { const char *tstr; /* Pointer into str */ - Var *v; /* Variable in invocation */ + Var *v; /* Variable in invocation */ Boolean haveModifier;/* TRUE if have modifiers for the variable */ char endc; /* Ending character when variable in parens * or braces */ - char startc=0; /* Starting character when variable in parens + char startc; /* Starting character when variable in parens * or braces */ int vlen; /* Length of variable name */ const char *start; /* Points to original start of str */ @@ -3266,6 +3296,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, * is done to support dynamic sources. The * result is just the invocation, unaltered */ Var_Parse_State parsestate; /* Flags passed to helper functions */ + char name[2]; *freePtr = NULL; dynamic = FALSE; @@ -3273,19 +3304,24 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, parsestate.oneBigWord = FALSE; parsestate.varSpace = ' '; /* word separator */ - if (str[1] != PROPEN && str[1] != BROPEN) { + startc = str[1]; + if (startc != PROPEN && startc != BROPEN) { /* * If it's not bounded by braces of some sort, life is much simpler. * We just need to check for the first character and return the * value if it exists. */ - char name[2]; - name[0] = str[1]; + /* Error out some really stupid names */ + if (startc == '\0' || strchr(")}:$", startc)) { + *lengthPtr = 1; + return var_Error; + } + name[0] = startc; name[1] = '\0'; v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); - if (v == (Var *)NIL) { + if (v == NULL) { *lengthPtr = 2; if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) { @@ -3318,15 +3354,11 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, tstr = &str[1]; endc = str[1]; } - } else if (str[1] == '\0') { - *lengthPtr = 1; - return (errnum ? var_Error : varNoError); } else { Buffer buf; /* Holds the variable name */ - startc = str[1]; endc = startc == PROPEN ? PRCLOSE : BRCLOSE; - buf = Buf_Init(0); + Buf_Init(&buf, 0); /* * Skip to the end character or a colon, whichever comes first. @@ -3343,14 +3375,14 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, void *freeIt; char *rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt); if (rval != NULL) { - Buf_AddBytes(buf, strlen(rval), (Byte *)rval); + Buf_AddBytes(&buf, strlen(rval), rval); } if (freeIt) free(freeIt); tstr += rlen - 1; } else - Buf_AddByte(buf, (Byte)*tstr); + Buf_AddByte(&buf, *tstr); } if (*tstr == ':') { haveModifier = TRUE; @@ -3363,12 +3395,10 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, * the end of the string, since that's what make does. */ *lengthPtr = tstr - str; - Buf_Destroy(buf, TRUE); + Buf_Destroy(&buf, TRUE); return (var_Error); } - Buf_AddByte(buf, (Byte)'\0'); - str = Buf_GetAll(buf, NULL); - vlen = strlen(str); + str = Buf_GetAll(&buf, &vlen); /* * At this point, str points into newly allocated memory from @@ -3382,65 +3412,50 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, */ v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); - if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && - (vlen == 2) && (str[1] == 'F' || str[1] == 'D')) - { + /* + * Check also for bogus D and F forms of local variables since we're + * in a local context and the name is the right length. + */ + if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && + (vlen == 2) && (str[1] == 'F' || str[1] == 'D') && + strchr("@%*!<>", str[0]) != NULL) { /* - * Check for bogus D and F forms of local variables since we're - * in a local context and the name is the right length. + * Well, it's local -- go look for it. */ - switch(*str) { - case '@': - case '%': - case '*': - case '!': - case '>': - case '<': - { - char vname[2]; - char *val; - - /* - * Well, it's local -- go look for it. - */ - vname[0] = *str; - vname[1] = '\0'; - v = VarFind(vname, ctxt, 0); + name[0] = *str; + name[1] = '\0'; + v = VarFind(name, ctxt, 0); - if (v != (Var *)NIL) { - /* - * No need for nested expansion or anything, as we're - * the only one who sets these things and we sure don't - * but nested invocations in them... - */ - val = (char *)Buf_GetAll(v->val, NULL); + if (v != NULL) { + /* + * No need for nested expansion or anything, as we're + * the only one who sets these things and we sure don't + * but nested invocations in them... + */ + nstr = Buf_GetAll(&v->val, NULL); - if (str[1] == 'D') { - val = VarModify(ctxt, &parsestate, val, VarHead, - NULL); - } else { - val = VarModify(ctxt, &parsestate, val, VarTail, - NULL); - } - /* - * Resulting string is dynamically allocated, so - * tell caller to free it. - */ - *freePtr = val; - *lengthPtr = tstr-start+1; - Buf_Destroy(buf, TRUE); - VarFreeEnv(v, TRUE); - return(val); - } - break; + if (str[1] == 'D') { + nstr = VarModify(ctxt, &parsestate, nstr, VarHead, + NULL); + } else { + nstr = VarModify(ctxt, &parsestate, nstr, VarTail, + NULL); } + /* + * Resulting string is dynamically allocated, so + * tell caller to free it. + */ + *freePtr = nstr; + *lengthPtr = tstr-start+1; + Buf_Destroy(&buf, TRUE); + VarFreeEnv(v, TRUE); + return nstr; } } - if (v == (Var *)NIL) { + if (v == NULL) { if (((vlen == 1) || - (((vlen == 2) && (str[1] == 'F' || - str[1] == 'D')))) && + (((vlen == 2) && (str[1] == 'F' || str[1] == 'D')))) && ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) { /* @@ -3485,10 +3500,10 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, if (dynamic) { char *pstr = bmake_strndup(start, *lengthPtr); *freePtr = pstr; - Buf_Destroy(buf, TRUE); + Buf_Destroy(&buf, TRUE); return(pstr); } else { - Buf_Destroy(buf, TRUE); + Buf_Destroy(&buf, TRUE); return (errnum ? var_Error : varNoError); } } else { @@ -3498,12 +3513,12 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, */ v = bmake_malloc(sizeof(Var)); v->name = UNCONST(str); - v->val = Buf_Init(1); + Buf_Init(&v->val, 1); v->flags = VAR_JUNK; - Buf_Destroy(buf, FALSE); + Buf_Destroy(&buf, FALSE); } } else - Buf_Destroy(buf, TRUE); + Buf_Destroy(&buf, TRUE); } if (v->flags & VAR_IN_USE) { @@ -3521,7 +3536,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, * been dynamically-allocated, so it will need freeing when we * return. */ - nstr = (char *)Buf_GetAll(v->val, NULL); + nstr = Buf_GetAll(&v->val, NULL); if (strchr(nstr, '$') != NULL) { nstr = Var_Subst(NULL, nstr, ctxt, errnum); *freePtr = nstr; @@ -3549,7 +3564,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, if (v->flags & VAR_FROM_ENV) { Boolean destroy = FALSE; - if (nstr != (char *)Buf_GetAll(v->val, NULL)) { + if (nstr != Buf_GetAll(&v->val, NULL)) { destroy = TRUE; } else { /* @@ -3577,8 +3592,8 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, nstr = var_Error; } } - if (nstr != (char *)Buf_GetAll(v->val, NULL)) - Buf_Destroy(v->val, TRUE); + if (nstr != Buf_GetAll(&v->val, NULL)) + Buf_Destroy(&v->val, TRUE); free(v->name); free(v); } @@ -3608,22 +3623,22 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, char * Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) { - Buffer buf; /* Buffer for forming things */ + Buffer buf; /* Buffer for forming things */ char *val; /* Value to substitute for a variable */ - int length; /* Length of the variable invocation */ + int length; /* Length of the variable invocation */ Boolean trailingBslash; /* variable ends in \ */ void *freeIt = NULL; /* Set if it should be freed */ static Boolean errorReported; /* Set true if an error has already * been reported to prevent a plethora * of messages when recursing */ - buf = Buf_Init(0); + Buf_Init(&buf, 0); errorReported = FALSE; trailingBslash = FALSE; while (*str) { if (*str == '\n' && trailingBslash) - Buf_AddByte(buf, ' '); + Buf_AddByte(&buf, ' '); if (var == NULL && (*str == '$') && (str[1] == '$')) { /* * A dollar sign may be escaped either with another dollar sign. @@ -3631,7 +3646,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) * dollar sign into the buffer directly. */ str++; - Buf_AddByte(buf, (Byte)*str); + Buf_AddByte(&buf, *str); str++; } else if (*str != '$') { /* @@ -3642,19 +3657,19 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) for (cp = str++; *str != '$' && *str != '\0'; str++) continue; - Buf_AddBytes(buf, str - cp, (const Byte *)cp); + Buf_AddBytes(&buf, str - cp, cp); } else { if (var != NULL) { int expand; for (;;) { if (str[1] == '\0') { /* A trailing $ is kind of a special case */ - Buf_AddByte(buf, str[0]); + Buf_AddByte(&buf, str[0]); str++; expand = FALSE; } else if (str[1] != PROPEN && str[1] != BROPEN) { if (str[1] != *var || strlen(var) > 1) { - Buf_AddBytes(buf, 2, (const Byte *)str); + Buf_AddBytes(&buf, 2, str); str += 2; expand = FALSE; } @@ -3678,7 +3693,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) * the nested one */ if (*p == '$') { - Buf_AddBytes(buf, p - str, (const Byte *)str); + Buf_AddBytes(&buf, p - str, str); str = p; continue; } @@ -3691,7 +3706,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) */ for (;*p != '$' && *p != '\0'; p++) continue; - Buf_AddBytes(buf, p - str, (const Byte *)str); + Buf_AddBytes(&buf, p - str, str); str = p; expand = FALSE; } @@ -3734,7 +3749,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) str += length; errorReported = TRUE; } else { - Buf_AddByte(buf, (Byte)*str); + Buf_AddByte(&buf, *str); str += 1; } } else { @@ -3749,7 +3764,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) * into the new string. */ length = strlen(val); - Buf_AddBytes(buf, length, (Byte *)val); + Buf_AddBytes(&buf, length, val); trailingBslash = length > 0 && val[length - 1] == '\\'; } if (freeIt) { @@ -3759,10 +3774,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr) } } - Buf_AddByte(buf, '\0'); - val = (char *)Buf_GetAll(buf, NULL); - Buf_Destroy(buf, FALSE); - return (val); + return Buf_Destroy(&buf, FALSE); } /*- @@ -3843,10 +3855,10 @@ Var_End(void) /****************** PRINT DEBUGGING INFO *****************/ static void -VarPrintVar(ClientData vp) +VarPrintVar(void *vp) { Var *v = (Var *)vp; - fprintf(debug_file, "%-16s = %s\n", v->name, (char *)Buf_GetAll(v->val, NULL)); + fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL)); } /*- |