[BACK]Return to var.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / make

Annotation of src/usr.bin/make/var.c, Revision 1.640

1.640   ! rillig      1: /*     $NetBSD: var.c,v 1.639 2020/11/01 22:12:54 rillig Exp $ */
1.11      christos    2:
1.1       cgd         3: /*
1.15      christos    4:  * Copyright (c) 1988, 1989, 1990, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.80      agc         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Adam de Boor.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
1.1       cgd        36:  * Copyright (c) 1989 by Berkeley Softworks
                     37:  * All rights reserved.
                     38:  *
                     39:  * This code is derived from software contributed to Berkeley by
                     40:  * Adam de Boor.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *     This product includes software developed by the University of
                     53:  *     California, Berkeley and its contributors.
                     54:  * 4. Neither the name of the University nor the names of its contributors
                     55:  *    may be used to endorse or promote products derived from this software
                     56:  *    without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     60:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     61:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     62:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     63:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     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:
1.592     rillig     71: /*
                     72:  * Handling of variables and the expressions formed from them.
                     73:  *
                     74:  * Variables are set using lines of the form VAR=value.  Both the variable
                     75:  * name and the value can contain references to other variables, by using
                     76:  * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
1.1       cgd        77:  *
                     78:  * Interface:
1.592     rillig     79:  *     Var_Init        Initialize this module.
                     80:  *
                     81:  *     Var_End         Clean up the module.
                     82:  *
                     83:  *     Var_Set         Set the value of the variable, creating it if
                     84:  *                     necessary.
                     85:  *
                     86:  *     Var_Append      Append more characters to the variable, creating it if
                     87:  *                     necessary. A space is placed between the old value and
                     88:  *                     the new one.
1.1       cgd        89:  *
1.546     rillig     90:  *     Var_Exists      See if a variable exists.
1.1       cgd        91:  *
1.592     rillig     92:  *     Var_Value       Return the unexpanded value of a variable, or NULL if
                     93:  *                     the variable is undefined.
                     94:  *
                     95:  *     Var_Subst       Substitute all variable expressions in a string.
                     96:  *
                     97:  *     Var_Parse       Parse a variable expression such as ${VAR:Mpattern}.
1.1       cgd        98:  *
1.592     rillig     99:  *     Var_Delete      Delete a variable.
1.1       cgd       100:  *
1.592     rillig    101:  *     Var_ExportVars  Export some or even all variables to the environment
                    102:  *                     of this process and its child processes.
1.1       cgd       103:  *
1.592     rillig    104:  *     Var_Export      Export the variable to the environment of this process
                    105:  *                     and its child processes.
1.1       cgd       106:  *
1.592     rillig    107:  *     Var_UnExport    Don't export the variable anymore.
1.1       cgd       108:  *
                    109:  * Debugging:
1.592     rillig    110:  *     Var_Stats       Print out hashing statistics if in -dh mode.
                    111:  *
                    112:  *     Var_Dump        Print out all variables defined in the given context.
1.1       cgd       113:  *
                    114:  * XXX: There's a lot of duplication in these functions.
                    115:  */
                    116:
1.630     rillig    117: #include <sys/stat.h>
1.31      gwr       118: #ifndef NO_REGEX
1.630     rillig    119: #include <sys/types.h>
                    120: #include <regex.h>
1.17      christos  121: #endif
1.631     rillig    122: #include <errno.h>
1.630     rillig    123: #include <inttypes.h>
                    124: #include <limits.h>
                    125: #include <time.h>
                    126:
                    127: #include "make.h"
                    128: #include "dir.h"
                    129: #include "job.h"
                    130: #include "metachar.h"
1.1       cgd       131:
1.512     rillig    132: /*     "@(#)var.c      8.3 (Berkeley) 3/19/94" */
1.640   ! rillig    133: MAKE_RCSID("$NetBSD: var.c,v 1.639 2020/11/01 22:12:54 rillig Exp $");
1.512     rillig    134:
1.547     rillig    135: #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
                    136: #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
                    137: #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3)
                    138: #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4)
1.411     rillig    139:
1.471     rillig    140: ENUM_FLAGS_RTTI_3(VarEvalFlags,
                    141:                  VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN);
1.430     rillig    142:
1.1       cgd       143: /*
1.170     sjg       144:  * This lets us tell if we have replaced the original environ
                    145:  * (which we cannot free).
                    146:  */
                    147: char **savedEnv = NULL;
                    148:
1.536     rillig    149: /* Special return value for Var_Parse, indicating a parse error.  It may be
                    150:  * caused by an undefined variable, a syntax error in a modifier or
                    151:  * something entirely different. */
1.249     rillig    152: char var_Error[] = "";
1.1       cgd       153:
1.536     rillig    154: /* Special return value for Var_Parse, indicating an undefined variable in
                    155:  * a case where VARE_UNDEFERR is not set.  This undefined variable is
                    156:  * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
                    157:  * be deferred until it is defined in an actual target. */
                    158: static char varUndefined[] = "";
                    159:
                    160: /* Special return value for Var_Parse, just to avoid allocating empty strings.
                    161:  * In contrast to var_Error and varUndefined, this is not an error marker but
                    162:  * just an ordinary successful return value. */
                    163: static char emptyString[] = "";
1.1       cgd       164:
                    165: /*
1.593     rillig    166:  * Traditionally this make consumed $$ during := like any other expansion.
                    167:  * Other make's do not, and this make follows straight since 2016-01-09.
                    168:  *
1.205     sjg       169:  * This knob allows controlling the behavior.
1.292     rillig    170:  * FALSE to consume $$ during := assignment.
                    171:  * TRUE to preserve $$ during := assignment.
1.205     sjg       172:  */
1.593     rillig    173: #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
1.205     sjg       174: static Boolean save_dollars = TRUE;
                    175:
                    176: /*
1.1       cgd       177:  * Internally, variables are contained in four different contexts.
1.292     rillig    178:  *     1) the environment. They cannot be changed. If an environment
1.594     rillig    179:  *        variable is appended to, the result is placed in the global
                    180:  *        context.
                    181:  *     2) the global context. Variables set in the makefiles are located
                    182:  *        here.
1.1       cgd       183:  *     3) the command-line context. All variables set on the command line
1.594     rillig    184:  *        are placed in this context.
1.1       cgd       185:  *     4) the local context. Each target has associated with it a context
                    186:  *        list. On this list are located the structures describing such
                    187:  *        local variables as $(@) and $(*)
                    188:  * The four contexts are searched in the reverse order from which they are
1.591     rillig    189:  * listed (but see opts.checkEnvFirst).
1.1       cgd       190:  */
1.240     rillig    191: GNode          *VAR_INTERNAL;  /* variables from make itself */
                    192: GNode          *VAR_GLOBAL;    /* variables from the makefile */
1.594     rillig    193: GNode          *VAR_CMDLINE;   /* variables defined on the command-line */
1.240     rillig    194:
1.578     rillig    195: typedef enum VarFlags {
1.601     rillig    196:
1.440     rillig    197:     /* The variable's value is currently being used by Var_Parse or Var_Subst.
                    198:      * This marker is used to avoid endless recursion. */
                    199:     VAR_IN_USE = 0x01,
1.601     rillig    200:
1.440     rillig    201:     /* The variable comes from the environment.
                    202:      * These variables are not registered in any GNode, therefore they must
                    203:      * be freed as soon as they are not used anymore. */
                    204:     VAR_FROM_ENV = 0x02,
1.601     rillig    205:
1.440     rillig    206:     /* The variable is exported to the environment, to be used by child
                    207:      * processes. */
                    208:     VAR_EXPORTED = 0x10,
1.601     rillig    209:
1.440     rillig    210:     /* At the point where this variable was exported, it contained an
                    211:      * unresolved reference to another variable.  Before any child process is
                    212:      * started, it needs to be exported again, in the hope that the referenced
                    213:      * variable can then be resolved. */
                    214:     VAR_REEXPORT = 0x20,
1.601     rillig    215:
                    216:     /* The variable came from the command line. */
1.457     sjg       217:     VAR_FROM_CMD = 0x40,
1.601     rillig    218:
                    219:     /* The variable value cannot be changed anymore, and the variable cannot
                    220:      * be deleted.  Any attempts to do so are ignored. */
1.457     sjg       221:     VAR_READONLY = 0x80
1.414     rillig    222: } VarFlags;
1.228     rillig    223:
1.527     rillig    224: ENUM_FLAGS_RTTI_6(VarFlags,
                    225:                  VAR_IN_USE, VAR_FROM_ENV,
1.471     rillig    226:                  VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY);
1.430     rillig    227:
1.570     rillig    228: /* Variables are defined using one of the VAR=value assignments.  Their
                    229:  * value can be queried by expressions such as $V, ${VAR}, or with modifiers
                    230:  * such as ${VAR:S,from,to,g:Q}.
                    231:  *
                    232:  * There are 3 kinds of variables: context variables, environment variables,
                    233:  * undefined variables.
                    234:  *
                    235:  * Context variables are stored in a GNode.context.  The only way to undefine
                    236:  * a context variable is using the .undef directive.  In particular, it must
                    237:  * not be possible to undefine a variable during the evaluation of an
                    238:  * expression, or Var.name might point nowhere.
                    239:  *
                    240:  * Environment variables are temporary.  They are returned by VarFind, and
                    241:  * after using them, they must be freed using VarFreeEnv.
                    242:  *
                    243:  * Undefined variables occur during evaluation of variable expressions such
                    244:  * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
                    245:  */
1.1       cgd       246: typedef struct Var {
1.570     rillig    247:     /* The name of the variable, once set, doesn't change anymore.
1.576     rillig    248:      * For context variables, it aliases the corresponding HashEntry name.
1.570     rillig    249:      * For environment and undefined variables, it is allocated. */
                    250:     const char *name;
                    251:     void *name_freeIt;
                    252:
1.138     dsl       253:     Buffer       val;          /* its value */
1.546     rillig    254:     VarFlags     flags;        /* miscellaneous status flags */
1.417     rillig    255: } Var;
1.1       cgd       256:
1.118     sjg       257: /*
                    258:  * Exporting vars is expensive so skip it if we can
                    259:  */
1.578     rillig    260: typedef enum VarExportedMode {
1.292     rillig    261:     VAR_EXPORTED_NONE,
1.602     rillig    262:     VAR_EXPORTED_SOME,
1.292     rillig    263:     VAR_EXPORTED_ALL
                    264: } VarExportedMode;
1.421     rillig    265:
1.292     rillig    266: static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
                    267:
1.578     rillig    268: typedef enum VarExportFlags {
1.292     rillig    269:     /*
                    270:      * We pass this to Var_Export when doing the initial export
                    271:      * or after updating an exported var.
                    272:      */
                    273:     VAR_EXPORT_PARENT  = 0x01,
                    274:     /*
                    275:      * We pass this to Var_Export1 to tell it to leave the value alone.
                    276:      */
                    277:     VAR_EXPORT_LITERAL = 0x02
                    278: } VarExportFlags;
1.16      christos  279:
1.261     rillig    280: /* Flags for pattern matching in the :S and :C modifiers */
1.578     rillig    281: typedef enum VarPatternFlags {
1.604     rillig    282:     VARP_SUB_GLOBAL    = 0x01, /* Replace as often as possible ('g') */
                    283:     VARP_SUB_ONE       = 0x02, /* Replace only once ('1') */
                    284:     VARP_ANCHOR_START  = 0x04, /* Match at start of word ('^') */
                    285:     VARP_ANCHOR_END    = 0x08  /* Match at end of word ('$') */
1.261     rillig    286: } VarPatternFlags;
1.16      christos  287:
1.569     rillig    288: static Var *
1.570     rillig    289: VarNew(const char *name, void *name_freeIt, const char *value, VarFlags flags)
1.569     rillig    290: {
                    291:     size_t value_len = strlen(value);
                    292:     Var *var = bmake_malloc(sizeof *var);
                    293:     var->name = name;
1.570     rillig    294:     var->name_freeIt = name_freeIt;
1.569     rillig    295:     Buf_Init(&var->val, value_len + 1);
                    296:     Buf_AddBytes(&var->val, value, value_len);
                    297:     var->flags = flags;
                    298:     return var;
                    299: }
                    300:
1.580     rillig    301: static const char *
                    302: CanonicalVarname(const char *name)
1.1       cgd       303: {
1.493     rillig    304:     if (*name == '.' && ch_isupper(name[1])) {
1.242     rillig    305:        switch (name[1]) {
                    306:        case 'A':
1.257     rillig    307:            if (strcmp(name, ".ALLSRC") == 0)
1.242     rillig    308:                name = ALLSRC;
1.257     rillig    309:            if (strcmp(name, ".ARCHIVE") == 0)
1.242     rillig    310:                name = ARCHIVE;
                    311:            break;
                    312:        case 'I':
1.257     rillig    313:            if (strcmp(name, ".IMPSRC") == 0)
1.242     rillig    314:                name = IMPSRC;
                    315:            break;
                    316:        case 'M':
1.257     rillig    317:            if (strcmp(name, ".MEMBER") == 0)
1.242     rillig    318:                name = MEMBER;
                    319:            break;
                    320:        case 'O':
1.257     rillig    321:            if (strcmp(name, ".OODATE") == 0)
1.242     rillig    322:                name = OODATE;
                    323:            break;
                    324:        case 'P':
1.257     rillig    325:            if (strcmp(name, ".PREFIX") == 0)
1.242     rillig    326:                name = PREFIX;
                    327:            break;
1.457     sjg       328:        case 'S':
1.580     rillig    329:            if (strcmp(name, ".SHELL") == 0) {
1.457     sjg       330:                if (!shellPath)
                    331:                    Shell_Init();
                    332:            }
                    333:            break;
1.242     rillig    334:        case 'T':
1.257     rillig    335:            if (strcmp(name, ".TARGET") == 0)
1.242     rillig    336:                name = TARGET;
                    337:            break;
                    338:        }
                    339:     }
                    340:
1.580     rillig    341:     /* GNU make has an additional alias $^ == ${.ALLSRC}. */
                    342:
                    343:     return name;
                    344: }
                    345:
1.587     rillig    346: static Var *
                    347: GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash)
                    348: {
1.588     rillig    349:     return HashTable_FindValueHash(&ctxt->context, varname, hash);
1.587     rillig    350: }
                    351:
1.605     rillig    352: /* Find the variable in the context, and maybe in other contexts as well.
1.580     rillig    353:  *
                    354:  * Input:
1.607     rillig    355:  *     name            name to find, is not expanded any further
1.605     rillig    356:  *     ctxt            context in which to look first
                    357:  *     elsewhere       TRUE to look in other contexts as well
1.580     rillig    358:  *
                    359:  * Results:
1.605     rillig    360:  *     The found variable, or NULL if the variable does not exist.
                    361:  *     If the variable is an environment variable, it must be freed using
                    362:  *     VarFreeEnv after use.
1.580     rillig    363:  */
                    364: static Var *
1.596     rillig    365: VarFind(const char *name, GNode *ctxt, Boolean elsewhere)
1.580     rillig    366: {
                    367:     Var *var;
1.586     rillig    368:     unsigned int nameHash;
1.580     rillig    369:
                    370:     /*
                    371:      * If the variable name begins with a '.', it could very well be one of
                    372:      * the local ones.  We check the name against all the local variables
                    373:      * and substitute the short version in for 'name' if it matches one of
                    374:      * them.
                    375:      */
                    376:     name = CanonicalVarname(name);
1.586     rillig    377:     nameHash = Hash_Hash(name);
1.160     christos  378:
1.605     rillig    379:     /* First look for the variable in the given context. */
1.587     rillig    380:     var = GNode_FindVar(ctxt, name, nameHash);
1.597     rillig    381:     if (!elsewhere)
1.599     rillig    382:        return var;
1.1       cgd       383:
1.605     rillig    384:     /* The variable was not found in the given context.  Now look for it in
                    385:      * the other contexts as well. */
1.597     rillig    386:     if (var == NULL && ctxt != VAR_CMDLINE)
1.594     rillig    387:        var = GNode_FindVar(VAR_CMDLINE, name, nameHash);
1.399     rillig    388:
1.597     rillig    389:     if (!opts.checkEnvFirst && var == NULL && ctxt != VAR_GLOBAL) {
1.587     rillig    390:        var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
1.231     rillig    391:        if (var == NULL && ctxt != VAR_INTERNAL) {
1.184     sjg       392:            /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
1.587     rillig    393:            var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
1.184     sjg       394:        }
1.1       cgd       395:     }
1.399     rillig    396:
1.597     rillig    397:     if (var == NULL) {
1.1       cgd       398:        char *env;
                    399:
1.570     rillig    400:        if ((env = getenv(name)) != NULL) {
                    401:            char *varname = bmake_strdup(name);
                    402:            return VarNew(varname, varname, env, VAR_FROM_ENV);
                    403:        }
1.399     rillig    404:
1.597     rillig    405:        if (opts.checkEnvFirst && ctxt != VAR_GLOBAL) {
1.587     rillig    406:            var = GNode_FindVar(VAR_GLOBAL, name, nameHash);
1.399     rillig    407:            if (var == NULL && ctxt != VAR_INTERNAL)
1.587     rillig    408:                var = GNode_FindVar(VAR_INTERNAL, name, nameHash);
1.542     rillig    409:            return var;
1.1       cgd       410:        }
1.399     rillig    411:
                    412:        return NULL;
                    413:     }
                    414:
1.542     rillig    415:     return var;
1.1       cgd       416: }
                    417:
1.605     rillig    418: /* If the variable is an environment variable, free it.
1.105     christos  419:  *
                    420:  * Input:
                    421:  *     v               the variable
1.605     rillig    422:  *     freeValue       true if the variable value should be freed as well
1.105     christos  423:  *
                    424:  * Results:
1.400     rillig    425:  *     TRUE if it is an environment variable, FALSE otherwise.
1.105     christos  426:  */
                    427: static Boolean
1.605     rillig    428: VarFreeEnv(Var *v, Boolean freeValue)
1.105     christos  429: {
1.257     rillig    430:     if (!(v->flags & VAR_FROM_ENV))
1.105     christos  431:        return FALSE;
1.605     rillig    432:
1.570     rillig    433:     free(v->name_freeIt);
1.605     rillig    434:     Buf_Destroy(&v->val, freeValue);
1.105     christos  435:     free(v);
                    436:     return TRUE;
                    437: }
                    438:
1.400     rillig    439: /* Add a new variable of the given name and value to the given context.
                    440:  * The name and val arguments are duplicated so they may safely be freed. */
1.5       cgd       441: static void
1.464     rillig    442: VarAdd(const char *name, const char *val, GNode *ctxt, VarSet_Flags flags)
1.1       cgd       443: {
1.588     rillig    444:     HashEntry *he = HashTable_CreateEntry(&ctxt->context, name, NULL);
1.605     rillig    445:     Var *v = VarNew(he->key /* aliased */, NULL, val,
1.577     rillig    446:                    flags & VAR_SET_READONLY ? VAR_READONLY : 0);
1.588     rillig    447:     HashEntry_Set(he, v);
1.547     rillig    448:     if (!(ctxt->flags & INTERNAL)) {
                    449:        VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
                    450:     }
1.1       cgd       451: }
                    452:
1.607     rillig    453: /* Remove a variable from a context, freeing all related memory as well.
                    454:  * The variable name is expanded once. */
1.1       cgd       455: void
1.73      christos  456: Var_Delete(const char *name, GNode *ctxt)
1.1       cgd       457: {
1.397     rillig    458:     char *name_freeIt = NULL;
1.576     rillig    459:     HashEntry *he;
1.412     rillig    460:
1.533     rillig    461:     if (strchr(name, '$') != NULL) {
                    462:        (void)Var_Subst(name, VAR_GLOBAL, VARE_WANTRES, &name_freeIt);
                    463:        /* TODO: handle errors */
                    464:        name = name_freeIt;
                    465:     }
1.588     rillig    466:     he = HashTable_FindEntry(&ctxt->context, name);
1.547     rillig    467:     VAR_DEBUG3("%s:delete %s%s\n",
                    468:               ctxt->name, name, he != NULL ? "" : " (not found)");
1.397     rillig    469:     free(name_freeIt);
                    470:
1.414     rillig    471:     if (he != NULL) {
1.588     rillig    472:        Var *v = HashEntry_Get(he);
1.292     rillig    473:        if (v->flags & VAR_EXPORTED)
1.118     sjg       474:            unsetenv(v->name);
1.420     rillig    475:        if (strcmp(v->name, MAKE_EXPORTED) == 0)
1.155     sjg       476:            var_exportedVars = VAR_EXPORTED_NONE;
1.570     rillig    477:        assert(v->name_freeIt == NULL);
1.588     rillig    478:        HashTable_DeleteEntry(&ctxt->context, he);
1.146     dsl       479:        Buf_Destroy(&v->val, TRUE);
1.98      christos  480:        free(v);
1.1       cgd       481:     }
                    482: }
                    483:
1.421     rillig    484: static Boolean
1.598     rillig    485: MayExport(const char *name)
1.118     sjg       486: {
1.422     rillig    487:     if (name[0] == '.')
1.421     rillig    488:        return FALSE;           /* skip internals */
1.567     rillig    489:     if (name[0] == '-')
                    490:        return FALSE;           /* skip misnamed variables */
1.422     rillig    491:     if (name[1] == '\0') {
1.118     sjg       492:        /*
                    493:         * A single char.
                    494:         * If it is one of the vars that should only appear in
                    495:         * local context, skip it, else we can get Var_Subst
                    496:         * into a loop.
                    497:         */
                    498:        switch (name[0]) {
                    499:        case '@':
                    500:        case '%':
                    501:        case '*':
                    502:        case '!':
1.421     rillig    503:            return FALSE;
1.118     sjg       504:        }
                    505:     }
1.598     rillig    506:     return TRUE;
                    507: }
                    508:
                    509: /*
                    510:  * Export a single variable.
                    511:  * We ignore make internal variables (those which start with '.').
                    512:  * Also we jump through some hoops to avoid calling setenv
                    513:  * more than necessary since it can leak.
                    514:  * We only manipulate flags of vars if 'parent' is set.
                    515:  */
                    516: static Boolean
                    517: Var_Export1(const char *name, VarExportFlags flags)
                    518: {
                    519:     VarExportFlags parent = flags & VAR_EXPORT_PARENT;
                    520:     Var *v;
                    521:     char *val;
                    522:
                    523:     if (!MayExport(name))
                    524:        return FALSE;
1.401     rillig    525:
1.412     rillig    526:     v = VarFind(name, VAR_GLOBAL, 0);
1.257     rillig    527:     if (v == NULL)
1.421     rillig    528:        return FALSE;
1.401     rillig    529:
1.372     rillig    530:     if (!parent && (v->flags & VAR_EXPORTED) && !(v->flags & VAR_REEXPORT))
1.421     rillig    531:        return FALSE;           /* nothing to do */
1.401     rillig    532:
1.433     rillig    533:     val = Buf_GetAll(&v->val, NULL);
1.422     rillig    534:     if (!(flags & VAR_EXPORT_LITERAL) && strchr(val, '$') != NULL) {
1.446     rillig    535:        char *expr;
1.412     rillig    536:
1.152     sjg       537:        if (parent) {
1.118     sjg       538:            /*
1.605     rillig    539:             * Flag the variable as something we need to re-export.
1.118     sjg       540:             * No point actually exporting it now though,
1.605     rillig    541:             * the child process can do it at the last minute.
1.118     sjg       542:             */
1.365     rillig    543:            v->flags |= VAR_EXPORTED | VAR_REEXPORT;
1.421     rillig    544:            return TRUE;
1.118     sjg       545:        }
1.158     sjg       546:        if (v->flags & VAR_IN_USE) {
                    547:            /*
                    548:             * We recursed while exporting in a child.
                    549:             * This isn't going to end well, just skip it.
                    550:             */
1.421     rillig    551:            return FALSE;
1.158     sjg       552:        }
1.446     rillig    553:
1.607     rillig    554:        /* XXX: name is injected without escaping it */
1.446     rillig    555:        expr = str_concat3("${", name, "}");
1.533     rillig    556:        (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &val);
                    557:        /* TODO: handle errors */
1.446     rillig    558:        setenv(name, val, 1);
                    559:        free(val);
                    560:        free(expr);
1.118     sjg       561:     } else {
1.292     rillig    562:        if (parent)
1.448     rillig    563:            v->flags &= ~(unsigned)VAR_REEXPORT;        /* once will do */
1.292     rillig    564:        if (parent || !(v->flags & VAR_EXPORTED))
1.118     sjg       565:            setenv(name, val, 1);
                    566:     }
1.605     rillig    567:
1.118     sjg       568:     /*
                    569:      * This is so Var_Set knows to call Var_Export again...
                    570:      */
1.152     sjg       571:     if (parent) {
                    572:        v->flags |= VAR_EXPORTED;
                    573:     }
1.421     rillig    574:     return TRUE;
1.118     sjg       575: }
                    576:
                    577: /*
1.605     rillig    578:  * This gets called from our child processes.
1.118     sjg       579:  */
                    580: void
                    581: Var_ExportVars(void)
                    582: {
1.412     rillig    583:     char *val;
                    584:
1.182     christos  585:     /*
                    586:      * Several make's support this sort of mechanism for tracking
                    587:      * recursion - but each uses a different name.
                    588:      * We allow the makefiles to update MAKELEVEL and ensure
                    589:      * children see a correctly incremented value.
                    590:      */
1.401     rillig    591:     char tmp[BUFSIZ];
1.182     christos  592:     snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
                    593:     setenv(MAKE_LEVEL_ENV, tmp, 1);
                    594:
1.420     rillig    595:     if (var_exportedVars == VAR_EXPORTED_NONE)
1.118     sjg       596:        return;
                    597:
1.420     rillig    598:     if (var_exportedVars == VAR_EXPORTED_ALL) {
1.599     rillig    599:        HashIter hi;
1.575     rillig    600:
                    601:        /* Ouch! Exporting all variables at once is crazy... */
                    602:        HashIter_Init(&hi, &VAR_GLOBAL->context);
1.603     rillig    603:        while (HashIter_Next(&hi) != NULL) {
                    604:            Var *var = hi.entry->value;
1.575     rillig    605:            Var_Export1(var->name, 0);
                    606:        }
1.118     sjg       607:        return;
                    608:     }
1.369     rillig    609:
1.533     rillig    610:     (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES, &val);
                    611:     /* TODO: handle errors */
1.369     rillig    612:     if (*val) {
1.494     rillig    613:        Words words = Str_Words(val, FALSE);
1.465     rillig    614:        size_t i;
1.142     dsl       615:
1.479     rillig    616:        for (i = 0; i < words.len; i++)
                    617:            Var_Export1(words.words[i], 0);
                    618:        Words_Free(words);
1.118     sjg       619:     }
1.369     rillig    620:     free(val);
1.118     sjg       621: }
                    622:
                    623: /*
1.400     rillig    624:  * This is called when .export is seen or .MAKE.EXPORTED is modified.
1.441     rillig    625:  *
1.400     rillig    626:  * It is also called when any exported variable is modified.
1.441     rillig    627:  * XXX: Is it really?
                    628:  *
                    629:  * str has the format "[-env|-literal] varname...".
1.118     sjg       630:  */
                    631: void
1.441     rillig    632: Var_Export(const char *str, Boolean isExport)
1.118     sjg       633: {
1.412     rillig    634:     VarExportFlags flags;
                    635:     char *val;
                    636:
1.422     rillig    637:     if (isExport && str[0] == '\0') {
1.118     sjg       638:        var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
                    639:        return;
                    640:     }
                    641:
1.567     rillig    642:     if (isExport && strncmp(str, "-env", 4) == 0) {
1.159     sjg       643:        str += 4;
1.571     rillig    644:        flags = 0;
1.567     rillig    645:     } else if (isExport && strncmp(str, "-literal", 8) == 0) {
1.203     sjg       646:        str += 8;
1.567     rillig    647:        flags = VAR_EXPORT_LITERAL;
1.159     sjg       648:     } else {
1.567     rillig    649:        flags = VAR_EXPORT_PARENT;
1.159     sjg       650:     }
1.302     rillig    651:
1.533     rillig    652:     (void)Var_Subst(str, VAR_GLOBAL, VARE_WANTRES, &val);
                    653:     /* TODO: handle errors */
1.422     rillig    654:     if (val[0] != '\0') {
1.494     rillig    655:        Words words = Str_Words(val, FALSE);
1.401     rillig    656:
1.465     rillig    657:        size_t i;
1.479     rillig    658:        for (i = 0; i < words.len; i++) {
                    659:            const char *name = words.words[i];
1.203     sjg       660:            if (Var_Export1(name, flags)) {
1.602     rillig    661:                if (var_exportedVars == VAR_EXPORTED_NONE)
                    662:                    var_exportedVars = VAR_EXPORTED_SOME;
1.203     sjg       663:                if (isExport && (flags & VAR_EXPORT_PARENT)) {
1.200     sjg       664:                    Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
                    665:                }
1.118     sjg       666:            }
                    667:        }
1.479     rillig    668:        Words_Free(words);
1.118     sjg       669:     }
                    670:     free(val);
                    671: }
                    672:
1.155     sjg       673:
1.257     rillig    674: extern char **environ;
                    675:
1.155     sjg       676: /*
                    677:  * This is called when .unexport[-env] is seen.
1.338     rillig    678:  *
                    679:  * str must have the form "unexport[-env] varname...".
1.155     sjg       680:  */
                    681: void
1.423     rillig    682: Var_UnExport(const char *str)
1.155     sjg       683: {
1.423     rillig    684:     const char *varnames;
                    685:     char *varnames_freeIt;
1.412     rillig    686:     Boolean unexport_env;
1.155     sjg       687:
1.423     rillig    688:     varnames = NULL;
                    689:     varnames_freeIt = NULL;
1.155     sjg       690:
1.338     rillig    691:     str += strlen("unexport");
1.412     rillig    692:     unexport_env = strncmp(str, "-env", 4) == 0;
1.155     sjg       693:     if (unexport_env) {
1.423     rillig    694:        const char *cp;
1.155     sjg       695:        char **newenv;
                    696:
1.179     sjg       697:        cp = getenv(MAKE_LEVEL_ENV);    /* we should preserve this */
1.170     sjg       698:        if (environ == savedEnv) {
1.155     sjg       699:            /* we have been here before! */
                    700:            newenv = bmake_realloc(environ, 2 * sizeof(char *));
                    701:        } else {
1.170     sjg       702:            if (savedEnv) {
                    703:                free(savedEnv);
                    704:                savedEnv = NULL;
1.155     sjg       705:            }
                    706:            newenv = bmake_malloc(2 * sizeof(char *));
                    707:        }
1.423     rillig    708:
1.155     sjg       709:        /* Note: we cannot safely free() the original environ. */
1.170     sjg       710:        environ = savedEnv = newenv;
1.155     sjg       711:        newenv[0] = NULL;
                    712:        newenv[1] = NULL;
1.221     sjg       713:        if (cp && *cp)
                    714:            setenv(MAKE_LEVEL_ENV, cp, 1);
1.155     sjg       715:     } else {
1.567     rillig    716:        cpp_skip_whitespace(&str);
1.423     rillig    717:        if (str[0] != '\0')
                    718:            varnames = str;
1.155     sjg       719:     }
                    720:
1.423     rillig    721:     if (varnames == NULL) {
1.155     sjg       722:        /* Using .MAKE.EXPORTED */
1.533     rillig    723:        (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES,
                    724:                        &varnames_freeIt);
                    725:        /* TODO: handle errors */
                    726:        varnames = varnames_freeIt;
1.155     sjg       727:     }
1.423     rillig    728:
1.477     rillig    729:     {
1.155     sjg       730:        Var *v;
1.465     rillig    731:        size_t i;
1.155     sjg       732:
1.479     rillig    733:        Words words = Str_Words(varnames, FALSE);
                    734:        for (i = 0; i < words.len; i++) {
                    735:            const char *varname = words.words[i];
                    736:            v = VarFind(varname, VAR_GLOBAL, 0);
1.423     rillig    737:            if (v == NULL) {
1.547     rillig    738:                VAR_DEBUG1("Not unexporting \"%s\" (not found)\n", varname);
1.155     sjg       739:                continue;
1.423     rillig    740:            }
                    741:
1.547     rillig    742:            VAR_DEBUG1("Unexporting \"%s\"\n", varname);
1.423     rillig    743:            if (!unexport_env && (v->flags & VAR_EXPORTED) &&
                    744:                !(v->flags & VAR_REEXPORT))
1.155     sjg       745:                unsetenv(v->name);
1.448     rillig    746:            v->flags &= ~(unsigned)(VAR_EXPORTED | VAR_REEXPORT);
1.423     rillig    747:
1.155     sjg       748:            /*
                    749:             * If we are unexporting a list,
                    750:             * remove each one from .MAKE.EXPORTED.
                    751:             * If we are removing them all,
                    752:             * just delete .MAKE.EXPORTED below.
                    753:             */
1.423     rillig    754:            if (varnames == str) {
1.614     rillig    755:                /* XXX: v->name is injected without escaping it */
1.446     rillig    756:                char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}");
1.533     rillig    757:                char *cp;
                    758:                (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp);
                    759:                /* TODO: handle errors */
1.446     rillig    760:                Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL);
                    761:                free(cp);
                    762:                free(expr);
1.155     sjg       763:            }
                    764:        }
1.479     rillig    765:        Words_Free(words);
1.423     rillig    766:        if (varnames != str) {
1.155     sjg       767:            Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
1.423     rillig    768:            free(varnames_freeIt);
1.155     sjg       769:        }
                    770:     }
                    771: }
                    772:
1.400     rillig    773: /* See Var_Set for documentation. */
1.457     sjg       774: void
1.242     rillig    775: Var_Set_with_flags(const char *name, const char *val, GNode *ctxt,
                    776:                   VarSet_Flags flags)
1.1       cgd       777: {
1.458     rillig    778:     const char *unexpanded_name = name;
1.370     rillig    779:     char *name_freeIt = NULL;
1.412     rillig    780:     Var *v;
1.142     dsl       781:
1.460     rillig    782:     assert(val != NULL);
                    783:
1.533     rillig    784:     if (strchr(name, '$') != NULL) {
                    785:        (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
                    786:        /* TODO: handle errors */
                    787:        name = name_freeIt;
                    788:     }
1.458     rillig    789:
                    790:     if (name[0] == '\0') {
1.547     rillig    791:        VAR_DEBUG2("Var_Set(\"%s\", \"%s\", ...) "
                    792:                   "name expands to empty string - ignored\n",
                    793:                   unexpanded_name, val);
1.458     rillig    794:        free(name_freeIt);
                    795:        return;
1.139     dsl       796:     }
1.400     rillig    797:
1.129     sjg       798:     if (ctxt == VAR_GLOBAL) {
1.594     rillig    799:        v = VarFind(name, VAR_CMDLINE, 0);
1.136     dsl       800:        if (v != NULL) {
1.371     rillig    801:            if (v->flags & VAR_FROM_CMD) {
1.547     rillig    802:                VAR_DEBUG3("%s:%s = %s ignored!\n", ctxt->name, name, val);
1.131     sjg       803:                goto out;
                    804:            }
                    805:            VarFreeEnv(v, TRUE);
1.129     sjg       806:        }
                    807:     }
1.400     rillig    808:
1.582     rillig    809:     /*
                    810:      * We only look for a variable in the given context since anything set
                    811:      * here will override anything in a lower context, so there's not much
                    812:      * point in searching them all just to save a bit of memory...
                    813:      */
1.92      christos  814:     v = VarFind(name, ctxt, 0);
1.136     dsl       815:     if (v == NULL) {
1.594     rillig    816:        if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT)) {
1.183     sjg       817:            /*
                    818:             * This var would normally prevent the same name being added
                    819:             * to VAR_GLOBAL, so delete it from there if needed.
                    820:             * Otherwise -V name may show the wrong value.
                    821:             */
1.607     rillig    822:            /* XXX: name is expanded for the second time */
1.183     sjg       823:            Var_Delete(name, VAR_GLOBAL);
                    824:        }
1.464     rillig    825:        VarAdd(name, val, ctxt, flags);
1.1       cgd       826:     } else {
1.457     sjg       827:        if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) {
1.547     rillig    828:            VAR_DEBUG3("%s:%s = %s ignored (read-only)\n",
                    829:                       ctxt->name, name, val);
1.457     sjg       830:            goto out;
1.599     rillig    831:        }
1.146     dsl       832:        Buf_Empty(&v->val);
1.608     rillig    833:        Buf_AddStr(&v->val, val);
1.1       cgd       834:
1.547     rillig    835:        VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
1.371     rillig    836:        if (v->flags & VAR_EXPORTED) {
1.152     sjg       837:            Var_Export1(name, VAR_EXPORT_PARENT);
1.118     sjg       838:        }
1.1       cgd       839:     }
                    840:     /*
                    841:      * Any variables given on the command line are automatically exported
                    842:      * to the environment (as per POSIX standard)
1.457     sjg       843:      * Other than internals.
1.1       cgd       844:      */
1.594     rillig    845:     if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT) && name[0] != '.') {
1.608     rillig    846:        if (v == NULL)
                    847:            v = VarFind(name, ctxt, 0); /* we just added it */
                    848:        v->flags |= VAR_FROM_CMD;
                    849:
1.71      thorpej   850:        /*
                    851:         * If requested, don't export these in the environment
                    852:         * individually.  We still put them in MAKEOVERRIDES so
                    853:         * that the command-line settings continue to override
                    854:         * Makefile settings.
                    855:         */
1.590     rillig    856:        if (!opts.varNoExportEnv)
1.613     rillig    857:            setenv(name, val, 1);
1.62      sjg       858:
1.64      sjg       859:        Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
1.1       cgd       860:     }
1.593     rillig    861:     if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
1.292     rillig    862:        save_dollars = s2Boolean(val, save_dollars);
1.205     sjg       863:
1.242     rillig    864: out:
1.370     rillig    865:     free(name_freeIt);
1.136     dsl       866:     if (v != NULL)
1.107     christos  867:        VarFreeEnv(v, TRUE);
1.1       cgd       868: }
                    869:
                    870: /*-
                    871:  *-----------------------------------------------------------------------
1.230     rillig    872:  * Var_Set --
                    873:  *     Set the variable name to the value val in the given context.
                    874:  *
1.483     rillig    875:  *     If the variable doesn't yet exist, it is created.
                    876:  *     Otherwise the new value overwrites and replaces the old value.
                    877:  *
1.230     rillig    878:  * Input:
1.607     rillig    879:  *     name            name of the variable to set, is expanded once
1.230     rillig    880:  *     val             value to give to the variable
                    881:  *     ctxt            context in which to set it
                    882:  *
                    883:  * Notes:
                    884:  *     The variable is searched for only in its context before being
                    885:  *     created in that context. I.e. if the context is VAR_GLOBAL,
1.594     rillig    886:  *     only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMDLINE,
                    887:  *     only VAR_CMDLINE->context is searched. This is done to avoid the
                    888:  *     literally thousands of unnecessary strcmp's that used to be done to
1.230     rillig    889:  *     set, say, $(@) or $(<).
                    890:  *     If the context is VAR_GLOBAL though, we check if the variable
1.594     rillig    891:  *     was set in VAR_CMDLINE from the command line and skip it if so.
1.230     rillig    892:  *-----------------------------------------------------------------------
                    893:  */
                    894: void
                    895: Var_Set(const char *name, const char *val, GNode *ctxt)
                    896: {
1.242     rillig    897:     Var_Set_with_flags(name, val, ctxt, 0);
1.230     rillig    898: }
                    899:
                    900: /*-
                    901:  *-----------------------------------------------------------------------
1.1       cgd       902:  * Var_Append --
                    903:  *     The variable of the given name has the given value appended to it in
                    904:  *     the given context.
                    905:  *
1.483     rillig    906:  *     If the variable doesn't exist, it is created. Otherwise the strings
                    907:  *     are concatenated, with a space in between.
                    908:  *
1.70      wiz       909:  * Input:
1.607     rillig    910:  *     name            name of the variable to modify, is expanded once
1.400     rillig    911:  *     val             string to append to it
                    912:  *     ctxt            context in which this should occur
1.70      wiz       913:  *
1.1       cgd       914:  * Notes:
                    915:  *     Only if the variable is being sought in the global context is the
                    916:  *     environment searched.
                    917:  *     XXX: Knows its calling circumstances in that if called with ctxt
                    918:  *     an actual target, it will only search that context since only
                    919:  *     a local variable could be being appended to. This is actually
                    920:  *     a big win and must be tolerated.
                    921:  *-----------------------------------------------------------------------
                    922:  */
                    923: void
1.73      christos  924: Var_Append(const char *name, const char *val, GNode *ctxt)
1.1       cgd       925: {
1.427     rillig    926:     char *name_freeIt = NULL;
1.412     rillig    927:     Var *v;
1.1       cgd       928:
1.460     rillig    929:     assert(val != NULL);
                    930:
1.139     dsl       931:     if (strchr(name, '$') != NULL) {
1.456     rillig    932:        const char *unexpanded_name = name;
1.533     rillig    933:        (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
                    934:        /* TODO: handle errors */
                    935:        name = name_freeIt;
1.427     rillig    936:        if (name[0] == '\0') {
1.547     rillig    937:            VAR_DEBUG2("Var_Append(\"%s\", \"%s\", ...) "
1.599     rillig    938:                       "name expands to empty string - ignored\n",
                    939:                       unexpanded_name, val);
1.427     rillig    940:            free(name_freeIt);
1.139     dsl       941:            return;
                    942:        }
                    943:     }
1.142     dsl       944:
1.596     rillig    945:     v = VarFind(name, ctxt, ctxt == VAR_GLOBAL);
1.1       cgd       946:
1.136     dsl       947:     if (v == NULL) {
1.607     rillig    948:        /* XXX: name is expanded for the second time */
1.230     rillig    949:        Var_Set(name, val, ctxt);
1.600     rillig    950:     } else if (v->flags & VAR_READONLY) {
1.614     rillig    951:        VAR_DEBUG1("Ignoring append to %s since it is read-only\n", name);
1.594     rillig    952:     } else if (ctxt == VAR_CMDLINE || !(v->flags & VAR_FROM_CMD)) {
1.146     dsl       953:        Buf_AddByte(&v->val, ' ');
1.313     rillig    954:        Buf_AddStr(&v->val, val);
1.1       cgd       955:
1.547     rillig    956:        VAR_DEBUG3("%s:%s = %s\n",
1.599     rillig    957:                   ctxt->name, name, Buf_GetAll(&v->val, NULL));
1.1       cgd       958:
                    959:        if (v->flags & VAR_FROM_ENV) {
1.576     rillig    960:            HashEntry *h;
1.412     rillig    961:
1.1       cgd       962:            /*
                    963:             * If the original variable came from the environment, we
                    964:             * have to install it in the global context (we could place
                    965:             * it in the environment, but then we should provide a way to
                    966:             * export other variables...)
                    967:             */
1.448     rillig    968:            v->flags &= ~(unsigned)VAR_FROM_ENV;
1.588     rillig    969:            h = HashTable_CreateEntry(&ctxt->context, name, NULL);
                    970:            HashEntry_Set(h, v);
1.1       cgd       971:        }
                    972:     }
1.427     rillig    973:     free(name_freeIt);
1.1       cgd       974: }
                    975:
1.483     rillig    976: /* See if the given variable exists, in the given context or in other
                    977:  * fallback contexts.
1.1       cgd       978:  *
1.70      wiz       979:  * Input:
1.607     rillig    980:  *     name            Variable to find, is expanded once
1.70      wiz       981:  *     ctxt            Context in which to start search
1.1       cgd       982:  */
                    983: Boolean
1.73      christos  984: Var_Exists(const char *name, GNode *ctxt)
1.1       cgd       985: {
1.373     rillig    986:     char *name_freeIt = NULL;
1.412     rillig    987:     Var *v;
                    988:
1.533     rillig    989:     if (strchr(name, '$') != NULL) {
                    990:        (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt);
                    991:        /* TODO: handle errors */
                    992:        name = name_freeIt;
                    993:     }
1.1       cgd       994:
1.596     rillig    995:     v = VarFind(name, ctxt, TRUE);
1.373     rillig    996:     free(name_freeIt);
1.257     rillig    997:     if (v == NULL)
1.231     rillig    998:        return FALSE;
                    999:
                   1000:     (void)VarFreeEnv(v, TRUE);
                   1001:     return TRUE;
1.1       cgd      1002: }
                   1003:
                   1004: /*-
                   1005:  *-----------------------------------------------------------------------
                   1006:  * Var_Value --
1.337     rillig   1007:  *     Return the unexpanded value of the given variable in the given
1.374     rillig   1008:  *     context, or the usual contexts.
1.1       cgd      1009:  *
1.70      wiz      1010:  * Input:
1.607     rillig   1011:  *     name            name to find, is not expanded any further
1.70      wiz      1012:  *     ctxt            context in which to search for it
                   1013:  *
1.1       cgd      1014:  * Results:
1.337     rillig   1015:  *     The value if the variable exists, NULL if it doesn't.
1.632     rillig   1016:  *     If the returned value is not NULL, the caller must free
                   1017:  *     out_freeIt when the returned value is no longer needed.
1.1       cgd      1018:  *-----------------------------------------------------------------------
                   1019:  */
1.375     rillig   1020: const char *
1.632     rillig   1021: Var_Value(const char *name, GNode *ctxt, void **out_freeIt)
1.1       cgd      1022: {
1.596     rillig   1023:     Var *v = VarFind(name, ctxt, TRUE);
1.609     rillig   1024:     char *value;
1.412     rillig   1025:
1.632     rillig   1026:     *out_freeIt = NULL;
1.231     rillig   1027:     if (v == NULL)
1.136     dsl      1028:        return NULL;
1.231     rillig   1029:
1.609     rillig   1030:     value = Buf_GetAll(&v->val, NULL);
1.231     rillig   1031:     if (VarFreeEnv(v, FALSE))
1.632     rillig   1032:        *out_freeIt = value;
1.609     rillig   1033:     return value;
1.1       cgd      1034: }
                   1035:
1.616     rillig   1036: /* Return the unexpanded variable value from this node, without trying to look
                   1037:  * up the variable in any other context. */
                   1038: const char *
                   1039: Var_ValueDirect(const char *name, GNode *ctxt)
                   1040: {
                   1041:     Var *v = VarFind(name, ctxt, FALSE);
                   1042:     return v != NULL ? Buf_GetAll(&v->val, NULL) : NULL;
                   1043: }
                   1044:
1.244     rillig   1045:
1.610     rillig   1046: /* SepBuf is a string being built from words, interleaved with separators. */
1.541     rillig   1047: typedef struct SepBuf {
1.278     rillig   1048:     Buffer buf;
                   1049:     Boolean needSep;
1.453     rillig   1050:     char sep;                  /* usually ' ', but see the :ts modifier */
1.278     rillig   1051: } SepBuf;
                   1052:
                   1053: static void
                   1054: SepBuf_Init(SepBuf *buf, char sep)
                   1055: {
1.433     rillig   1056:     Buf_Init(&buf->buf, 32 /* bytes */);
1.278     rillig   1057:     buf->needSep = FALSE;
                   1058:     buf->sep = sep;
                   1059: }
                   1060:
                   1061: static void
                   1062: SepBuf_Sep(SepBuf *buf)
                   1063: {
                   1064:     buf->needSep = TRUE;
                   1065: }
                   1066:
                   1067: static void
1.314     rillig   1068: SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1.278     rillig   1069: {
                   1070:     if (mem_size == 0)
                   1071:        return;
                   1072:     if (buf->needSep && buf->sep != '\0') {
                   1073:        Buf_AddByte(&buf->buf, buf->sep);
                   1074:        buf->needSep = FALSE;
                   1075:     }
1.433     rillig   1076:     Buf_AddBytes(&buf->buf, mem, mem_size);
1.278     rillig   1077: }
                   1078:
1.314     rillig   1079: static void
                   1080: SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end)
                   1081: {
                   1082:     SepBuf_AddBytes(buf, start, (size_t)(end - start));
                   1083: }
                   1084:
                   1085: static void
                   1086: SepBuf_AddStr(SepBuf *buf, const char *str)
                   1087: {
                   1088:     SepBuf_AddBytes(buf, str, strlen(str));
                   1089: }
                   1090:
1.278     rillig   1091: static char *
                   1092: SepBuf_Destroy(SepBuf *buf, Boolean free_buf)
                   1093: {
                   1094:     return Buf_Destroy(&buf->buf, free_buf);
                   1095: }
                   1096:
                   1097:
1.609     rillig   1098: /* This callback for ModifyWords gets a single word from a variable expression
                   1099:  * and typically adds a modification of this word to the buffer. It may also
                   1100:  * do nothing or add several words.
                   1101:  *
                   1102:  * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for
                   1103:  * each word of "a b c". */
1.295     rillig   1104: typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data);
1.244     rillig   1105:
                   1106:
1.291     rillig   1107: /* Callback for ModifyWords to implement the :H modifier.
1.244     rillig   1108:  * Add the dirname of the given word to the buffer. */
1.278     rillig   1109: static void
1.295     rillig   1110: ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1111: {
1.238     rillig   1112:     const char *slash = strrchr(word, '/');
                   1113:     if (slash != NULL)
1.314     rillig   1114:        SepBuf_AddBytesBetween(buf, word, slash);
1.238     rillig   1115:     else
1.314     rillig   1116:        SepBuf_AddStr(buf, ".");
1.1       cgd      1117: }
                   1118:
1.291     rillig   1119: /* Callback for ModifyWords to implement the :T modifier.
1.244     rillig   1120:  * Add the basename of the given word to the buffer. */
1.278     rillig   1121: static void
1.295     rillig   1122: ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1123: {
1.238     rillig   1124:     const char *slash = strrchr(word, '/');
                   1125:     const char *base = slash != NULL ? slash + 1 : word;
1.314     rillig   1126:     SepBuf_AddStr(buf, base);
1.1       cgd      1127: }
                   1128:
1.291     rillig   1129: /* Callback for ModifyWords to implement the :E modifier.
1.244     rillig   1130:  * Add the filename suffix of the given word to the buffer, if it exists. */
1.278     rillig   1131: static void
1.295     rillig   1132: ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1133: {
1.239     rillig   1134:     const char *dot = strrchr(word, '.');
1.278     rillig   1135:     if (dot != NULL)
1.314     rillig   1136:        SepBuf_AddStr(buf, dot + 1);
1.1       cgd      1137: }
                   1138:
1.291     rillig   1139: /* Callback for ModifyWords to implement the :R modifier.
                   1140:  * Add the basename of the given word to the buffer. */
1.278     rillig   1141: static void
1.295     rillig   1142: ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1143: {
1.314     rillig   1144:     const char *dot = strrchr(word, '.');
1.247     lukem    1145:     size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1.278     rillig   1146:     SepBuf_AddBytes(buf, word, len);
1.1       cgd      1147: }
                   1148:
1.291     rillig   1149: /* Callback for ModifyWords to implement the :M modifier.
1.244     rillig   1150:  * Place the word in the buffer if it matches the given pattern. */
1.278     rillig   1151: static void
1.295     rillig   1152: ModifyWord_Match(const char *word, SepBuf *buf, void *data)
1.1       cgd      1153: {
1.244     rillig   1154:     const char *pattern = data;
1.547     rillig   1155:     VAR_DEBUG2("VarMatch [%s] [%s]\n", word, pattern);
1.278     rillig   1156:     if (Str_Match(word, pattern))
1.314     rillig   1157:        SepBuf_AddStr(buf, word);
1.1       cgd      1158: }
                   1159:
1.291     rillig   1160: /* Callback for ModifyWords to implement the :N modifier.
                   1161:  * Place the word in the buffer if it doesn't match the given pattern. */
                   1162: static void
1.295     rillig   1163: ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
1.291     rillig   1164: {
                   1165:     const char *pattern = data;
                   1166:     if (!Str_Match(word, pattern))
1.314     rillig   1167:        SepBuf_AddStr(buf, word);
1.291     rillig   1168: }
                   1169:
1.13      christos 1170: #ifdef SYSVVARSUB
1.610     rillig   1171: /* Check word against pattern for a match (% is a wildcard).
1.256     rillig   1172:  *
                   1173:  * Input:
                   1174:  *     word            Word to examine
                   1175:  *     pattern         Pattern to examine against
                   1176:  *
                   1177:  * Results:
1.377     rillig   1178:  *     Returns the start of the match, or NULL.
1.610     rillig   1179:  *     out_match_len returns the length of the match, if any.
                   1180:  *     out_hasPercent returns whether the pattern contains a percent.
1.256     rillig   1181:  */
1.277     rillig   1182: static const char *
1.610     rillig   1183: SysVMatch(const char *word, const char *pattern,
                   1184:              size_t *out_match_len, Boolean *out_hasPercent)
1.256     rillig   1185: {
                   1186:     const char *p = pattern;
                   1187:     const char *w = word;
1.412     rillig   1188:     const char *percent;
                   1189:     size_t w_len;
                   1190:     size_t p_len;
                   1191:     const char *w_tail;
1.256     rillig   1192:
1.610     rillig   1193:     *out_hasPercent = FALSE;
1.412     rillig   1194:     percent = strchr(p, '%');
1.377     rillig   1195:     if (percent != NULL) {     /* ${VAR:...%...=...} */
1.610     rillig   1196:        *out_hasPercent = TRUE;
1.377     rillig   1197:        if (*w == '\0')
                   1198:            return NULL;        /* empty word does not match pattern */
                   1199:
1.256     rillig   1200:        /* check that the prefix matches */
1.377     rillig   1201:        for (; p != percent && *w != '\0' && *w == *p; w++, p++)
1.417     rillig   1202:            continue;
1.377     rillig   1203:        if (p != percent)
1.256     rillig   1204:            return NULL;        /* No match */
                   1205:
1.377     rillig   1206:        p++;                    /* Skip the percent */
                   1207:        if (*p == '\0') {
1.256     rillig   1208:            /* No more pattern, return the rest of the string */
1.610     rillig   1209:            *out_match_len = strlen(w);
1.277     rillig   1210:            return w;
1.256     rillig   1211:        }
                   1212:     }
                   1213:
1.378     rillig   1214:     /* Test whether the tail matches */
1.412     rillig   1215:     w_len = strlen(w);
                   1216:     p_len = strlen(p);
1.378     rillig   1217:     if (w_len < p_len)
                   1218:        return NULL;
1.256     rillig   1219:
1.412     rillig   1220:     w_tail = w + w_len - p_len;
1.378     rillig   1221:     if (memcmp(p, w_tail, p_len) != 0)
1.380     rillig   1222:        return NULL;
1.256     rillig   1223:
1.610     rillig   1224:     *out_match_len = (size_t)(w_tail - w);
1.378     rillig   1225:     return w;
1.256     rillig   1226: }
                   1227:
1.541     rillig   1228: struct ModifyWord_SYSVSubstArgs {
1.295     rillig   1229:     GNode *ctx;
1.276     rillig   1230:     const char *lhs;
                   1231:     const char *rhs;
1.541     rillig   1232: };
1.276     rillig   1233:
1.291     rillig   1234: /* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1.278     rillig   1235: static void
1.295     rillig   1236: ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
1.5       cgd      1237: {
1.541     rillig   1238:     const struct ModifyWord_SYSVSubstArgs *args = data;
1.412     rillig   1239:     char *rhs_expanded;
                   1240:     const char *rhs;
                   1241:     const char *percent;
1.5       cgd      1242:
1.377     rillig   1243:     size_t match_len;
                   1244:     Boolean lhsPercent;
1.610     rillig   1245:     const char *match = SysVMatch(word, args->lhs, &match_len, &lhsPercent);
1.379     rillig   1246:     if (match == NULL) {
1.314     rillig   1247:        SepBuf_AddStr(buf, word);
1.379     rillig   1248:        return;
                   1249:     }
                   1250:
                   1251:     /* Append rhs to the buffer, substituting the first '%' with the
                   1252:      * match, but only if the lhs had a '%' as well. */
                   1253:
1.533     rillig   1254:     (void)Var_Subst(args->rhs, args->ctx, VARE_WANTRES, &rhs_expanded);
                   1255:     /* TODO: handle errors */
1.379     rillig   1256:
1.412     rillig   1257:     rhs = rhs_expanded;
                   1258:     percent = strchr(rhs, '%');
1.379     rillig   1259:
                   1260:     if (percent != NULL && lhsPercent) {
                   1261:        /* Copy the prefix of the replacement pattern */
                   1262:        SepBuf_AddBytesBetween(buf, rhs, percent);
                   1263:        rhs = percent + 1;
1.61      explorer 1264:     }
1.379     rillig   1265:     if (percent != NULL || !lhsPercent)
                   1266:        SepBuf_AddBytes(buf, match, match_len);
                   1267:
                   1268:     /* Append the suffix of the replacement pattern */
                   1269:     SepBuf_AddStr(buf, rhs);
                   1270:
                   1271:     free(rhs_expanded);
1.5       cgd      1272: }
1.13      christos 1273: #endif
1.5       cgd      1274:
1.1       cgd      1275:
1.541     rillig   1276: struct ModifyWord_SubstArgs {
1.291     rillig   1277:     const char *lhs;
                   1278:     size_t     lhsLen;
                   1279:     const char *rhs;
                   1280:     size_t     rhsLen;
                   1281:     VarPatternFlags pflags;
1.452     rillig   1282:     Boolean    matched;
1.541     rillig   1283: };
1.291     rillig   1284:
                   1285: /* Callback for ModifyWords to implement the :S,from,to, modifier.
1.244     rillig   1286:  * Perform a string substitution on the given word. */
1.278     rillig   1287: static void
1.295     rillig   1288: ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
1.1       cgd      1289: {
1.279     rillig   1290:     size_t wordLen = strlen(word);
1.541     rillig   1291:     struct ModifyWord_SubstArgs *args = data;
1.412     rillig   1292:     const char *match;
1.1       cgd      1293:
1.452     rillig   1294:     if ((args->pflags & VARP_SUB_ONE) && args->matched)
1.279     rillig   1295:        goto nosub;
                   1296:
1.288     rillig   1297:     if (args->pflags & VARP_ANCHOR_START) {
1.282     rillig   1298:        if (wordLen < args->lhsLen ||
                   1299:            memcmp(word, args->lhs, args->lhsLen) != 0)
1.1       cgd      1300:            goto nosub;
1.279     rillig   1301:
1.611     rillig   1302:        if ((args->pflags & VARP_ANCHOR_END) && wordLen != args->lhsLen)
                   1303:            goto nosub;
                   1304:
                   1305:        /* :S,^prefix,replacement, or :S,^whole$,replacement, */
                   1306:        SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
                   1307:        SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen);
                   1308:        args->matched = TRUE;
1.278     rillig   1309:        return;
1.1       cgd      1310:     }
1.279     rillig   1311:
1.288     rillig   1312:     if (args->pflags & VARP_ANCHOR_END) {
1.417     rillig   1313:        const char *start;
1.412     rillig   1314:
1.281     rillig   1315:        if (wordLen < args->lhsLen)
1.280     rillig   1316:            goto nosub;
1.315     rillig   1317:
1.412     rillig   1318:        start = word + (wordLen - args->lhsLen);
1.281     rillig   1319:        if (memcmp(start, args->lhs, args->lhsLen) != 0)
1.279     rillig   1320:            goto nosub;
                   1321:
1.476     rillig   1322:        /* :S,suffix$,replacement, */
1.314     rillig   1323:        SepBuf_AddBytesBetween(buf, word, start);
1.281     rillig   1324:        SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1.452     rillig   1325:        args->matched = TRUE;
1.279     rillig   1326:        return;
                   1327:     }
                   1328:
1.567     rillig   1329:     if (args->lhs[0] == '\0')
1.571     rillig   1330:        goto nosub;
1.567     rillig   1331:
1.424     rillig   1332:     /* unanchored case, may match more than once */
1.567     rillig   1333:     while ((match = strstr(word, args->lhs)) != NULL) {
1.315     rillig   1334:        SepBuf_AddBytesBetween(buf, word, match);
1.281     rillig   1335:        SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1.452     rillig   1336:        args->matched = TRUE;
1.448     rillig   1337:        wordLen -= (size_t)(match - word) + args->lhsLen;
                   1338:        word += (size_t)(match - word) + args->lhsLen;
1.281     rillig   1339:        if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL))
1.279     rillig   1340:            break;
                   1341:     }
1.242     rillig   1342: nosub:
1.278     rillig   1343:     SepBuf_AddBytes(buf, word, wordLen);
1.1       cgd      1344: }
                   1345:
1.31      gwr      1346: #ifndef NO_REGEX
1.400     rillig   1347: /* Print the error caused by a regcomp or regexec call. */
1.16      christos 1348: static void
1.202     christos 1349: VarREError(int reerr, regex_t *pat, const char *str)
1.16      christos 1350: {
1.448     rillig   1351:     size_t errlen = regerror(reerr, pat, 0, 0);
1.401     rillig   1352:     char *errbuf = bmake_malloc(errlen);
1.202     christos 1353:     regerror(reerr, pat, errbuf, errlen);
1.16      christos 1354:     Error("%s: %s", str, errbuf);
                   1355:     free(errbuf);
                   1356: }
                   1357:
1.541     rillig   1358: struct ModifyWord_SubstRegexArgs {
1.546     rillig   1359:     regex_t re;
                   1360:     size_t nsub;
                   1361:     char *replace;
1.291     rillig   1362:     VarPatternFlags pflags;
1.546     rillig   1363:     Boolean matched;
1.541     rillig   1364: };
1.291     rillig   1365:
                   1366: /* Callback for ModifyWords to implement the :C/from/to/ modifier.
1.244     rillig   1367:  * Perform a regex substitution on the given word. */
1.278     rillig   1368: static void
1.295     rillig   1369: ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data)
1.16      christos 1370: {
1.541     rillig   1371:     struct ModifyWord_SubstRegexArgs *args = data;
1.16      christos 1372:     int xrv;
1.253     rillig   1373:     const char *wp = word;
1.16      christos 1374:     char *rp;
1.20      christos 1375:     int flags = 0;
1.305     rillig   1376:     regmatch_t m[10];
1.16      christos 1377:
1.452     rillig   1378:     if ((args->pflags & VARP_SUB_ONE) && args->matched)
1.307     rillig   1379:        goto nosub;
                   1380:
                   1381: tryagain:
                   1382:     xrv = regexec(&args->re, wp, args->nsub, m, flags);
1.16      christos 1383:
                   1384:     switch (xrv) {
                   1385:     case 0:
1.452     rillig   1386:        args->matched = TRUE;
1.448     rillig   1387:        SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1.16      christos 1388:
1.304     rillig   1389:        for (rp = args->replace; *rp; rp++) {
1.278     rillig   1390:            if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
                   1391:                SepBuf_AddBytes(buf, rp + 1, 1);
1.16      christos 1392:                rp++;
1.445     rillig   1393:                continue;
                   1394:            }
                   1395:
                   1396:            if (*rp == '&') {
                   1397:                SepBuf_AddBytesBetween(buf, wp + m[0].rm_so, wp + m[0].rm_eo);
                   1398:                continue;
                   1399:            }
                   1400:
1.493     rillig   1401:            if (*rp != '\\' || !ch_isdigit(rp[1])) {
1.445     rillig   1402:                SepBuf_AddBytes(buf, rp, 1);
                   1403:                continue;
                   1404:            }
                   1405:
                   1406:            {                   /* \0 to \9 backreference */
1.448     rillig   1407:                size_t n = (size_t)(rp[1] - '0');
1.445     rillig   1408:                rp++;
1.16      christos 1409:
1.304     rillig   1410:                if (n >= args->nsub) {
1.448     rillig   1411:                    Error("No subexpression \\%zu", n);
1.617     rillig   1412:                } else if (m[n].rm_so == -1) {
1.448     rillig   1413:                    Error("No match for subexpression \\%zu", n);
1.242     rillig   1414:                } else {
1.314     rillig   1415:                    SepBuf_AddBytesBetween(buf, wp + m[n].rm_so,
                   1416:                                           wp + m[n].rm_eo);
1.16      christos 1417:                }
                   1418:            }
                   1419:        }
1.445     rillig   1420:
1.305     rillig   1421:        wp += m[0].rm_eo;
1.304     rillig   1422:        if (args->pflags & VARP_SUB_GLOBAL) {
1.20      christos 1423:            flags |= REG_NOTBOL;
1.305     rillig   1424:            if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1.278     rillig   1425:                SepBuf_AddBytes(buf, wp, 1);
1.20      christos 1426:                wp++;
                   1427:            }
                   1428:            if (*wp)
                   1429:                goto tryagain;
                   1430:        }
1.16      christos 1431:        if (*wp) {
1.314     rillig   1432:            SepBuf_AddStr(buf, wp);
1.16      christos 1433:        }
                   1434:        break;
                   1435:     default:
1.304     rillig   1436:        VarREError(xrv, &args->re, "Unexpected regex error");
1.568     rillig   1437:        /* FALLTHROUGH */
1.16      christos 1438:     case REG_NOMATCH:
1.307     rillig   1439:     nosub:
1.314     rillig   1440:        SepBuf_AddStr(buf, wp);
1.16      christos 1441:        break;
                   1442:     }
                   1443: }
1.17      christos 1444: #endif
1.16      christos 1445:
                   1446:
1.541     rillig   1447: struct ModifyWord_LoopArgs {
1.295     rillig   1448:     GNode      *ctx;
1.291     rillig   1449:     char       *tvar;          /* name of temporary variable */
                   1450:     char       *str;           /* string to expand */
                   1451:     VarEvalFlags eflags;
1.541     rillig   1452: };
1.291     rillig   1453:
                   1454: /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1.278     rillig   1455: static void
1.295     rillig   1456: ModifyWord_Loop(const char *word, SepBuf *buf, void *data)
1.40      sjg      1457: {
1.541     rillig   1458:     const struct ModifyWord_LoopArgs *args;
1.412     rillig   1459:     char *s;
                   1460:
1.278     rillig   1461:     if (word[0] == '\0')
                   1462:        return;
                   1463:
1.412     rillig   1464:     args = data;
1.295     rillig   1465:     Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT);
1.533     rillig   1466:     (void)Var_Subst(args->str, args->ctx, args->eflags, &s);
                   1467:     /* TODO: handle errors */
1.411     rillig   1468:
1.618     rillig   1469:     VAR_DEBUG4("ModifyWord_Loop: "
                   1470:               "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n",
1.547     rillig   1471:               word, args->tvar, args->str, s);
1.64      sjg      1472:
1.544     rillig   1473:     if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1.477     rillig   1474:        buf->needSep = FALSE;
                   1475:     SepBuf_AddStr(buf, s);
1.278     rillig   1476:     free(s);
1.40      sjg      1477: }
                   1478:
1.81      sjg      1479:
1.619     rillig   1480: /* The :[first..last] modifier selects words from the expression.
                   1481:  * It can also reverse the words. */
1.81      sjg      1482: static char *
1.449     rillig   1483: VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first,
1.301     rillig   1484:               int last)
1.81      sjg      1485: {
1.479     rillig   1486:     Words words;
1.583     rillig   1487:     int len, start, end, step;
1.412     rillig   1488:     int i;
                   1489:
1.278     rillig   1490:     SepBuf buf;
1.401     rillig   1491:     SepBuf_Init(&buf, sep);
                   1492:
1.301     rillig   1493:     if (oneBigWord) {
1.479     rillig   1494:        /* fake what Str_Words() would do if there were only one word */
                   1495:        words.len = 1;
                   1496:        words.words = bmake_malloc((words.len + 1) * sizeof(char *));
                   1497:        words.freeIt = bmake_strdup(str);
                   1498:        words.words[0] = words.freeIt;
                   1499:        words.words[1] = NULL;
1.81      sjg      1500:     } else {
1.479     rillig   1501:        words = Str_Words(str, FALSE);
1.81      sjg      1502:     }
                   1503:
                   1504:     /*
1.400     rillig   1505:      * Now sanitize the given range.
                   1506:      * If first or last are negative, convert them to the positive equivalents
                   1507:      * (-1 gets converted to ac, -2 gets converted to (ac - 1), etc.).
1.81      sjg      1508:      */
1.583     rillig   1509:     len = (int)words.len;
1.290     rillig   1510:     if (first < 0)
1.583     rillig   1511:        first += len + 1;
1.290     rillig   1512:     if (last < 0)
1.583     rillig   1513:        last += len + 1;
1.81      sjg      1514:
                   1515:     /*
                   1516:      * We avoid scanning more of the list than we need to.
                   1517:      */
1.290     rillig   1518:     if (first > last) {
1.583     rillig   1519:        start = (first > len ? len : first) - 1;
                   1520:        end = last < 1 ? 0 : last - 1;
1.81      sjg      1521:        step = -1;
                   1522:     } else {
1.583     rillig   1523:        start = first < 1 ? 0 : first - 1;
                   1524:        end = last > len ? len : last;
1.81      sjg      1525:        step = 1;
                   1526:     }
                   1527:
1.296     rillig   1528:     for (i = start; (step < 0) == (i >= end); i += step) {
1.479     rillig   1529:        SepBuf_AddStr(&buf, words.words[i]);
1.308     rillig   1530:        SepBuf_Sep(&buf);
1.81      sjg      1531:     }
                   1532:
1.479     rillig   1533:     Words_Free(words);
1.81      sjg      1534:
1.278     rillig   1535:     return SepBuf_Destroy(&buf, FALSE);
1.81      sjg      1536: }
                   1537:
1.156     sjg      1538:
1.291     rillig   1539: /* Callback for ModifyWords to implement the :tA modifier.
1.244     rillig   1540:  * Replace each word with the result of realpath() if successful. */
1.278     rillig   1541: static void
1.295     rillig   1542: ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.156     sjg      1543: {
1.242     rillig   1544:     struct stat st;
                   1545:     char rbuf[MAXPATHLEN];
1.231     rillig   1546:
1.314     rillig   1547:     const char *rp = cached_realpath(word, rbuf);
1.257     rillig   1548:     if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1.242     rillig   1549:        word = rp;
1.231     rillig   1550:
1.314     rillig   1551:     SepBuf_AddStr(buf, word);
1.156     sjg      1552: }
                   1553:
1.619     rillig   1554: /* Modify each of the words of the passed string using the given function.
1.1       cgd      1555:  *
1.70      wiz      1556:  * Input:
1.278     rillig   1557:  *     str             String whose words should be modified
1.291     rillig   1558:  *     modifyWord      Function that modifies a single word
1.453     rillig   1559:  *     modifyWord_args Custom arguments for modifyWord
1.70      wiz      1560:  *
1.1       cgd      1561:  * Results:
                   1562:  *     A string of all the words modified appropriately.
                   1563:  *-----------------------------------------------------------------------
                   1564:  */
                   1565: static char *
1.619     rillig   1566: ModifyWords(const char *str,
                   1567:            ModifyWordsCallback modifyWord, void *modifyWord_args,
                   1568:            Boolean oneBigWord, char sep)
1.1       cgd      1569: {
1.412     rillig   1570:     SepBuf result;
1.479     rillig   1571:     Words words;
1.465     rillig   1572:     size_t i;
1.412     rillig   1573:
1.316     rillig   1574:     if (oneBigWord) {
                   1575:        SepBuf_Init(&result, sep);
1.453     rillig   1576:        modifyWord(str, &result, modifyWord_args);
1.316     rillig   1577:        return SepBuf_Destroy(&result, FALSE);
                   1578:     }
                   1579:
1.401     rillig   1580:     SepBuf_Init(&result, sep);
                   1581:
1.479     rillig   1582:     words = Str_Words(str, FALSE);
1.1       cgd      1583:
1.547     rillig   1584:     VAR_DEBUG2("ModifyWords: split \"%s\" into %zu words\n", str, words.len);
1.255     rillig   1585:
1.479     rillig   1586:     for (i = 0; i < words.len; i++) {
                   1587:        modifyWord(words.words[i], &result, modifyWord_args);
1.545     rillig   1588:        if (Buf_Len(&result.buf) > 0)
1.278     rillig   1589:            SepBuf_Sep(&result);
                   1590:     }
1.24      christos 1591:
1.479     rillig   1592:     Words_Free(words);
1.15      christos 1593:
1.278     rillig   1594:     return SepBuf_Destroy(&result, FALSE);
1.1       cgd      1595: }
                   1596:
1.35      christos 1597:
1.403     rillig   1598: static char *
1.479     rillig   1599: Words_JoinFree(Words words)
1.403     rillig   1600: {
                   1601:     Buffer buf;
1.465     rillig   1602:     size_t i;
1.412     rillig   1603:
1.433     rillig   1604:     Buf_Init(&buf, 0);
1.403     rillig   1605:
1.479     rillig   1606:     for (i = 0; i < words.len; i++) {
1.403     rillig   1607:        if (i != 0)
1.442     rillig   1608:            Buf_AddByte(&buf, ' ');     /* XXX: st->sep, for consistency */
1.479     rillig   1609:        Buf_AddStr(&buf, words.words[i]);
1.403     rillig   1610:     }
                   1611:
1.479     rillig   1612:     Words_Free(words);
1.403     rillig   1613:
                   1614:     return Buf_Destroy(&buf, FALSE);
                   1615: }
                   1616:
1.319     rillig   1617: /* Remove adjacent duplicate words. */
1.55      christos 1618: static char *
1.73      christos 1619: VarUniq(const char *str)
1.55      christos 1620: {
1.479     rillig   1621:     Words words = Str_Words(str, FALSE);
1.55      christos 1622:
1.480     rillig   1623:     if (words.len > 1) {
1.465     rillig   1624:        size_t i, j;
1.480     rillig   1625:        for (j = 0, i = 1; i < words.len; i++)
1.482     rillig   1626:            if (strcmp(words.words[i], words.words[j]) != 0 && (++j != i))
                   1627:                words.words[j] = words.words[i];
1.480     rillig   1628:        words.len = j + 1;
1.55      christos 1629:     }
                   1630:
1.479     rillig   1631:     return Words_JoinFree(words);
1.55      christos 1632: }
                   1633:
                   1634:
1.483     rillig   1635: /* Quote shell meta-characters and space characters in the string.
                   1636:  * If quoteDollar is set, also quote and double any '$' characters. */
1.16      christos 1637: static char *
1.483     rillig   1638: VarQuote(const char *str, Boolean quoteDollar)
1.16      christos 1639: {
1.293     rillig   1640:     Buffer buf;
1.433     rillig   1641:     Buf_Init(&buf, 0);
1.193     christos 1642:
                   1643:     for (; *str != '\0'; str++) {
                   1644:        if (*str == '\n') {
1.293     rillig   1645:            const char *newline = Shell_GetNewline();
                   1646:            if (newline == NULL)
                   1647:                newline = "\\\n";
1.313     rillig   1648:            Buf_AddStr(&buf, newline);
1.193     christos 1649:            continue;
                   1650:        }
1.629     rillig   1651:        if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str))
1.146     dsl      1652:            Buf_AddByte(&buf, '\\');
1.193     christos 1653:        Buf_AddByte(&buf, *str);
1.220     christos 1654:        if (quoteDollar && *str == '$')
1.313     rillig   1655:            Buf_AddStr(&buf, "\\$");
1.16      christos 1656:     }
1.193     christos 1657:
1.628     rillig   1658:     return Buf_Destroy(&buf, FALSE);
1.16      christos 1659: }
                   1660:
1.400     rillig   1661: /* Compute the 32-bit hash of the given string, using the MurmurHash3
                   1662:  * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */
1.163     joerg    1663: static char *
1.252     rillig   1664: VarHash(const char *str)
1.163     joerg    1665: {
                   1666:     static const char    hexdigits[16] = "0123456789abcdef";
1.252     rillig   1667:     const unsigned char *ustr = (const unsigned char *)str;
1.163     joerg    1668:
1.401     rillig   1669:     uint32_t h  = 0x971e137bU;
                   1670:     uint32_t c1 = 0x95543787U;
                   1671:     uint32_t c2 = 0x2ad7eb25U;
                   1672:     size_t len2 = strlen(str);
1.163     joerg    1673:
1.412     rillig   1674:     char *buf;
                   1675:     size_t i;
                   1676:
1.401     rillig   1677:     size_t len;
1.163     joerg    1678:     for (len = len2; len; ) {
1.401     rillig   1679:        uint32_t k = 0;
1.163     joerg    1680:        switch (len) {
                   1681:        default:
1.252     rillig   1682:            k = ((uint32_t)ustr[3] << 24) |
                   1683:                ((uint32_t)ustr[2] << 16) |
                   1684:                ((uint32_t)ustr[1] << 8) |
                   1685:                (uint32_t)ustr[0];
1.163     joerg    1686:            len -= 4;
                   1687:            ustr += 4;
                   1688:            break;
                   1689:        case 3:
1.252     rillig   1690:            k |= (uint32_t)ustr[2] << 16;
1.222     mrg      1691:            /* FALLTHROUGH */
1.163     joerg    1692:        case 2:
1.252     rillig   1693:            k |= (uint32_t)ustr[1] << 8;
1.222     mrg      1694:            /* FALLTHROUGH */
1.163     joerg    1695:        case 1:
1.252     rillig   1696:            k |= (uint32_t)ustr[0];
1.163     joerg    1697:            len = 0;
                   1698:        }
                   1699:        c1 = c1 * 5 + 0x7b7d159cU;
                   1700:        c2 = c2 * 5 + 0x6bce6396U;
                   1701:        k *= c1;
                   1702:        k = (k << 11) ^ (k >> 21);
                   1703:        k *= c2;
                   1704:        h = (h << 13) ^ (h >> 19);
                   1705:        h = h * 5 + 0x52dce729U;
                   1706:        h ^= k;
1.242     rillig   1707:     }
1.448     rillig   1708:     h ^= (uint32_t)len2;
1.242     rillig   1709:     h *= 0x85ebca6b;
                   1710:     h ^= h >> 13;
                   1711:     h *= 0xc2b2ae35;
                   1712:     h ^= h >> 16;
                   1713:
1.412     rillig   1714:     buf = bmake_malloc(9);
1.405     rillig   1715:     for (i = 0; i < 8; i++) {
                   1716:        buf[i] = hexdigits[h & 0x0f];
1.242     rillig   1717:        h >>= 4;
1.249     rillig   1718:     }
1.405     rillig   1719:     buf[8] = '\0';
                   1720:     return buf;
1.163     joerg    1721: }
                   1722:
1.164     sjg      1723: static char *
1.425     rillig   1724: VarStrftime(const char *fmt, Boolean zulu, time_t tim)
1.164     sjg      1725: {
                   1726:     char buf[BUFSIZ];
                   1727:
1.425     rillig   1728:     if (!tim)
                   1729:        time(&tim);
1.164     sjg      1730:     if (!*fmt)
                   1731:        fmt = "%c";
1.425     rillig   1732:     strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&tim) : localtime(&tim));
1.235     rillig   1733:
1.164     sjg      1734:     buf[sizeof(buf) - 1] = '\0';
                   1735:     return bmake_strdup(buf);
                   1736: }
                   1737:
1.409     rillig   1738: /* The ApplyModifier functions all work in the same way.  They get the
                   1739:  * current parsing position (pp) and parse the modifier from there.  The
1.467     rillig   1740:  * modifier typically lasts until the next ':', or a closing '}' or ')'
1.409     rillig   1741:  * (taken from st->endc), or the end of the string (parse error).
                   1742:  *
1.467     rillig   1743:  * The high-level behavior of these functions is:
                   1744:  *
                   1745:  * 1. parse the modifier
                   1746:  * 2. evaluate the modifier
                   1747:  * 3. housekeeping
                   1748:  *
                   1749:  * Parsing the modifier
                   1750:  *
                   1751:  * If parsing succeeds, the parsing position *pp is updated to point to the
                   1752:  * first character following the modifier, which typically is either ':' or
                   1753:  * st->endc.
                   1754:  *
                   1755:  * If parsing fails because of a missing delimiter (as in the :S, :C or :@
1.530     rillig   1756:  * modifiers), return AMR_CLEANUP.
1.467     rillig   1757:  *
                   1758:  * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
                   1759:  * try the SysV modifier ${VAR:from=to} as fallback.  This should only be
                   1760:  * done as long as there have been no side effects from evaluating nested
                   1761:  * variables, to avoid evaluating them more than once.  In this case, the
                   1762:  * parsing position must not be updated.  (XXX: Why not? The original parsing
                   1763:  * position is well-known in ApplyModifiers.)
                   1764:  *
                   1765:  * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
                   1766:  * as a fallback, either issue an error message using Error or Parse_Error
                   1767:  * and then return AMR_CLEANUP, or return AMR_BAD for the default error
                   1768:  * message.  Both of these return values will stop processing the variable
                   1769:  * expression.  (XXX: As of 2020-08-23, evaluation of the whole string
                   1770:  * continues nevertheless after skipping a few bytes, which essentially is
                   1771:  * undefined behavior.  Not in the sense of C, but still it's impossible to
                   1772:  * predict what happens in the parser.)
                   1773:  *
                   1774:  * Evaluating the modifier
                   1775:  *
                   1776:  * After parsing, the modifier is evaluated.  The side effects from evaluating
                   1777:  * nested variable expressions in the modifier text often already happen
                   1778:  * during parsing though.
                   1779:  *
                   1780:  * Evaluating the modifier usually takes the current value of the variable
                   1781:  * expression from st->val, or the variable name from st->v->name and stores
                   1782:  * the result in st->newVal.
                   1783:  *
                   1784:  * If evaluating fails (as of 2020-08-23), an error message is printed using
                   1785:  * Error.  This function has no side-effects, it really just prints the error
                   1786:  * message.  Processing the expression continues as if everything were ok.
                   1787:  * XXX: This should be fixed by adding proper error handling to Var_Subst,
                   1788:  * Var_Parse, ApplyModifiers and ModifyWords.
                   1789:  *
                   1790:  * Housekeeping
                   1791:  *
1.528     rillig   1792:  * Some modifiers such as :D and :U turn undefined expressions into defined
                   1793:  * expressions (see VEF_UNDEF, VEF_DEF).
1.467     rillig   1794:  *
                   1795:  * Some modifiers need to free some memory.
1.350     rillig   1796:  */
1.409     rillig   1797:
1.527     rillig   1798: typedef enum VarExprFlags {
                   1799:     /* The variable expression is based on an undefined variable. */
                   1800:     VEF_UNDEF = 0x01,
                   1801:     /* The variable expression started as an undefined expression, but one
                   1802:      * of the modifiers (such as :D or :U) has turned the expression from
                   1803:      * undefined to defined. */
                   1804:     VEF_DEF = 0x02
                   1805: } VarExprFlags;
                   1806:
                   1807: ENUM_FLAGS_RTTI_2(VarExprFlags,
                   1808:                  VEF_UNDEF, VEF_DEF);
                   1809:
                   1810:
1.541     rillig   1811: typedef struct ApplyModifiersState {
1.437     rillig   1812:     const char startc;         /* '\0' or '{' or '(' */
                   1813:     const char endc;           /* '\0' or '}' or ')' */
1.368     rillig   1814:     Var * const v;
                   1815:     GNode * const ctxt;
                   1816:     const VarEvalFlags eflags;
1.236     rillig   1817:
1.454     rillig   1818:     char *val;                 /* The old value of the expression,
1.460     rillig   1819:                                 * before applying the modifier, never NULL */
1.454     rillig   1820:     char *newVal;              /* The new value of the expression,
1.460     rillig   1821:                                 * after applying the modifier, never NULL */
1.449     rillig   1822:     char sep;                  /* Word separator in expansions
1.444     rillig   1823:                                 * (see the :ts modifier) */
1.454     rillig   1824:     Boolean oneBigWord;                /* TRUE if some modifiers that otherwise split
                   1825:                                 * the variable value into words, like :S and
                   1826:                                 * :C, treat the variable value as a single big
                   1827:                                 * word, possibly containing spaces. */
1.527     rillig   1828:     VarExprFlags exprFlags;
1.236     rillig   1829: } ApplyModifiersState;
                   1830:
1.525     rillig   1831: static void
1.527     rillig   1832: ApplyModifiersState_Define(ApplyModifiersState *st)
1.525     rillig   1833: {
1.527     rillig   1834:     if (st->exprFlags & VEF_UNDEF)
1.571     rillig   1835:        st->exprFlags |= VEF_DEF;
1.525     rillig   1836: }
                   1837:
1.578     rillig   1838: typedef enum ApplyModifierResult {
1.356     rillig   1839:     AMR_OK,                    /* Continue parsing */
1.400     rillig   1840:     AMR_UNKNOWN,               /* Not a match, try other modifiers as well */
                   1841:     AMR_BAD,                   /* Error out with "Bad modifier" message */
1.530     rillig   1842:     AMR_CLEANUP                        /* Error out without error message */
1.356     rillig   1843: } ApplyModifierResult;
                   1844:
1.620     rillig   1845: /* Allow backslashes to escape the delimiter, $, and \, but don't touch other
                   1846:  * backslashes. */
                   1847: static Boolean
                   1848: IsEscapedModifierPart(const char *p, char delim,
                   1849:                      struct ModifyWord_SubstArgs *subst)
                   1850: {
                   1851:     if (p[0] != '\\')
                   1852:        return FALSE;
                   1853:     if (p[1] == delim || p[1] == '\\' || p[1] == '$')
                   1854:        return TRUE;
                   1855:     return p[1] == '&' && subst != NULL;
                   1856: }
                   1857:
                   1858: /*
                   1859:  * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
                   1860:  * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
1.529     rillig   1861:  * including the next unescaped delimiter.  The delimiter, as well as the
                   1862:  * backslash or the dollar, can be escaped with a backslash.
                   1863:  *
                   1864:  * Return the parsed (and possibly expanded) string, or NULL if no delimiter
                   1865:  * was found.  On successful return, the parsing position pp points right
                   1866:  * after the delimiter.  The delimiter is not included in the returned
                   1867:  * value though.
                   1868:  */
1.531     rillig   1869: static VarParseResult
1.529     rillig   1870: ParseModifierPart(
                   1871:     const char **pp,           /* The parsing position, updated upon return */
1.621     rillig   1872:     char delim,                        /* Parsing stops at this delimiter */
1.529     rillig   1873:     VarEvalFlags eflags,       /* Flags for evaluating nested variables;
                   1874:                                 * if VARE_WANTRES is not set, the text is
                   1875:                                 * only parsed */
                   1876:     ApplyModifiersState *st,
1.531     rillig   1877:     char **out_part,
1.529     rillig   1878:     size_t *out_length,                /* Optionally stores the length of the returned
                   1879:                                 * string, just to save another strlen call. */
                   1880:     VarPatternFlags *out_pflags,/* For the first part of the :S modifier,
                   1881:                                 * sets the VARP_ANCHOR_END flag if the last
                   1882:                                 * character of the pattern is a $. */
1.541     rillig   1883:     struct ModifyWord_SubstArgs *subst
                   1884:                                /* For the second part of the :S modifier,
1.529     rillig   1885:                                 * allow ampersands to be escaped and replace
                   1886:                                 * unescaped ampersands with subst->lhs. */
                   1887: ) {
                   1888:     Buffer buf;
                   1889:     const char *p;
                   1890:
                   1891:     Buf_Init(&buf, 0);
                   1892:
                   1893:     /*
1.620     rillig   1894:      * Skim through until the matching delimiter is found; pick up variable
                   1895:      * expressions on the way.
1.529     rillig   1896:      */
                   1897:     p = *pp;
                   1898:     while (*p != '\0' && *p != delim) {
                   1899:        const char *varstart;
                   1900:
1.620     rillig   1901:        if (IsEscapedModifierPart(p, delim, subst)) {
1.529     rillig   1902:            Buf_AddByte(&buf, p[1]);
                   1903:            p += 2;
                   1904:            continue;
                   1905:        }
                   1906:
                   1907:        if (*p != '$') {        /* Unescaped, simple text */
                   1908:            if (subst != NULL && *p == '&')
                   1909:                Buf_AddBytes(&buf, subst->lhs, subst->lhsLen);
                   1910:            else
                   1911:                Buf_AddByte(&buf, *p);
                   1912:            p++;
                   1913:            continue;
                   1914:        }
                   1915:
                   1916:        if (p[1] == delim) {    /* Unescaped $ at end of pattern */
                   1917:            if (out_pflags != NULL)
                   1918:                *out_pflags |= VARP_ANCHOR_END;
                   1919:            else
                   1920:                Buf_AddByte(&buf, *p);
                   1921:            p++;
                   1922:            continue;
                   1923:        }
                   1924:
                   1925:        if (eflags & VARE_WANTRES) {    /* Nested variable, evaluated */
                   1926:            const char *nested_p = p;
                   1927:            const char *nested_val;
                   1928:            void *nested_val_freeIt;
                   1929:            VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN;
                   1930:
                   1931:            (void)Var_Parse(&nested_p, st->ctxt, nested_eflags,
                   1932:                            &nested_val, &nested_val_freeIt);
                   1933:            /* TODO: handle errors */
                   1934:            Buf_AddStr(&buf, nested_val);
                   1935:            free(nested_val_freeIt);
                   1936:            p += nested_p - p;
                   1937:            continue;
                   1938:        }
                   1939:
                   1940:        /* XXX: This whole block is very similar to Var_Parse without
                   1941:         * VARE_WANTRES.  There may be subtle edge cases though that are
                   1942:         * not yet covered in the unit tests and that are parsed differently,
                   1943:         * depending on whether they are evaluated or not.
                   1944:         *
                   1945:         * This subtle difference is not documented in the manual page,
                   1946:         * neither is the difference between parsing :D and :M documented.
                   1947:         * No code should ever depend on these details, but who knows. */
                   1948:
                   1949:        varstart = p;           /* Nested variable, only parsed */
                   1950:        if (p[1] == '(' || p[1] == '{') {
                   1951:            /*
                   1952:             * Find the end of this variable reference
                   1953:             * and suck it in without further ado.
                   1954:             * It will be interpreted later.
                   1955:             */
1.627     rillig   1956:            char startc = p[1];
                   1957:            int endc = startc == '(' ? ')' : '}';
1.529     rillig   1958:            int depth = 1;
                   1959:
                   1960:            for (p += 2; *p != '\0' && depth > 0; p++) {
                   1961:                if (p[-1] != '\\') {
1.627     rillig   1962:                    if (*p == startc)
1.529     rillig   1963:                        depth++;
1.627     rillig   1964:                    if (*p == endc)
1.529     rillig   1965:                        depth--;
                   1966:                }
                   1967:            }
                   1968:            Buf_AddBytesBetween(&buf, varstart, p);
                   1969:        } else {
                   1970:            Buf_AddByte(&buf, *varstart);
                   1971:            p++;
                   1972:        }
                   1973:     }
                   1974:
                   1975:     if (*p != delim) {
                   1976:        *pp = p;
1.530     rillig   1977:        Error("Unfinished modifier for %s ('%c' missing)", st->v->name, delim);
1.531     rillig   1978:        *out_part = NULL;
                   1979:        return VPR_PARSE_MSG;
1.529     rillig   1980:     }
                   1981:
                   1982:     *pp = ++p;
                   1983:     if (out_length != NULL)
1.545     rillig   1984:        *out_length = Buf_Len(&buf);
1.529     rillig   1985:
1.531     rillig   1986:     *out_part = Buf_Destroy(&buf, FALSE);
1.547     rillig   1987:     VAR_DEBUG1("Modifier part: \"%s\"\n", *out_part);
1.531     rillig   1988:     return VPR_OK;
1.529     rillig   1989: }
                   1990:
1.400     rillig   1991: /* Test whether mod starts with modname, followed by a delimiter. */
1.340     rillig   1992: static Boolean
                   1993: ModMatch(const char *mod, const char *modname, char endc)
                   1994: {
                   1995:     size_t n = strlen(modname);
                   1996:     return strncmp(mod, modname, n) == 0 &&
                   1997:           (mod[n] == endc || mod[n] == ':');
                   1998: }
                   1999:
1.400     rillig   2000: /* Test whether mod starts with modname, followed by a delimiter or '='. */
1.340     rillig   2001: static inline Boolean
                   2002: ModMatchEq(const char *mod, const char *modname, char endc)
                   2003: {
                   2004:     size_t n = strlen(modname);
                   2005:     return strncmp(mod, modname, n) == 0 &&
                   2006:           (mod[n] == endc || mod[n] == ':' || mod[n] == '=');
                   2007: }
1.236     rillig   2008:
1.635     rillig   2009: static Boolean
                   2010: TryParseIntBase0(const char **pp, int *out_num)
                   2011: {
                   2012:     char *end;
                   2013:     long n;
                   2014:
                   2015:     errno = 0;
                   2016:     n = strtol(*pp, &end, 0);
                   2017:     if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
                   2018:        return FALSE;
                   2019:     if (n < INT_MIN || n > INT_MAX)
                   2020:        return FALSE;
                   2021:
                   2022:     *pp = end;
                   2023:     *out_num = (int)n;
                   2024:     return TRUE;
                   2025: }
                   2026:
                   2027: static Boolean
                   2028: TryParseSize(const char **pp, size_t *out_num)
                   2029: {
                   2030:     char *end;
                   2031:     unsigned long n;
                   2032:
                   2033:     if (!ch_isdigit(**pp))
                   2034:        return FALSE;
                   2035:
                   2036:     errno = 0;
                   2037:     n = strtoul(*pp, &end, 10);
                   2038:     if (n == ULONG_MAX && errno == ERANGE)
                   2039:        return FALSE;
                   2040:     if (n > SIZE_MAX)
                   2041:        return FALSE;
                   2042:
                   2043:     *pp = end;
                   2044:     *out_num = (size_t)n;
                   2045:     return TRUE;
                   2046: }
                   2047:
                   2048: static Boolean
                   2049: TryParseChar(const char **pp, int base, char *out_ch)
                   2050: {
                   2051:     char *end;
                   2052:     unsigned long n;
                   2053:
                   2054:     if (!ch_isalnum(**pp))
                   2055:        return FALSE;
                   2056:
                   2057:     errno = 0;
                   2058:     n = strtoul(*pp, &end, base);
                   2059:     if (n == ULONG_MAX && errno == ERANGE)
                   2060:        return FALSE;
                   2061:     if (n > UCHAR_MAX)
                   2062:        return FALSE;
                   2063:
                   2064:     *pp = end;
                   2065:     *out_ch = (char)n;
                   2066:     return TRUE;
                   2067: }
                   2068:
1.236     rillig   2069: /* :@var@...${var}...@ */
1.356     rillig   2070: static ApplyModifierResult
1.417     rillig   2071: ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
                   2072: {
1.541     rillig   2073:     struct ModifyWord_LoopArgs args;
1.448     rillig   2074:     char prev_sep;
                   2075:     VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.531     rillig   2076:     VarParseResult res;
1.236     rillig   2077:
1.295     rillig   2078:     args.ctx = st->ctxt;
1.409     rillig   2079:
                   2080:     (*pp)++;                   /* Skip the first '@' */
1.535     rillig   2081:     res = ParseModifierPart(pp, '@', eflags, st,
1.531     rillig   2082:                            &args.tvar, NULL, NULL, NULL);
                   2083:     if (res != VPR_OK)
1.356     rillig   2084:        return AMR_CLEANUP;
1.410     rillig   2085:     if (DEBUG(LINT) && strchr(args.tvar, '$') != NULL) {
                   2086:        Parse_Error(PARSE_FATAL,
                   2087:                    "In the :@ modifier of \"%s\", the variable name \"%s\" "
                   2088:                    "must not contain a dollar.",
                   2089:                    st->v->name, args.tvar);
1.417     rillig   2090:        return AMR_CLEANUP;
1.410     rillig   2091:     }
1.236     rillig   2092:
1.535     rillig   2093:     res = ParseModifierPart(pp, '@', eflags, st,
1.531     rillig   2094:                            &args.str, NULL, NULL, NULL);
                   2095:     if (res != VPR_OK)
1.356     rillig   2096:        return AMR_CLEANUP;
1.236     rillig   2097:
1.291     rillig   2098:     args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
1.412     rillig   2099:     prev_sep = st->sep;
1.409     rillig   2100:     st->sep = ' ';             /* XXX: should be st->sep for consistency */
1.619     rillig   2101:     st->newVal = ModifyWords(st->val, ModifyWord_Loop, &args,
                   2102:                             st->oneBigWord, st->sep);
1.301     rillig   2103:     st->sep = prev_sep;
1.291     rillig   2104:     Var_Delete(args.tvar, st->ctxt);
                   2105:     free(args.tvar);
                   2106:     free(args.str);
1.356     rillig   2107:     return AMR_OK;
1.236     rillig   2108: }
                   2109:
                   2110: /* :Ddefined or :Uundefined */
1.356     rillig   2111: static ApplyModifierResult
1.409     rillig   2112: ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
1.236     rillig   2113: {
1.467     rillig   2114:     Buffer buf;
1.412     rillig   2115:     const char *p;
                   2116:
1.448     rillig   2117:     VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.268     rillig   2118:     if (st->eflags & VARE_WANTRES) {
1.527     rillig   2119:        if ((**pp == 'D') == !(st->exprFlags & VEF_UNDEF))
1.415     rillig   2120:            eflags |= VARE_WANTRES;
                   2121:     }
1.236     rillig   2122:
1.433     rillig   2123:     Buf_Init(&buf, 0);
1.412     rillig   2124:     p = *pp + 1;
1.339     rillig   2125:     while (*p != st->endc && *p != ':' && *p != '\0') {
1.466     rillig   2126:
1.494     rillig   2127:        /* Escaped delimiter or other special character */
1.466     rillig   2128:        if (*p == '\\') {
                   2129:            char c = p[1];
                   2130:            if (c == st->endc || c == ':' || c == '$' || c == '\\') {
                   2131:                Buf_AddByte(&buf, c);
                   2132:                p += 2;
                   2133:                continue;
                   2134:            }
                   2135:        }
                   2136:
1.467     rillig   2137:        /* Nested variable expression */
1.466     rillig   2138:        if (*p == '$') {
1.486     rillig   2139:            const char *nested_val;
                   2140:            void *nested_val_freeIt;
1.236     rillig   2141:
1.514     rillig   2142:            (void)Var_Parse(&p, st->ctxt, eflags,
                   2143:                            &nested_val, &nested_val_freeIt);
                   2144:            /* TODO: handle errors */
1.486     rillig   2145:            Buf_AddStr(&buf, nested_val);
                   2146:            free(nested_val_freeIt);
1.466     rillig   2147:            continue;
1.236     rillig   2148:        }
1.466     rillig   2149:
                   2150:        /* Ordinary text */
                   2151:        Buf_AddByte(&buf, *p);
                   2152:        p++;
1.236     rillig   2153:     }
1.409     rillig   2154:     *pp = p;
1.236     rillig   2155:
1.527     rillig   2156:     ApplyModifiersState_Define(st);
1.525     rillig   2157:
1.415     rillig   2158:     if (eflags & VARE_WANTRES) {
1.349     rillig   2159:        st->newVal = Buf_Destroy(&buf, FALSE);
1.236     rillig   2160:     } else {
1.349     rillig   2161:        st->newVal = st->val;
1.236     rillig   2162:        Buf_Destroy(&buf, TRUE);
                   2163:     }
1.356     rillig   2164:     return AMR_OK;
1.236     rillig   2165: }
                   2166:
1.567     rillig   2167: /* :L */
                   2168: static ApplyModifierResult
                   2169: ApplyModifier_Literal(const char **pp, ApplyModifiersState *st)
                   2170: {
                   2171:     ApplyModifiersState_Define(st);
                   2172:     st->newVal = bmake_strdup(st->v->name);
                   2173:     (*pp)++;
                   2174:     return AMR_OK;
                   2175: }
                   2176:
1.633     rillig   2177: static Boolean
                   2178: TryParseTime(const char **pp, time_t *out_time)
1.631     rillig   2179: {
                   2180:     char *end;
                   2181:     unsigned long n;
                   2182:
                   2183:     if (!ch_isdigit(**pp))
                   2184:        return FALSE;
                   2185:
                   2186:     errno = 0;
                   2187:     n = strtoul(*pp, &end, 10);
                   2188:     if (n == ULONG_MAX && errno == ERANGE)
                   2189:        return FALSE;
                   2190:
                   2191:     *pp = end;
                   2192:     *out_time = (time_t)n;     /* ignore possible truncation for now */
                   2193:     return TRUE;
                   2194: }
                   2195:
1.236     rillig   2196: /* :gmtime */
1.356     rillig   2197: static ApplyModifierResult
1.409     rillig   2198: ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st)
1.236     rillig   2199: {
1.412     rillig   2200:     time_t utc;
                   2201:
1.409     rillig   2202:     const char *mod = *pp;
1.358     rillig   2203:     if (!ModMatchEq(mod, "gmtime", st->endc))
1.356     rillig   2204:        return AMR_UNKNOWN;
1.340     rillig   2205:
1.299     rillig   2206:     if (mod[6] == '=') {
1.631     rillig   2207:        const char *arg = mod + 7;
                   2208:        if (!TryParseTime(&arg, &utc)) {
                   2209:            Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 7);
                   2210:            return AMR_CLEANUP;
                   2211:        }
                   2212:        *pp = arg;
1.236     rillig   2213:     } else {
                   2214:        utc = 0;
1.409     rillig   2215:        *pp = mod + 6;
1.236     rillig   2216:     }
1.425     rillig   2217:     st->newVal = VarStrftime(st->val, TRUE, utc);
1.356     rillig   2218:     return AMR_OK;
1.236     rillig   2219: }
                   2220:
                   2221: /* :localtime */
1.505     rillig   2222: static ApplyModifierResult
1.409     rillig   2223: ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st)
1.236     rillig   2224: {
1.412     rillig   2225:     time_t utc;
                   2226:
1.409     rillig   2227:     const char *mod = *pp;
1.358     rillig   2228:     if (!ModMatchEq(mod, "localtime", st->endc))
1.356     rillig   2229:        return AMR_UNKNOWN;
1.236     rillig   2230:
1.299     rillig   2231:     if (mod[9] == '=') {
1.631     rillig   2232:        const char *arg = mod + 10;
                   2233:        if (!TryParseTime(&arg, &utc)) {
                   2234:            Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 10);
                   2235:            return AMR_CLEANUP;
                   2236:        }
                   2237:        *pp = arg;
1.236     rillig   2238:     } else {
                   2239:        utc = 0;
1.409     rillig   2240:        *pp = mod + 9;
1.236     rillig   2241:     }
1.425     rillig   2242:     st->newVal = VarStrftime(st->val, FALSE, utc);
1.356     rillig   2243:     return AMR_OK;
1.236     rillig   2244: }
                   2245:
                   2246: /* :hash */
1.356     rillig   2247: static ApplyModifierResult
1.409     rillig   2248: ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
1.236     rillig   2249: {
1.409     rillig   2250:     if (!ModMatch(*pp, "hash", st->endc))
1.356     rillig   2251:        return AMR_UNKNOWN;
1.340     rillig   2252:
1.349     rillig   2253:     st->newVal = VarHash(st->val);
1.409     rillig   2254:     *pp += 4;
1.356     rillig   2255:     return AMR_OK;
1.236     rillig   2256: }
                   2257:
                   2258: /* :P */
1.356     rillig   2259: static ApplyModifierResult
1.409     rillig   2260: ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
1.236     rillig   2261: {
1.412     rillig   2262:     GNode *gn;
1.461     rillig   2263:     char *path;
1.412     rillig   2264:
1.527     rillig   2265:     ApplyModifiersState_Define(st);
1.409     rillig   2266:
1.543     rillig   2267:     gn = Targ_FindNode(st->v->name);
1.236     rillig   2268:     if (gn == NULL || gn->type & OP_NOPATH) {
1.461     rillig   2269:        path = NULL;
1.589     rillig   2270:     } else if (gn->path != NULL) {
1.461     rillig   2271:        path = bmake_strdup(gn->path);
1.236     rillig   2272:     } else {
1.524     rillig   2273:        SearchPath *searchPath = Suff_FindPath(gn);
1.461     rillig   2274:        path = Dir_FindFile(st->v->name, searchPath);
1.236     rillig   2275:     }
1.461     rillig   2276:     if (path == NULL)
                   2277:        path = bmake_strdup(st->v->name);
                   2278:     st->newVal = path;
1.409     rillig   2279:
                   2280:     (*pp)++;
1.356     rillig   2281:     return AMR_OK;
1.236     rillig   2282: }
                   2283:
                   2284: /* :!cmd! */
1.356     rillig   2285: static ApplyModifierResult
1.509     rillig   2286: ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st)
1.236     rillig   2287: {
1.412     rillig   2288:     char *cmd;
1.416     rillig   2289:     const char *errfmt;
1.531     rillig   2290:     VarParseResult res;
1.412     rillig   2291:
1.409     rillig   2292:     (*pp)++;
1.535     rillig   2293:     res = ParseModifierPart(pp, '!', st->eflags, st,
1.531     rillig   2294:                            &cmd, NULL, NULL, NULL);
                   2295:     if (res != VPR_OK)
1.356     rillig   2296:        return AMR_CLEANUP;
1.274     rillig   2297:
1.416     rillig   2298:     errfmt = NULL;
1.268     rillig   2299:     if (st->eflags & VARE_WANTRES)
1.416     rillig   2300:        st->newVal = Cmd_Exec(cmd, &errfmt);
1.236     rillig   2301:     else
1.536     rillig   2302:        st->newVal = emptyString;
1.274     rillig   2303:     free(cmd);
                   2304:
1.416     rillig   2305:     if (errfmt != NULL)
                   2306:        Error(errfmt, st->val); /* XXX: why still return AMR_OK? */
1.274     rillig   2307:
1.527     rillig   2308:     ApplyModifiersState_Define(st);
1.356     rillig   2309:     return AMR_OK;
1.236     rillig   2310: }
                   2311:
1.386     rillig   2312: /* The :range modifier generates an integer sequence as long as the words.
                   2313:  * The :range=7 modifier generates an integer sequence from 1 to 7. */
1.356     rillig   2314: static ApplyModifierResult
1.409     rillig   2315: ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
1.236     rillig   2316: {
1.465     rillig   2317:     size_t n;
1.412     rillig   2318:     Buffer buf;
1.465     rillig   2319:     size_t i;
1.412     rillig   2320:
1.409     rillig   2321:     const char *mod = *pp;
1.358     rillig   2322:     if (!ModMatchEq(mod, "range", st->endc))
1.356     rillig   2323:        return AMR_UNKNOWN;
1.236     rillig   2324:
1.299     rillig   2325:     if (mod[5] == '=') {
1.635     rillig   2326:        const char *p = mod + 6;
                   2327:        if (!TryParseSize(&p, &n)) {
                   2328:            Parse_Error(PARSE_FATAL, "Invalid number: %s\n", mod + 6);
                   2329:            return AMR_CLEANUP;
                   2330:        }
                   2331:        *pp = p;
1.236     rillig   2332:     } else {
                   2333:        n = 0;
1.409     rillig   2334:        *pp = mod + 5;
1.236     rillig   2335:     }
1.386     rillig   2336:
                   2337:     if (n == 0) {
1.494     rillig   2338:        Words words = Str_Words(st->val, FALSE);
                   2339:        n = words.len;
                   2340:        Words_Free(words);
1.386     rillig   2341:     }
                   2342:
1.433     rillig   2343:     Buf_Init(&buf, 0);
1.386     rillig   2344:
                   2345:     for (i = 0; i < n; i++) {
                   2346:        if (i != 0)
1.442     rillig   2347:            Buf_AddByte(&buf, ' ');     /* XXX: st->sep, for consistency */
1.465     rillig   2348:        Buf_AddInt(&buf, 1 + (int)i);
1.386     rillig   2349:     }
                   2350:
                   2351:     st->newVal = Buf_Destroy(&buf, FALSE);
1.356     rillig   2352:     return AMR_OK;
1.236     rillig   2353: }
                   2354:
                   2355: /* :Mpattern or :Npattern */
1.356     rillig   2356: static ApplyModifierResult
1.409     rillig   2357: ApplyModifier_Match(const char **pp, ApplyModifiersState *st)
1.236     rillig   2358: {
1.409     rillig   2359:     const char *mod = *pp;
1.288     rillig   2360:     Boolean copy = FALSE;      /* pattern should be, or has been, copied */
                   2361:     Boolean needSubst = FALSE;
1.412     rillig   2362:     const char *endpat;
                   2363:     char *pattern;
                   2364:     ModifyWordsCallback callback;
                   2365:
1.236     rillig   2366:     /*
1.288     rillig   2367:      * In the loop below, ignore ':' unless we are at (or back to) the
                   2368:      * original brace level.
                   2369:      * XXX This will likely not work right if $() and ${} are intermixed.
1.236     rillig   2370:      */
1.387     rillig   2371:     int nest = 0;
1.347     rillig   2372:     const char *p;
1.387     rillig   2373:     for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) {
1.347     rillig   2374:        if (*p == '\\' &&
                   2375:            (p[1] == ':' || p[1] == st->endc || p[1] == st->startc)) {
1.637     rillig   2376:            if (!needSubst)
                   2377:                copy = TRUE;
1.347     rillig   2378:            p++;
1.236     rillig   2379:            continue;
                   2380:        }
1.347     rillig   2381:        if (*p == '$')
1.236     rillig   2382:            needSubst = TRUE;
1.347     rillig   2383:        if (*p == '(' || *p == '{')
1.426     rillig   2384:            nest++;
1.347     rillig   2385:        if (*p == ')' || *p == '}') {
1.426     rillig   2386:            nest--;
1.387     rillig   2387:            if (nest < 0)
1.236     rillig   2388:                break;
                   2389:        }
                   2390:     }
1.409     rillig   2391:     *pp = p;
1.412     rillig   2392:     endpat = p;
1.288     rillig   2393:
1.236     rillig   2394:     if (copy) {
1.417     rillig   2395:        char *dst;
                   2396:        const char *src;
1.412     rillig   2397:
1.345     rillig   2398:        /* Compress the \:'s out of the pattern. */
1.448     rillig   2399:        pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
1.412     rillig   2400:        dst = pattern;
                   2401:        src = mod + 1;
1.346     rillig   2402:        for (; src < endpat; src++, dst++) {
                   2403:            if (src[0] == '\\' && src + 1 < endpat &&
1.345     rillig   2404:                /* XXX: st->startc is missing here; see above */
1.346     rillig   2405:                (src[1] == ':' || src[1] == st->endc))
                   2406:                src++;
                   2407:            *dst = *src;
1.236     rillig   2408:        }
1.346     rillig   2409:        *dst = '\0';
                   2410:        endpat = dst;
1.236     rillig   2411:     } else {
1.474     rillig   2412:        pattern = bmake_strsedup(mod + 1, endpat);
1.236     rillig   2413:     }
1.346     rillig   2414:
1.236     rillig   2415:     if (needSubst) {
                   2416:        /* pattern contains embedded '$', so use Var_Subst to expand it. */
1.288     rillig   2417:        char *old_pattern = pattern;
1.533     rillig   2418:        (void)Var_Subst(pattern, st->ctxt, st->eflags, &pattern);
                   2419:        /* TODO: handle errors */
1.288     rillig   2420:        free(old_pattern);
1.236     rillig   2421:     }
1.346     rillig   2422:
1.547     rillig   2423:     VAR_DEBUG3("Pattern[%s] for [%s] is [%s]\n", st->v->name, st->val, pattern);
1.346     rillig   2424:
1.412     rillig   2425:     callback = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
1.619     rillig   2426:     st->newVal = ModifyWords(st->val, callback, pattern,
                   2427:                             st->oneBigWord, st->sep);
1.236     rillig   2428:     free(pattern);
1.356     rillig   2429:     return AMR_OK;
1.236     rillig   2430: }
                   2431:
                   2432: /* :S,from,to, */
1.356     rillig   2433: static ApplyModifierResult
1.409     rillig   2434: ApplyModifier_Subst(const char **pp, ApplyModifiersState *st)
1.236     rillig   2435: {
1.541     rillig   2436:     struct ModifyWord_SubstArgs args;
1.412     rillig   2437:     char *lhs, *rhs;
                   2438:     Boolean oneBigWord;
1.531     rillig   2439:     VarParseResult res;
1.412     rillig   2440:
1.409     rillig   2441:     char delim = (*pp)[1];
1.359     rillig   2442:     if (delim == '\0') {
                   2443:        Error("Missing delimiter for :S modifier");
1.409     rillig   2444:        (*pp)++;
1.359     rillig   2445:        return AMR_CLEANUP;
                   2446:     }
1.299     rillig   2447:
1.409     rillig   2448:     *pp += 2;
1.236     rillig   2449:
1.362     rillig   2450:     args.pflags = 0;
1.452     rillig   2451:     args.matched = FALSE;
1.362     rillig   2452:
1.236     rillig   2453:     /*
                   2454:      * If pattern begins with '^', it is anchored to the
                   2455:      * start of the word -- skip over it and flag pattern.
                   2456:      */
1.409     rillig   2457:     if (**pp == '^') {
1.288     rillig   2458:        args.pflags |= VARP_ANCHOR_START;
1.409     rillig   2459:        (*pp)++;
1.236     rillig   2460:     }
                   2461:
1.531     rillig   2462:     res = ParseModifierPart(pp, delim, st->eflags, st,
                   2463:                            &lhs, &args.lhsLen, &args.pflags, NULL);
                   2464:     if (res != VPR_OK)
1.356     rillig   2465:        return AMR_CLEANUP;
1.281     rillig   2466:     args.lhs = lhs;
1.236     rillig   2467:
1.531     rillig   2468:     res = ParseModifierPart(pp, delim, st->eflags, st,
                   2469:                            &rhs, &args.rhsLen, NULL, &args);
                   2470:     if (res != VPR_OK)
1.356     rillig   2471:        return AMR_CLEANUP;
1.281     rillig   2472:     args.rhs = rhs;
1.236     rillig   2473:
1.412     rillig   2474:     oneBigWord = st->oneBigWord;
1.409     rillig   2475:     for (;; (*pp)++) {
                   2476:        switch (**pp) {
1.236     rillig   2477:        case 'g':
1.281     rillig   2478:            args.pflags |= VARP_SUB_GLOBAL;
1.236     rillig   2479:            continue;
                   2480:        case '1':
1.281     rillig   2481:            args.pflags |= VARP_SUB_ONE;
1.236     rillig   2482:            continue;
                   2483:        case 'W':
1.301     rillig   2484:            oneBigWord = TRUE;
1.236     rillig   2485:            continue;
                   2486:        }
                   2487:        break;
                   2488:     }
                   2489:
1.619     rillig   2490:     st->newVal = ModifyWords(st->val, ModifyWord_Subst, &args,
                   2491:                             oneBigWord, st->sep);
1.236     rillig   2492:
1.281     rillig   2493:     free(lhs);
                   2494:     free(rhs);
1.356     rillig   2495:     return AMR_OK;
1.236     rillig   2496: }
                   2497:
                   2498: #ifndef NO_REGEX
1.291     rillig   2499:
1.236     rillig   2500: /* :C,from,to, */
1.356     rillig   2501: static ApplyModifierResult
1.409     rillig   2502: ApplyModifier_Regex(const char **pp, ApplyModifiersState *st)
1.236     rillig   2503: {
1.412     rillig   2504:     char *re;
1.541     rillig   2505:     struct ModifyWord_SubstRegexArgs args;
1.412     rillig   2506:     Boolean oneBigWord;
                   2507:     int error;
1.531     rillig   2508:     VarParseResult res;
1.412     rillig   2509:
1.409     rillig   2510:     char delim = (*pp)[1];
1.360     rillig   2511:     if (delim == '\0') {
                   2512:        Error("Missing delimiter for :C modifier");
1.409     rillig   2513:        (*pp)++;
1.360     rillig   2514:        return AMR_CLEANUP;
                   2515:     }
1.236     rillig   2516:
1.409     rillig   2517:     *pp += 2;
1.236     rillig   2518:
1.531     rillig   2519:     res = ParseModifierPart(pp, delim, st->eflags, st,
1.599     rillig   2520:                            &re, NULL, NULL, NULL);
1.531     rillig   2521:     if (res != VPR_OK)
1.356     rillig   2522:        return AMR_CLEANUP;
1.236     rillig   2523:
1.531     rillig   2524:     res = ParseModifierPart(pp, delim, st->eflags, st,
                   2525:                            &args.replace, NULL, NULL, NULL);
1.291     rillig   2526:     if (args.replace == NULL) {
1.236     rillig   2527:        free(re);
1.356     rillig   2528:        return AMR_CLEANUP;
1.236     rillig   2529:     }
                   2530:
1.361     rillig   2531:     args.pflags = 0;
1.452     rillig   2532:     args.matched = FALSE;
1.412     rillig   2533:     oneBigWord = st->oneBigWord;
1.409     rillig   2534:     for (;; (*pp)++) {
                   2535:        switch (**pp) {
1.236     rillig   2536:        case 'g':
1.291     rillig   2537:            args.pflags |= VARP_SUB_GLOBAL;
1.236     rillig   2538:            continue;
                   2539:        case '1':
1.291     rillig   2540:            args.pflags |= VARP_SUB_ONE;
1.236     rillig   2541:            continue;
                   2542:        case 'W':
1.301     rillig   2543:            oneBigWord = TRUE;
1.236     rillig   2544:            continue;
                   2545:        }
                   2546:        break;
                   2547:     }
                   2548:
1.412     rillig   2549:     error = regcomp(&args.re, re, REG_EXTENDED);
1.236     rillig   2550:     free(re);
1.242     rillig   2551:     if (error) {
1.385     rillig   2552:        VarREError(error, &args.re, "Regex compilation error");
1.291     rillig   2553:        free(args.replace);
1.356     rillig   2554:        return AMR_CLEANUP;
1.236     rillig   2555:     }
                   2556:
1.291     rillig   2557:     args.nsub = args.re.re_nsub + 1;
                   2558:     if (args.nsub > 10)
                   2559:        args.nsub = 10;
1.619     rillig   2560:     st->newVal = ModifyWords(st->val, ModifyWord_SubstRegex, &args,
                   2561:                             oneBigWord, st->sep);
1.291     rillig   2562:     regfree(&args.re);
                   2563:     free(args.replace);
1.356     rillig   2564:     return AMR_OK;
1.236     rillig   2565: }
                   2566: #endif
                   2567:
1.555     rillig   2568: /* :Q, :q */
                   2569: static ApplyModifierResult
                   2570: ApplyModifier_Quote(const char **pp, ApplyModifiersState *st)
                   2571: {
                   2572:     if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
                   2573:        st->newVal = VarQuote(st->val, **pp == 'q');
                   2574:        (*pp)++;
                   2575:        return AMR_OK;
                   2576:     } else
                   2577:        return AMR_UNKNOWN;
                   2578: }
                   2579:
1.278     rillig   2580: static void
1.295     rillig   2581: ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.278     rillig   2582: {
1.314     rillig   2583:     SepBuf_AddStr(buf, word);
1.275     rillig   2584: }
                   2585:
1.289     rillig   2586: /* :ts<separator> */
1.356     rillig   2587: static ApplyModifierResult
1.409     rillig   2588: ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
1.289     rillig   2589: {
1.556     rillig   2590:     const char *sep = *pp + 2;
1.468     rillig   2591:
                   2592:     /* ":ts<any><endc>" or ":ts<any>:" */
1.289     rillig   2593:     if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
1.301     rillig   2594:        st->sep = sep[0];
1.409     rillig   2595:        *pp = sep + 1;
1.468     rillig   2596:        goto ok;
                   2597:     }
                   2598:
                   2599:     /* ":ts<endc>" or ":ts:" */
                   2600:     if (sep[0] == st->endc || sep[0] == ':') {
1.301     rillig   2601:        st->sep = '\0';         /* no separator */
1.409     rillig   2602:        *pp = sep;
1.468     rillig   2603:        goto ok;
                   2604:     }
                   2605:
                   2606:     /* ":ts<unrecognised><unrecognised>". */
1.556     rillig   2607:     if (sep[0] != '\\') {
                   2608:        (*pp)++;                /* just for backwards compatibility */
1.468     rillig   2609:        return AMR_BAD;
1.556     rillig   2610:     }
1.468     rillig   2611:
                   2612:     /* ":ts\n" */
                   2613:     if (sep[1] == 'n') {
                   2614:        st->sep = '\n';
                   2615:        *pp = sep + 2;
                   2616:        goto ok;
                   2617:     }
                   2618:
                   2619:     /* ":ts\t" */
                   2620:     if (sep[1] == 't') {
                   2621:        st->sep = '\t';
                   2622:        *pp = sep + 2;
                   2623:        goto ok;
                   2624:     }
                   2625:
                   2626:     /* ":ts\x40" or ":ts\100" */
                   2627:     {
1.635     rillig   2628:        const char *p = sep + 1;
1.289     rillig   2629:        int base = 8;           /* assume octal */
                   2630:
1.468     rillig   2631:        if (sep[1] == 'x') {
1.289     rillig   2632:            base = 16;
1.635     rillig   2633:            p++;
1.556     rillig   2634:        } else if (!ch_isdigit(sep[1])) {
                   2635:            (*pp)++;            /* just for backwards compatibility */
1.468     rillig   2636:            return AMR_BAD;     /* ":ts<backslash><unrecognised>". */
1.556     rillig   2637:        }
1.468     rillig   2638:
1.635     rillig   2639:        if (!TryParseChar(&p, base, &st->sep)) {
                   2640:            Parse_Error(PARSE_FATAL, "Invalid character number: %s\n", p);
                   2641:            return AMR_CLEANUP;
                   2642:        }
                   2643:        if (*p != ':' && *p != st->endc) {
1.556     rillig   2644:            (*pp)++;            /* just for backwards compatibility */
1.468     rillig   2645:            return AMR_BAD;
1.556     rillig   2646:        }
1.635     rillig   2647:
                   2648:        *pp = p;
1.289     rillig   2649:     }
                   2650:
1.468     rillig   2651: ok:
1.619     rillig   2652:     st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL,
                   2653:                             st->oneBigWord, st->sep);
1.356     rillig   2654:     return AMR_OK;
1.289     rillig   2655: }
                   2656:
                   2657: /* :tA, :tu, :tl, :ts<separator>, etc. */
1.356     rillig   2658: static ApplyModifierResult
1.409     rillig   2659: ApplyModifier_To(const char **pp, ApplyModifiersState *st)
1.236     rillig   2660: {
1.409     rillig   2661:     const char *mod = *pp;
1.363     rillig   2662:     assert(mod[0] == 't');
                   2663:
1.556     rillig   2664:     if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') {
                   2665:        *pp = mod + 1;
1.356     rillig   2666:        return AMR_BAD;         /* Found ":t<endc>" or ":t:". */
1.556     rillig   2667:     }
1.289     rillig   2668:
1.299     rillig   2669:     if (mod[1] == 's')
1.409     rillig   2670:        return ApplyModifier_ToSep(pp, st);
1.289     rillig   2671:
1.556     rillig   2672:     if (mod[2] != st->endc && mod[2] != ':') {
                   2673:        *pp = mod + 1;
1.356     rillig   2674:        return AMR_BAD;         /* Found ":t<unrecognised><unrecognised>". */
1.556     rillig   2675:     }
1.236     rillig   2676:
1.289     rillig   2677:     /* Check for two-character options: ":tu", ":tl" */
1.299     rillig   2678:     if (mod[1] == 'A') {       /* absolute path */
1.619     rillig   2679:        st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL,
                   2680:                                 st->oneBigWord, st->sep);
1.409     rillig   2681:        *pp = mod + 2;
1.475     rillig   2682:        return AMR_OK;
                   2683:     }
                   2684:
1.556     rillig   2685:     if (mod[1] == 'u') {       /* :tu */
1.412     rillig   2686:        size_t i;
1.364     rillig   2687:        size_t len = strlen(st->val);
                   2688:        st->newVal = bmake_malloc(len + 1);
                   2689:        for (i = 0; i < len + 1; i++)
1.493     rillig   2690:            st->newVal[i] = ch_toupper(st->val[i]);
1.409     rillig   2691:        *pp = mod + 2;
1.475     rillig   2692:        return AMR_OK;
                   2693:     }
                   2694:
1.556     rillig   2695:     if (mod[1] == 'l') {       /* :tl */
1.412     rillig   2696:        size_t i;
1.364     rillig   2697:        size_t len = strlen(st->val);
                   2698:        st->newVal = bmake_malloc(len + 1);
                   2699:        for (i = 0; i < len + 1; i++)
1.493     rillig   2700:            st->newVal[i] = ch_tolower(st->val[i]);
1.409     rillig   2701:        *pp = mod + 2;
1.475     rillig   2702:        return AMR_OK;
                   2703:     }
                   2704:
1.556     rillig   2705:     if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
1.301     rillig   2706:        st->oneBigWord = mod[1] == 'W';
1.349     rillig   2707:        st->newVal = st->val;
1.409     rillig   2708:        *pp = mod + 2;
1.475     rillig   2709:        return AMR_OK;
1.236     rillig   2710:     }
1.475     rillig   2711:
                   2712:     /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
1.556     rillig   2713:     *pp = mod + 1;
1.475     rillig   2714:     return AMR_BAD;
1.236     rillig   2715: }
                   2716:
1.634     rillig   2717: /* :[#], :[1], :[-1..1], etc. */
1.356     rillig   2718: static ApplyModifierResult
1.409     rillig   2719: ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
1.236     rillig   2720: {
1.412     rillig   2721:     char *estr;
                   2722:     int first, last;
1.531     rillig   2723:     VarParseResult res;
1.635     rillig   2724:     const char *p;
1.412     rillig   2725:
1.409     rillig   2726:     (*pp)++;                   /* skip the '[' */
1.535     rillig   2727:     res = ParseModifierPart(pp, ']', st->eflags, st,
1.531     rillig   2728:                            &estr, NULL, NULL, NULL);
                   2729:     if (res != VPR_OK)
1.356     rillig   2730:        return AMR_CLEANUP;
1.288     rillig   2731:
1.409     rillig   2732:     /* now *pp points just after the closing ']' */
                   2733:     if (**pp != ':' && **pp != st->endc)
1.288     rillig   2734:        goto bad_modifier;      /* Found junk after ']' */
                   2735:
                   2736:     if (estr[0] == '\0')
                   2737:        goto bad_modifier;      /* empty square brackets in ":[]". */
1.236     rillig   2738:
1.288     rillig   2739:     if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
1.301     rillig   2740:        if (st->oneBigWord) {
1.349     rillig   2741:            st->newVal = bmake_strdup("1");
1.236     rillig   2742:        } else {
1.412     rillig   2743:            Buffer buf;
                   2744:
1.479     rillig   2745:            Words words = Str_Words(st->val, FALSE);
                   2746:            size_t ac = words.len;
                   2747:            Words_Free(words);
1.494     rillig   2748:
1.479     rillig   2749:            Buf_Init(&buf, 4);  /* 3 digits + '\0' is usually enough */
1.465     rillig   2750:            Buf_AddInt(&buf, (int)ac);
1.349     rillig   2751:            st->newVal = Buf_Destroy(&buf, FALSE);
1.236     rillig   2752:        }
1.288     rillig   2753:        goto ok;
                   2754:     }
                   2755:
                   2756:     if (estr[0] == '*' && estr[1] == '\0') {
1.236     rillig   2757:        /* Found ":[*]" */
1.301     rillig   2758:        st->oneBigWord = TRUE;
1.349     rillig   2759:        st->newVal = st->val;
1.288     rillig   2760:        goto ok;
                   2761:     }
                   2762:
                   2763:     if (estr[0] == '@' && estr[1] == '\0') {
1.236     rillig   2764:        /* Found ":[@]" */
1.301     rillig   2765:        st->oneBigWord = FALSE;
1.349     rillig   2766:        st->newVal = st->val;
1.288     rillig   2767:        goto ok;
                   2768:     }
                   2769:
                   2770:     /*
                   2771:      * We expect estr to contain a single integer for :[N], or two integers
                   2772:      * separated by ".." for :[start..end].
                   2773:      */
1.635     rillig   2774:     p = estr;
                   2775:     if (!TryParseIntBase0(&p, &first))
                   2776:        goto bad_modifier;      /* Found junk instead of a number */
1.288     rillig   2777:
1.635     rillig   2778:     if (p[0] == '\0') {        /* Found only one integer in :[N] */
1.290     rillig   2779:        last = first;
1.635     rillig   2780:     } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') {
1.288     rillig   2781:        /* Expecting another integer after ".." */
1.635     rillig   2782:        p += 2;
                   2783:        if (!TryParseIntBase0(&p, &last) || *p != '\0')
                   2784:            goto bad_modifier;  /* Found junk after ".." */
1.288     rillig   2785:     } else
                   2786:        goto bad_modifier;      /* Found junk instead of ".." */
1.236     rillig   2787:
1.288     rillig   2788:     /*
1.633     rillig   2789:      * Now first and last are properly filled in, but we still have to check
                   2790:      * for 0 as a special case.
1.288     rillig   2791:      */
1.290     rillig   2792:     if (first == 0 && last == 0) {
1.288     rillig   2793:        /* ":[0]" or perhaps ":[0..0]" */
1.301     rillig   2794:        st->oneBigWord = TRUE;
1.349     rillig   2795:        st->newVal = st->val;
1.288     rillig   2796:        goto ok;
1.236     rillig   2797:     }
1.288     rillig   2798:
                   2799:     /* ":[0..N]" or ":[N..0]" */
1.290     rillig   2800:     if (first == 0 || last == 0)
1.288     rillig   2801:        goto bad_modifier;
                   2802:
1.633     rillig   2803:     /* Normal case: select the words described by first and last. */
1.349     rillig   2804:     st->newVal = VarSelectWords(st->sep, st->oneBigWord, st->val, first, last);
1.288     rillig   2805:
                   2806: ok:
                   2807:     free(estr);
1.356     rillig   2808:     return AMR_OK;
1.288     rillig   2809:
                   2810: bad_modifier:
                   2811:     free(estr);
1.356     rillig   2812:     return AMR_BAD;
1.236     rillig   2813: }
                   2814:
1.404     rillig   2815: static int
                   2816: str_cmp_asc(const void *a, const void *b)
                   2817: {
                   2818:     return strcmp(*(const char * const *)a, *(const char * const *)b);
                   2819: }
                   2820:
                   2821: static int
                   2822: str_cmp_desc(const void *a, const void *b)
                   2823: {
                   2824:     return strcmp(*(const char * const *)b, *(const char * const *)a);
                   2825: }
                   2826:
1.402     rillig   2827: /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
1.356     rillig   2828: static ApplyModifierResult
1.409     rillig   2829: ApplyModifier_Order(const char **pp, ApplyModifiersState *st)
1.236     rillig   2830: {
1.409     rillig   2831:     const char *mod = (*pp)++; /* skip past the 'O' in any case */
1.402     rillig   2832:
1.479     rillig   2833:     Words words = Str_Words(st->val, FALSE);
1.401     rillig   2834:
1.299     rillig   2835:     if (mod[1] == st->endc || mod[1] == ':') {
1.417     rillig   2836:        /* :O sorts ascending */
1.479     rillig   2837:        qsort(words.words, words.len, sizeof(char *), str_cmp_asc);
1.402     rillig   2838:
1.299     rillig   2839:     } else if ((mod[1] == 'r' || mod[1] == 'x') &&
                   2840:               (mod[2] == st->endc || mod[2] == ':')) {
1.409     rillig   2841:        (*pp)++;
1.402     rillig   2842:
                   2843:        if (mod[1] == 'r') {
                   2844:            /* :Or sorts descending */
1.479     rillig   2845:            qsort(words.words, words.len, sizeof(char *), str_cmp_desc);
1.402     rillig   2846:
                   2847:        } else {
                   2848:            /* :Ox shuffles
                   2849:             *
                   2850:             * We will use [ac..2] range for mod factors. This will produce
                   2851:             * random numbers in [(ac-1)..0] interval, and minimal
                   2852:             * reasonable value for mod factor is 2 (the mod 1 will produce
                   2853:             * 0 with probability 1).
                   2854:             */
1.465     rillig   2855:            size_t i;
1.479     rillig   2856:            for (i = words.len - 1; i > 0; i--) {
1.465     rillig   2857:                size_t rndidx = (size_t)random() % (i + 1);
1.479     rillig   2858:                char *t = words.words[i];
                   2859:                words.words[i] = words.words[rndidx];
                   2860:                words.words[rndidx] = t;
1.402     rillig   2861:            }
                   2862:        }
1.236     rillig   2863:     } else {
1.479     rillig   2864:        Words_Free(words);
1.356     rillig   2865:        return AMR_BAD;
1.236     rillig   2866:     }
1.402     rillig   2867:
1.479     rillig   2868:     st->newVal = Words_JoinFree(words);
1.356     rillig   2869:     return AMR_OK;
1.236     rillig   2870: }
                   2871:
                   2872: /* :? then : else */
1.356     rillig   2873: static ApplyModifierResult
1.409     rillig   2874: ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
1.236     rillig   2875: {
1.412     rillig   2876:     char *then_expr, *else_expr;
1.531     rillig   2877:     VarParseResult res;
1.412     rillig   2878:
1.285     rillig   2879:     Boolean value = FALSE;
1.448     rillig   2880:     VarEvalFlags then_eflags = st->eflags & ~(unsigned)VARE_WANTRES;
                   2881:     VarEvalFlags else_eflags = st->eflags & ~(unsigned)VARE_WANTRES;
1.236     rillig   2882:
1.384     rillig   2883:     int cond_rc = COND_PARSE;  /* anything other than COND_INVALID */
1.268     rillig   2884:     if (st->eflags & VARE_WANTRES) {
1.511     rillig   2885:        cond_rc = Cond_EvalCondition(st->v->name, &value);
1.285     rillig   2886:        if (cond_rc != COND_INVALID && value)
                   2887:            then_eflags |= VARE_WANTRES;
                   2888:        if (cond_rc != COND_INVALID && !value)
                   2889:            else_eflags |= VARE_WANTRES;
1.236     rillig   2890:     }
                   2891:
1.409     rillig   2892:     (*pp)++;                   /* skip past the '?' */
1.535     rillig   2893:     res = ParseModifierPart(pp, ':', then_eflags, st,
1.531     rillig   2894:                            &then_expr, NULL, NULL, NULL);
                   2895:     if (res != VPR_OK)
1.356     rillig   2896:        return AMR_CLEANUP;
1.236     rillig   2897:
1.535     rillig   2898:     res = ParseModifierPart(pp, st->endc, else_eflags, st,
1.531     rillig   2899:                            &else_expr, NULL, NULL, NULL);
                   2900:     if (res != VPR_OK)
1.356     rillig   2901:        return AMR_CLEANUP;
1.236     rillig   2902:
1.409     rillig   2903:     (*pp)--;
1.236     rillig   2904:     if (cond_rc == COND_INVALID) {
                   2905:        Error("Bad conditional expression `%s' in %s?%s:%s",
1.417     rillig   2906:              st->v->name, st->v->name, then_expr, else_expr);
1.356     rillig   2907:        return AMR_CLEANUP;
1.236     rillig   2908:     }
                   2909:
                   2910:     if (value) {
1.349     rillig   2911:        st->newVal = then_expr;
1.258     rillig   2912:        free(else_expr);
1.236     rillig   2913:     } else {
1.349     rillig   2914:        st->newVal = else_expr;
1.270     rillig   2915:        free(then_expr);
1.236     rillig   2916:     }
1.527     rillig   2917:     ApplyModifiersState_Define(st);
1.356     rillig   2918:     return AMR_OK;
1.236     rillig   2919: }
                   2920:
1.283     rillig   2921: /*
                   2922:  * The ::= modifiers actually assign a value to the variable.
                   2923:  * Their main purpose is in supporting modifiers of .for loop
                   2924:  * iterators and other obscure uses.  They always expand to
                   2925:  * nothing.  In a target rule that would otherwise expand to an
                   2926:  * empty line they can be preceded with @: to keep make happy.
                   2927:  * Eg.
                   2928:  *
                   2929:  * foo:        .USE
                   2930:  * .for i in ${.TARGET} ${.TARGET:R}.gz
1.546     rillig   2931:  *     @: ${t::=$i}
1.283     rillig   2932:  *     @echo blah ${t:T}
                   2933:  * .endfor
                   2934:  *
                   2935:  *       ::=<str>      Assigns <str> as the new value of variable.
                   2936:  *       ::?=<str>     Assigns <str> as value of variable if
                   2937:  *                     it was not already set.
                   2938:  *       ::+=<str>     Appends <str> to variable.
                   2939:  *       ::!=<cmd>     Assigns output of <cmd> as the new value of
                   2940:  *                     variable.
                   2941:  */
1.356     rillig   2942: static ApplyModifierResult
1.409     rillig   2943: ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
1.236     rillig   2944: {
1.412     rillig   2945:     GNode *v_ctxt;
                   2946:     char delim;
                   2947:     char *val;
1.531     rillig   2948:     VarParseResult res;
1.412     rillig   2949:
1.409     rillig   2950:     const char *mod = *pp;
1.299     rillig   2951:     const char *op = mod + 1;
1.236     rillig   2952:
1.638     rillig   2953:     if (op[0] == '=')
1.640   ! rillig   2954:        goto ok;
1.638     rillig   2955:     if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=')
                   2956:        goto ok;
                   2957:     return AMR_UNKNOWN;                /* "::<unrecognised>" */
                   2958: ok:
1.272     rillig   2959:
1.570     rillig   2960:     if (st->v->name[0] == '\0') {
1.409     rillig   2961:        *pp = mod + 1;
1.356     rillig   2962:        return AMR_BAD;
1.355     rillig   2963:     }
1.272     rillig   2964:
1.412     rillig   2965:     v_ctxt = st->ctxt;         /* context where v belongs */
1.570     rillig   2966:     if (!(st->exprFlags & VEF_UNDEF) && st->ctxt != VAR_GLOBAL) {
1.272     rillig   2967:        Var *gv = VarFind(st->v->name, st->ctxt, 0);
                   2968:        if (gv == NULL)
                   2969:            v_ctxt = VAR_GLOBAL;
                   2970:        else
                   2971:            VarFreeEnv(gv, TRUE);
                   2972:     }
                   2973:
1.273     rillig   2974:     switch (op[0]) {
1.272     rillig   2975:     case '+':
                   2976:     case '?':
                   2977:     case '!':
1.409     rillig   2978:        *pp = mod + 3;
1.272     rillig   2979:        break;
                   2980:     default:
1.409     rillig   2981:        *pp = mod + 2;
1.272     rillig   2982:        break;
                   2983:     }
                   2984:
1.521     rillig   2985:     delim = st->startc == '(' ? ')' : '}';
1.531     rillig   2986:     res = ParseModifierPart(pp, delim, st->eflags, st, &val, NULL, NULL, NULL);
                   2987:     if (res != VPR_OK)
1.356     rillig   2988:        return AMR_CLEANUP;
1.236     rillig   2989:
1.409     rillig   2990:     (*pp)--;
1.236     rillig   2991:
1.272     rillig   2992:     if (st->eflags & VARE_WANTRES) {
1.273     rillig   2993:        switch (op[0]) {
1.236     rillig   2994:        case '+':
1.273     rillig   2995:            Var_Append(st->v->name, val, v_ctxt);
1.272     rillig   2996:            break;
1.273     rillig   2997:        case '!': {
1.416     rillig   2998:            const char *errfmt;
                   2999:            char *cmd_output = Cmd_Exec(val, &errfmt);
                   3000:            if (errfmt)
1.472     rillig   3001:                Error(errfmt, val);
1.272     rillig   3002:            else
1.406     rillig   3003:                Var_Set(st->v->name, cmd_output, v_ctxt);
                   3004:            free(cmd_output);
1.236     rillig   3005:            break;
1.273     rillig   3006:        }
1.272     rillig   3007:        case '?':
1.527     rillig   3008:            if (!(st->exprFlags & VEF_UNDEF))
1.272     rillig   3009:                break;
                   3010:            /* FALLTHROUGH */
1.236     rillig   3011:        default:
1.273     rillig   3012:            Var_Set(st->v->name, val, v_ctxt);
1.236     rillig   3013:            break;
                   3014:        }
                   3015:     }
1.273     rillig   3016:     free(val);
1.536     rillig   3017:     st->newVal = emptyString;
1.356     rillig   3018:     return AMR_OK;
1.236     rillig   3019: }
                   3020:
1.639     rillig   3021: /* :_=...
                   3022:  * remember current value */
1.356     rillig   3023: static ApplyModifierResult
1.409     rillig   3024: ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
1.236     rillig   3025: {
1.409     rillig   3026:     const char *mod = *pp;
1.358     rillig   3027:     if (!ModMatchEq(mod, "_", st->endc))
1.356     rillig   3028:        return AMR_UNKNOWN;
1.236     rillig   3029:
1.299     rillig   3030:     if (mod[1] == '=') {
1.340     rillig   3031:        size_t n = strcspn(mod + 2, ":)}");
1.450     rillig   3032:        char *name = bmake_strldup(mod + 2, n);
1.349     rillig   3033:        Var_Set(name, st->val, st->ctxt);
1.340     rillig   3034:        free(name);
1.409     rillig   3035:        *pp = mod + 2 + n;
1.236     rillig   3036:     } else {
1.349     rillig   3037:        Var_Set("_", st->val, st->ctxt);
1.409     rillig   3038:        *pp = mod + 1;
1.236     rillig   3039:     }
1.349     rillig   3040:     st->newVal = st->val;
1.356     rillig   3041:     return AMR_OK;
1.236     rillig   3042: }
                   3043:
1.639     rillig   3044: /* Apply the given function to each word of the variable value,
                   3045:  * for a single-letter modifier such as :H, :T. */
1.434     rillig   3046: static ApplyModifierResult
                   3047: ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
                   3048:                       ModifyWordsCallback modifyWord)
                   3049: {
                   3050:     char delim = (*pp)[1];
                   3051:     if (delim != st->endc && delim != ':')
                   3052:        return AMR_UNKNOWN;
                   3053:
1.619     rillig   3054:     st->newVal = ModifyWords(st->val, modifyWord, NULL,
                   3055:                             st->oneBigWord, st->sep);
1.434     rillig   3056:     (*pp)++;
                   3057:     return AMR_OK;
                   3058: }
                   3059:
1.567     rillig   3060: static ApplyModifierResult
                   3061: ApplyModifier_Unique(const char **pp, ApplyModifiersState *st)
                   3062: {
                   3063:     if ((*pp)[1] == st->endc || (*pp)[1] == ':') {
                   3064:        st->newVal = VarUniq(st->val);
                   3065:        (*pp)++;
                   3066:        return AMR_OK;
                   3067:     } else
                   3068:        return AMR_UNKNOWN;
                   3069: }
                   3070:
1.236     rillig   3071: #ifdef SYSVVARSUB
                   3072: /* :from=to */
1.356     rillig   3073: static ApplyModifierResult
1.409     rillig   3074: ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
1.236     rillig   3075: {
1.412     rillig   3076:     char *lhs, *rhs;
1.531     rillig   3077:     VarParseResult res;
1.412     rillig   3078:
1.409     rillig   3079:     const char *mod = *pp;
1.276     rillig   3080:     Boolean eqFound = FALSE;
1.245     rillig   3081:
1.236     rillig   3082:     /*
1.639     rillig   3083:      * First we make a pass through the string trying to verify it is a
                   3084:      * SysV-make-style translation. It must be: <lhs>=<rhs>
1.236     rillig   3085:      */
1.639     rillig   3086:     int depth = 1;
                   3087:     const char *p = mod;
                   3088:     while (*p != '\0' && depth > 0) {
                   3089:        if (*p == '=') {        /* XXX: should also test depth == 1 */
1.236     rillig   3090:            eqFound = TRUE;
                   3091:            /* continue looking for st->endc */
1.639     rillig   3092:        } else if (*p == st->endc)
                   3093:            depth--;
                   3094:        else if (*p == st->startc)
                   3095:            depth++;
                   3096:        if (depth > 0)
                   3097:            p++;
1.236     rillig   3098:     }
1.639     rillig   3099:     if (*p != st->endc || !eqFound)
1.356     rillig   3100:        return AMR_UNKNOWN;
1.236     rillig   3101:
1.409     rillig   3102:     *pp = mod;
1.535     rillig   3103:     res = ParseModifierPart(pp, '=', st->eflags, st,
                   3104:                            &lhs, NULL, NULL, NULL);
1.531     rillig   3105:     if (res != VPR_OK)
1.356     rillig   3106:        return AMR_CLEANUP;
1.245     rillig   3107:
1.640   ! rillig   3108:     /* The SysV modifier lasts until the end of the variable expression. */
1.535     rillig   3109:     res = ParseModifierPart(pp, st->endc, st->eflags, st,
                   3110:                            &rhs, NULL, NULL, NULL);
1.531     rillig   3111:     if (res != VPR_OK)
1.356     rillig   3112:        return AMR_CLEANUP;
1.236     rillig   3113:
1.409     rillig   3114:     (*pp)--;
1.492     rillig   3115:     if (lhs[0] == '\0' && st->val[0] == '\0') {
1.349     rillig   3116:        st->newVal = st->val;   /* special case */
1.245     rillig   3117:     } else {
1.541     rillig   3118:        struct ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs};
1.619     rillig   3119:        st->newVal = ModifyWords(st->val, ModifyWord_SYSVSubst, &args,
                   3120:                                 st->oneBigWord, st->sep);
1.245     rillig   3121:     }
1.276     rillig   3122:     free(lhs);
                   3123:     free(rhs);
1.356     rillig   3124:     return AMR_OK;
1.236     rillig   3125: }
                   3126: #endif
                   3127:
1.548     rillig   3128: #ifdef SUNSHCMD
                   3129: /* :sh */
                   3130: static ApplyModifierResult
                   3131: ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st)
                   3132: {
                   3133:     const char *p = *pp;
                   3134:     if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) {
                   3135:        if (st->eflags & VARE_WANTRES) {
                   3136:            const char *errfmt;
                   3137:            st->newVal = Cmd_Exec(st->val, &errfmt);
                   3138:            if (errfmt)
                   3139:                Error(errfmt, st->val);
                   3140:        } else
                   3141:            st->newVal = emptyString;
                   3142:        *pp = p + 2;
                   3143:        return AMR_OK;
                   3144:     } else
                   3145:        return AMR_UNKNOWN;
                   3146: }
                   3147: #endif
                   3148:
1.549     rillig   3149: static void
                   3150: LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc)
                   3151: {
                   3152:     char eflags_str[VarEvalFlags_ToStringSize];
                   3153:     char vflags_str[VarFlags_ToStringSize];
                   3154:     char exprflags_str[VarExprFlags_ToStringSize];
                   3155:     Boolean is_single_char = mod[0] != '\0' &&
                   3156:                             (mod[1] == endc || mod[1] == ':');
                   3157:
                   3158:     /* At this point, only the first character of the modifier can
                   3159:      * be used since the end of the modifier is not yet known. */
1.550     rillig   3160:     debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n",
                   3161:                 st->v->name, mod[0], is_single_char ? "" : "...", st->val,
                   3162:                 Enum_FlagsToString(eflags_str, sizeof eflags_str,
                   3163:                                    st->eflags, VarEvalFlags_ToStringSpecs),
                   3164:                 Enum_FlagsToString(vflags_str, sizeof vflags_str,
                   3165:                                    st->v->flags, VarFlags_ToStringSpecs),
                   3166:                 Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
                   3167:                                    st->exprFlags,
                   3168:                                    VarExprFlags_ToStringSpecs));
1.549     rillig   3169: }
                   3170:
                   3171: static void
                   3172: LogAfterApply(ApplyModifiersState *st, const char *p, const char *mod)
                   3173: {
                   3174:     char eflags_str[VarEvalFlags_ToStringSize];
                   3175:     char vflags_str[VarFlags_ToStringSize];
                   3176:     char exprflags_str[VarExprFlags_ToStringSize];
                   3177:     const char *quot = st->newVal == var_Error ? "" : "\"";
                   3178:     const char *newVal = st->newVal == var_Error ? "error" : st->newVal;
                   3179:
1.550     rillig   3180:     debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n",
                   3181:                 st->v->name, (int)(p - mod), mod, quot, newVal, quot,
                   3182:                 Enum_FlagsToString(eflags_str, sizeof eflags_str,
                   3183:                                    st->eflags, VarEvalFlags_ToStringSpecs),
                   3184:                 Enum_FlagsToString(vflags_str, sizeof vflags_str,
                   3185:                                    st->v->flags, VarFlags_ToStringSpecs),
                   3186:                 Enum_FlagsToString(exprflags_str, sizeof exprflags_str,
                   3187:                                    st->exprFlags,
                   3188:                                    VarExprFlags_ToStringSpecs));
1.549     rillig   3189: }
                   3190:
1.551     rillig   3191: static ApplyModifierResult
                   3192: ApplyModifier(const char **pp, ApplyModifiersState *st)
                   3193: {
                   3194:     switch (**pp) {
                   3195:     case ':':
                   3196:        return ApplyModifier_Assign(pp, st);
                   3197:     case '@':
                   3198:        return ApplyModifier_Loop(pp, st);
                   3199:     case '_':
                   3200:        return ApplyModifier_Remember(pp, st);
                   3201:     case 'D':
                   3202:     case 'U':
                   3203:        return ApplyModifier_Defined(pp, st);
                   3204:     case 'L':
1.571     rillig   3205:        return ApplyModifier_Literal(pp, st);
1.551     rillig   3206:     case 'P':
                   3207:        return ApplyModifier_Path(pp, st);
                   3208:     case '!':
                   3209:        return ApplyModifier_ShellCommand(pp, st);
                   3210:     case '[':
                   3211:        return ApplyModifier_Words(pp, st);
                   3212:     case 'g':
                   3213:        return ApplyModifier_Gmtime(pp, st);
                   3214:     case 'h':
                   3215:        return ApplyModifier_Hash(pp, st);
                   3216:     case 'l':
                   3217:        return ApplyModifier_Localtime(pp, st);
                   3218:     case 't':
                   3219:        return ApplyModifier_To(pp, st);
                   3220:     case 'N':
                   3221:     case 'M':
                   3222:        return ApplyModifier_Match(pp, st);
                   3223:     case 'S':
                   3224:        return ApplyModifier_Subst(pp, st);
                   3225:     case '?':
                   3226:        return ApplyModifier_IfElse(pp, st);
                   3227: #ifndef NO_REGEX
                   3228:     case 'C':
                   3229:        return ApplyModifier_Regex(pp, st);
                   3230: #endif
                   3231:     case 'q':
                   3232:     case 'Q':
1.571     rillig   3233:        return ApplyModifier_Quote(pp, st);
1.551     rillig   3234:     case 'T':
                   3235:        return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail);
                   3236:     case 'H':
                   3237:        return ApplyModifier_WordFunc(pp, st, ModifyWord_Head);
                   3238:     case 'E':
                   3239:        return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix);
                   3240:     case 'R':
                   3241:        return ApplyModifier_WordFunc(pp, st, ModifyWord_Root);
                   3242:     case 'r':
                   3243:        return ApplyModifier_Range(pp, st);
                   3244:     case 'O':
                   3245:        return ApplyModifier_Order(pp, st);
                   3246:     case 'u':
1.571     rillig   3247:        return ApplyModifier_Unique(pp, st);
1.551     rillig   3248: #ifdef SUNSHCMD
                   3249:     case 's':
                   3250:        return ApplyModifier_SunShell(pp, st);
                   3251: #endif
                   3252:     default:
                   3253:        return AMR_UNKNOWN;
                   3254:     }
                   3255: }
                   3256:
1.419     rillig   3257: /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
1.108     sjg      3258: static char *
1.357     rillig   3259: ApplyModifiers(
1.367     rillig   3260:     const char **pp,           /* the parsing position, updated upon return */
1.640   ! rillig   3261:     char *const val,           /* the current value of the expression */
1.444     rillig   3262:     char const startc,         /* '(' or '{', or '\0' for indirect modifiers */
                   3263:     char const endc,           /* ')' or '}', or '\0' for indirect modifiers */
1.527     rillig   3264:     Var * const v,
                   3265:     VarExprFlags *exprFlags,
1.357     rillig   3266:     GNode * const ctxt,                /* for looking up and modifying variables */
                   3267:     VarEvalFlags const eflags,
1.640   ! rillig   3268:     void ** const out_freeIt   /* free this after using the return value */
1.357     rillig   3269: ) {
1.236     rillig   3270:     ApplyModifiersState st = {
1.640   ! rillig   3271:        startc, endc, v, ctxt, eflags,
        !          3272:        val,                    /* .val */
1.460     rillig   3273:        var_Error,              /* .newVal */
1.443     rillig   3274:        ' ',                    /* .sep */
1.527     rillig   3275:        FALSE,                  /* .oneBigWord */
                   3276:        *exprFlags              /* .exprFlags */
1.443     rillig   3277:     };
1.412     rillig   3278:     const char *p;
                   3279:     const char *mod;
                   3280:     ApplyModifierResult res;
                   3281:
                   3282:     assert(startc == '(' || startc == '{' || startc == '\0');
1.413     rillig   3283:     assert(endc == ')' || endc == '}' || endc == '\0');
1.460     rillig   3284:     assert(val != NULL);
1.15      christos 3285:
1.412     rillig   3286:     p = *pp;
1.299     rillig   3287:     while (*p != '\0' && *p != endc) {
1.142     dsl      3288:
1.299     rillig   3289:        if (*p == '$') {
1.142     dsl      3290:            /*
1.167     sjg      3291:             * We may have some complex modifiers in a variable.
1.1       cgd      3292:             */
1.489     rillig   3293:            const char *nested_p = p;
1.108     sjg      3294:            void *freeIt;
1.514     rillig   3295:            const char *rval;
1.539     rillig   3296:            char c;
1.514     rillig   3297:
                   3298:            (void)Var_Parse(&nested_p, st.ctxt, st.eflags, &rval, &freeIt);
                   3299:            /* TODO: handle errors */
1.1       cgd      3300:
1.167     sjg      3301:            /*
1.567     rillig   3302:             * If we have not parsed up to st.endc or ':', we are not
                   3303:             * interested.  This means the expression ${VAR:${M_1}${M_2}}
                   3304:             * is not accepted, but ${VAR:${M_1}:${M_2}} is.
1.167     sjg      3305:             */
1.447     rillig   3306:            if (rval[0] != '\0' &&
1.489     rillig   3307:                (c = *nested_p) != '\0' && c != ':' && c != st.endc) {
1.567     rillig   3308:                if (DEBUG(LINT))
                   3309:                    Parse_Error(PARSE_FATAL,
                   3310:                                "Missing delimiter ':' after indirect modifier \"%.*s\"",
                   3311:                                (int)(nested_p - p), p);
                   3312:
1.196     christos 3313:                free(freeIt);
1.491     rillig   3314:                /* XXX: apply_mods doesn't sound like "not interested". */
1.567     rillig   3315:                /* XXX: Why is the indirect modifier parsed again by
                   3316:                 * apply_mods?  If any, p should be advanced to nested_p. */
1.167     sjg      3317:                goto apply_mods;
                   3318:            }
                   3319:
1.547     rillig   3320:            VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n",
1.599     rillig   3321:                       rval, (int)(size_t)(nested_p - p), p);
1.1       cgd      3322:
1.489     rillig   3323:            p = nested_p;
1.15      christos 3324:
1.447     rillig   3325:            if (rval[0] != '\0') {
1.367     rillig   3326:                const char *rval_pp = rval;
1.444     rillig   3327:                st.val = ApplyModifiers(&rval_pp, st.val, '\0', '\0', v,
1.640   ! rillig   3328:                                        &st.exprFlags, ctxt, eflags, out_freeIt);
1.349     rillig   3329:                if (st.val == var_Error
1.536     rillig   3330:                    || (st.val == varUndefined && !(st.eflags & VARE_UNDEFERR))
1.367     rillig   3331:                    || *rval_pp != '\0') {
1.196     christos 3332:                    free(freeIt);
1.240     rillig   3333:                    goto out;   /* error already reported */
1.1       cgd      3334:                }
                   3335:            }
1.196     christos 3336:            free(freeIt);
1.567     rillig   3337:
1.299     rillig   3338:            if (*p == ':')
                   3339:                p++;
                   3340:            else if (*p == '\0' && endc != '\0') {
1.246     rillig   3341:                Error("Unclosed variable specification after complex "
1.417     rillig   3342:                      "modifier (expecting '%c') for %s", st.endc, st.v->name);
1.119     sjg      3343:                goto out;
                   3344:            }
1.108     sjg      3345:            continue;
                   3346:        }
1.167     sjg      3347:     apply_mods:
1.417     rillig   3348:        st.newVal = var_Error;  /* default value, in case of errors */
1.409     rillig   3349:        mod = p;
1.430     rillig   3350:
1.549     rillig   3351:        if (DEBUG(VAR))
                   3352:            LogBeforeApply(&st, mod, endc);
1.430     rillig   3353:
1.551     rillig   3354:        res = ApplyModifier(&p, &st);
1.356     rillig   3355:
1.108     sjg      3356: #ifdef SYSVVARSUB
1.409     rillig   3357:        if (res == AMR_UNKNOWN) {
                   3358:            assert(p == mod);
                   3359:            res = ApplyModifier_SysV(&p, &st);
                   3360:        }
1.108     sjg      3361: #endif
1.356     rillig   3362:
                   3363:        if (res == AMR_UNKNOWN) {
1.409     rillig   3364:            Error("Unknown modifier '%c'", *mod);
                   3365:            for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++)
                   3366:                continue;
1.356     rillig   3367:            st.newVal = var_Error;
                   3368:        }
                   3369:        if (res == AMR_CLEANUP)
                   3370:            goto cleanup;
                   3371:        if (res == AMR_BAD)
                   3372:            goto bad_modifier;
                   3373:
1.549     rillig   3374:        if (DEBUG(VAR))
                   3375:            LogAfterApply(&st, p, mod);
1.25      christos 3376:
1.349     rillig   3377:        if (st.newVal != st.val) {
1.640   ! rillig   3378:            if (*out_freeIt) {
1.349     rillig   3379:                free(st.val);
1.640   ! rillig   3380:                *out_freeIt = NULL;
1.108     sjg      3381:            }
1.349     rillig   3382:            st.val = st.newVal;
1.536     rillig   3383:            if (st.val != var_Error && st.val != varUndefined &&
                   3384:                st.val != emptyString) {
1.640   ! rillig   3385:                *out_freeIt = st.val;
1.108     sjg      3386:            }
                   3387:        }
1.409     rillig   3388:        if (*p == '\0' && st.endc != '\0') {
1.246     rillig   3389:            Error("Unclosed variable specification (expecting '%c') "
1.417     rillig   3390:                  "for \"%s\" (value \"%s\") modifier %c",
                   3391:                  st.endc, st.v->name, st.val, *mod);
1.409     rillig   3392:        } else if (*p == ':') {
                   3393:            p++;
1.567     rillig   3394:        } else if (DEBUG(LINT) && *p != '\0' && *p != endc) {
                   3395:            Parse_Error(PARSE_FATAL,
                   3396:                        "Missing delimiter ':' after modifier \"%.*s\"",
                   3397:                        (int)(p - mod), mod);
1.108     sjg      3398:        }
                   3399:     }
1.240     rillig   3400: out:
1.367     rillig   3401:     *pp = p;
1.536     rillig   3402:     assert(st.val != NULL);    /* Use var_Error or varUndefined instead. */
1.527     rillig   3403:     *exprFlags = st.exprFlags;
1.349     rillig   3404:     return st.val;
1.25      christos 3405:
1.240     rillig   3406: bad_modifier:
1.299     rillig   3407:     Error("Bad modifier `:%.*s' for %s",
1.409     rillig   3408:          (int)strcspn(mod, ":)}"), mod, st.v->name);
1.25      christos 3409:
1.240     rillig   3410: cleanup:
1.409     rillig   3411:     *pp = p;
1.640   ! rillig   3412:     free(*out_freeIt);
        !          3413:     *out_freeIt = NULL;
1.527     rillig   3414:     *exprFlags = st.exprFlags;
1.231     rillig   3415:     return var_Error;
1.108     sjg      3416: }
1.25      christos 3417:
1.626     rillig   3418: /* Only four of the local variables are treated specially as they are the
                   3419:  * only four that will be set when dynamic sources are expanded. */
1.335     rillig   3420: static Boolean
1.626     rillig   3421: VarnameIsDynamic(const char *name, size_t len)
1.335     rillig   3422: {
1.626     rillig   3423:     if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
                   3424:        switch (name[0]) {
1.335     rillig   3425:        case '@':
                   3426:        case '%':
                   3427:        case '*':
                   3428:        case '!':
                   3429:            return TRUE;
                   3430:        }
                   3431:        return FALSE;
                   3432:     }
                   3433:
1.626     rillig   3434:     if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
                   3435:        return strcmp(name, ".TARGET") == 0 ||
                   3436:               strcmp(name, ".ARCHIVE") == 0 ||
                   3437:               strcmp(name, ".PREFIX") == 0 ||
                   3438:               strcmp(name, ".MEMBER") == 0;
1.335     rillig   3439:     }
                   3440:
                   3441:     return FALSE;
                   3442: }
                   3443:
1.502     rillig   3444: static const char *
1.553     rillig   3445: UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags)
1.502     rillig   3446: {
1.594     rillig   3447:     if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) {
1.502     rillig   3448:        /*
                   3449:         * If substituting a local variable in a non-local context,
                   3450:         * assume it's for dynamic source stuff. We have to handle
                   3451:         * this specially and return the longhand for the variable
                   3452:         * with the dollar sign escaped so it makes it back to the
                   3453:         * caller. Only four of the local variables are treated
                   3454:         * specially as they are the only four that will be set
                   3455:         * when dynamic sources are expanded.
                   3456:         */
                   3457:        switch (varname) {
                   3458:        case '@':
                   3459:            return "$(.TARGET)";
                   3460:        case '%':
                   3461:            return "$(.MEMBER)";
                   3462:        case '*':
                   3463:            return "$(.PREFIX)";
                   3464:        case '!':
                   3465:            return "$(.ARCHIVE)";
                   3466:        }
                   3467:     }
1.536     rillig   3468:     return eflags & VARE_UNDEFERR ? var_Error : varUndefined;
1.502     rillig   3469: }
                   3470:
1.504     rillig   3471: /* Parse a variable name, until the end character or a colon, whichever
                   3472:  * comes first. */
                   3473: static char *
1.501     rillig   3474: ParseVarname(const char **pp, char startc, char endc,
1.504     rillig   3475:             GNode *ctxt, VarEvalFlags eflags,
                   3476:             size_t *out_varname_len)
1.501     rillig   3477: {
1.504     rillig   3478:     Buffer buf;
1.501     rillig   3479:     const char *p = *pp;
                   3480:     int depth = 1;
                   3481:
1.504     rillig   3482:     Buf_Init(&buf, 0);
                   3483:
1.501     rillig   3484:     while (*p != '\0') {
                   3485:        /* Track depth so we can spot parse errors. */
                   3486:        if (*p == startc)
                   3487:            depth++;
                   3488:        if (*p == endc) {
                   3489:            if (--depth == 0)
                   3490:                break;
                   3491:        }
                   3492:        if (*p == ':' && depth == 1)
                   3493:            break;
1.504     rillig   3494:
1.501     rillig   3495:        /* A variable inside a variable, expand. */
                   3496:        if (*p == '$') {
                   3497:            void *freeIt;
1.514     rillig   3498:            const char *rval;
                   3499:            (void)Var_Parse(&p, ctxt, eflags, &rval, &freeIt);
                   3500:            /* TODO: handle errors */
1.504     rillig   3501:            Buf_AddStr(&buf, rval);
1.501     rillig   3502:            free(freeIt);
                   3503:        } else {
1.504     rillig   3504:            Buf_AddByte(&buf, *p);
1.501     rillig   3505:            p++;
                   3506:        }
                   3507:     }
                   3508:     *pp = p;
1.545     rillig   3509:     *out_varname_len = Buf_Len(&buf);
1.504     rillig   3510:     return Buf_Destroy(&buf, FALSE);
1.501     rillig   3511: }
                   3512:
1.507     rillig   3513: static Boolean
                   3514: ValidShortVarname(char varname, const char *start)
                   3515: {
1.508     rillig   3516:     switch (varname) {
                   3517:     case '\0':
                   3518:     case ')':
                   3519:     case '}':
                   3520:     case ':':
                   3521:     case '$':
1.523     rillig   3522:        break;                  /* and continue below */
1.508     rillig   3523:     default:
1.571     rillig   3524:        return TRUE;
1.508     rillig   3525:     }
1.507     rillig   3526:
                   3527:     if (!DEBUG(LINT))
                   3528:        return FALSE;
                   3529:
                   3530:     if (varname == '$')
                   3531:        Parse_Error(PARSE_FATAL,
                   3532:                    "To escape a dollar, use \\$, not $$, at \"%s\"", start);
                   3533:     else if (varname == '\0')
                   3534:        Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
                   3535:     else
                   3536:        Parse_Error(PARSE_FATAL,
                   3537:                    "Invalid variable name '%c', at \"%s\"", varname, start);
                   3538:
                   3539:     return FALSE;
                   3540: }
                   3541:
1.622     rillig   3542: /* Parse a single-character variable name such as $V or $@.
                   3543:  * Return whether to continue parsing. */
                   3544: static Boolean
1.624     rillig   3545: ParseVarnameShort(
                   3546:        char startc,
                   3547:        const char **pp,
                   3548:        GNode *ctxt,
                   3549:        VarEvalFlags eflags,
                   3550:        VarParseResult *out_FALSE_res,
                   3551:        const char **out_FALSE_val,
                   3552:        Var **out_TRUE_var
                   3553: ) {
1.622     rillig   3554:     char name[2];
                   3555:     Var *v;
                   3556:
                   3557:     /*
                   3558:      * If it's not bounded by braces of some sort, life is much simpler.
                   3559:      * We just need to check for the first character and return the
                   3560:      * value if it exists.
                   3561:      */
                   3562:
                   3563:     if (!ValidShortVarname(startc, *pp)) {
                   3564:        (*pp)++;
                   3565:        *out_FALSE_val = var_Error;
                   3566:        *out_FALSE_res = VPR_PARSE_MSG;
                   3567:        return FALSE;
                   3568:     }
                   3569:
                   3570:     name[0] = startc;
                   3571:     name[1] = '\0';
                   3572:     v = VarFind(name, ctxt, TRUE);
                   3573:     if (v == NULL) {
                   3574:        *pp += 2;
                   3575:
                   3576:        *out_FALSE_val = UndefinedShortVarValue(startc, ctxt, eflags);
                   3577:        if (DEBUG(LINT) && *out_FALSE_val == var_Error) {
                   3578:            Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", name);
                   3579:            *out_FALSE_res = VPR_UNDEF_MSG;
                   3580:            return FALSE;
                   3581:        }
                   3582:        *out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF_SILENT : VPR_OK;
                   3583:        return FALSE;
                   3584:     }
                   3585:
                   3586:     *out_TRUE_var = v;
                   3587:     return TRUE;
                   3588: }
                   3589:
1.623     rillig   3590: /* Parse a long variable name enclosed in braces or parentheses such as $(VAR)
                   3591:  * or ${VAR}, up to the closing brace or parenthesis, or in the case of
                   3592:  * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
                   3593:  * Return whether to continue parsing. */
                   3594: static Boolean
                   3595: ParseVarnameLong(
1.624     rillig   3596:        const char **pp,
                   3597:        char startc,
                   3598:        GNode *ctxt,
                   3599:        VarEvalFlags eflags,
                   3600:
                   3601:        VarParseResult *out_FALSE_res,
                   3602:        const char **out_FALSE_val,
                   3603:        void **out_FALSE_freePtr,
                   3604:
                   3605:        char *out_TRUE_endc,
                   3606:        const char **out_TRUE_p,
                   3607:        Var **out_TRUE_v,
                   3608:        Boolean *out_TRUE_haveModifier,
                   3609:        const char **out_TRUE_extraModifiers,
                   3610:        Boolean *out_TRUE_dynamic,
                   3611:        VarExprFlags *out_TRUE_exprFlags
1.623     rillig   3612: ) {
                   3613:     size_t namelen;
                   3614:     char *varname;
                   3615:     Var *v;
                   3616:     Boolean haveModifier;
                   3617:     Boolean dynamic = FALSE;
                   3618:
                   3619:     const char *const start = *pp;
                   3620:     char endc = startc == '(' ? ')' : '}';
                   3621:
                   3622:     const char *p = start + 2;
                   3623:     varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen);
                   3624:
                   3625:     if (*p == ':') {
                   3626:        haveModifier = TRUE;
                   3627:     } else if (*p == endc) {
                   3628:        haveModifier = FALSE;
                   3629:     } else {
                   3630:        Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname);
                   3631:        *pp = p;
                   3632:        free(varname);
                   3633:        *out_FALSE_val = var_Error;
                   3634:        *out_FALSE_res = VPR_PARSE_MSG;
                   3635:        return FALSE;
                   3636:     }
                   3637:
                   3638:     v = VarFind(varname, ctxt, TRUE);
                   3639:
                   3640:     /* At this point, p points just after the variable name,
                   3641:      * either at ':' or at endc. */
                   3642:
                   3643:     /*
                   3644:      * Check also for bogus D and F forms of local variables since we're
                   3645:      * in a local context and the name is the right length.
                   3646:      */
                   3647:     if (v == NULL && ctxt != VAR_CMDLINE && ctxt != VAR_GLOBAL &&
                   3648:        namelen == 2 && (varname[1] == 'F' || varname[1] == 'D') &&
                   3649:        strchr("@%?*!<>", varname[0]) != NULL)
                   3650:     {
                   3651:        /*
                   3652:         * Well, it's local -- go look for it.
                   3653:         */
                   3654:        char name[] = { varname[0], '\0' };
                   3655:        v = VarFind(name, ctxt, 0);
                   3656:
                   3657:        if (v != NULL) {
                   3658:            if (varname[1] == 'D') {
                   3659:                *out_TRUE_extraModifiers = "H:";
                   3660:            } else { /* F */
                   3661:                *out_TRUE_extraModifiers = "T:";
                   3662:            }
                   3663:        }
                   3664:     }
                   3665:
                   3666:     if (v == NULL) {
1.626     rillig   3667:        /* Defer expansion of dynamic variables if they appear in non-local
                   3668:         * context since they are not defined there. */
                   3669:        dynamic = VarnameIsDynamic(varname, namelen) &&
                   3670:                  (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL);
1.623     rillig   3671:
                   3672:        if (!haveModifier) {
                   3673:            p++;                /* skip endc */
                   3674:            *pp = p;
                   3675:            if (dynamic) {
                   3676:                char *pstr = bmake_strsedup(start, p);
                   3677:                free(varname);
                   3678:                *out_FALSE_res = VPR_OK;
                   3679:                *out_FALSE_freePtr = pstr;
                   3680:                *out_FALSE_val = pstr;
                   3681:                return FALSE;
                   3682:            }
                   3683:
                   3684:            if ((eflags & VARE_UNDEFERR) && (eflags & VARE_WANTRES) &&
                   3685:                DEBUG(LINT))
                   3686:            {
                   3687:                Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined",
                   3688:                            varname);
                   3689:                free(varname);
                   3690:                *out_FALSE_res = VPR_UNDEF_MSG;
                   3691:                *out_FALSE_val = var_Error;
                   3692:                return FALSE;
                   3693:            }
                   3694:
                   3695:            if (eflags & VARE_UNDEFERR) {
                   3696:                free(varname);
                   3697:                *out_FALSE_res = VPR_UNDEF_SILENT;
                   3698:                *out_FALSE_val = var_Error;
                   3699:                return FALSE;
                   3700:            }
                   3701:
                   3702:            free(varname);
                   3703:            *out_FALSE_res = VPR_OK;
                   3704:            *out_FALSE_val = varUndefined;
                   3705:            return FALSE;
                   3706:        }
                   3707:
                   3708:        /* The variable expression is based on an undefined variable.
                   3709:         * Nevertheless it needs a Var, for modifiers that access the
                   3710:         * variable name, such as :L or :?.
                   3711:         *
                   3712:         * Most modifiers leave this expression in the "undefined" state
                   3713:         * (VEF_UNDEF), only a few modifiers like :D, :U, :L, :P turn this
                   3714:         * undefined expression into a defined expression (VEF_DEF).
                   3715:         *
                   3716:         * At the end, after applying all modifiers, if the expression
                   3717:         * is still undefined, Var_Parse will return an empty string
                   3718:         * instead of the actually computed value. */
                   3719:        v = VarNew(varname, varname, "", 0);
                   3720:        *out_TRUE_exprFlags = VEF_UNDEF;
                   3721:     } else
                   3722:        free(varname);
                   3723:
                   3724:     *out_TRUE_endc = endc;
                   3725:     *out_TRUE_p = p;
                   3726:     *out_TRUE_v = v;
                   3727:     *out_TRUE_haveModifier = haveModifier;
                   3728:     *out_TRUE_dynamic = dynamic;
                   3729:     return TRUE;
                   3730: }
                   3731:
1.108     sjg      3732: /*-
                   3733:  *-----------------------------------------------------------------------
                   3734:  * Var_Parse --
1.503     rillig   3735:  *     Given the start of a variable expression (such as $v, $(VAR),
1.328     rillig   3736:  *     ${VAR:Mpattern}), extract the variable name, possibly some
                   3737:  *     modifiers and find its value by applying the modifiers to the
                   3738:  *     original value.
1.108     sjg      3739:  *
1.579     rillig   3740:  *     When parsing a condition in ParseEmptyArg, pp may also point to
                   3741:  *     the "y" of "empty(VARNAME:Modifiers)", which is syntactically
                   3742:  *     identical.
                   3743:  *
1.108     sjg      3744:  * Input:
                   3745:  *     str             The string to parse
                   3746:  *     ctxt            The context for the variable
1.625     rillig   3747:  *     flags           Select the exact details of parsing
                   3748:  *     out_val_freeIt  Must be freed by the caller after using out_val
1.108     sjg      3749:  *
                   3750:  * Results:
1.478     rillig   3751:  *     Returns the value of the variable expression, never NULL.
1.536     rillig   3752:  *     Returns var_Error if there was a parse error and VARE_UNDEFERR was
                   3753:  *     set.
                   3754:  *     Returns varUndefined if there was an undefined variable and
                   3755:  *     VARE_UNDEFERR was not set.
                   3756:  *
                   3757:  *     Parsing should continue at *pp.
                   3758:  *     TODO: Document the value of *pp on parse errors.  It might be advanced
                   3759:  *     by 0, or +1, or the index of the parse error, or the guessed end of the
1.491     rillig   3760:  *     variable expression.
                   3761:  *
                   3762:  *     If var_Error is returned, a diagnostic may or may not have been
                   3763:  *     printed. XXX: This is inconsistent.
                   3764:  *
1.536     rillig   3765:  *     If varUndefined is returned, a diagnostic may or may not have been
                   3766:  *     printed. XXX: This is inconsistent.
1.455     rillig   3767:  *
1.625     rillig   3768:  *     After using the returned value, *out_val_freeIt must be freed,
                   3769:  *     preferably using bmake_free since it is NULL in most cases.
1.108     sjg      3770:  *
                   3771:  * Side Effects:
1.429     rillig   3772:  *     Any effects from the modifiers, such as :!cmd! or ::=value.
1.108     sjg      3773:  *-----------------------------------------------------------------------
                   3774:  */
1.514     rillig   3775: /* coverity[+alloc : arg-*4] */
1.526     rillig   3776: VarParseResult
1.514     rillig   3777: Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags,
1.625     rillig   3778:          const char **out_val, void **out_val_freeIt)
1.108     sjg      3779: {
1.498     rillig   3780:     const char *const start = *pp;
                   3781:     const char *p;
1.546     rillig   3782:     Boolean haveModifier;      /* TRUE if have modifiers for the variable */
                   3783:     char startc;               /* Starting character if variable in parens
1.401     rillig   3784:                                 * or braces */
1.546     rillig   3785:     char endc;                 /* Ending character if variable in parens
1.108     sjg      3786:                                 * or braces */
1.546     rillig   3787:     Boolean dynamic;           /* TRUE if the variable is local and we're
1.108     sjg      3788:                                 * expanding it in a non-local context. This
                   3789:                                 * is done to support dynamic sources. The
1.503     rillig   3790:                                 * result is just the expression, unaltered */
1.412     rillig   3791:     const char *extramodifiers;
                   3792:     Var *v;
                   3793:     char *nstr;
1.436     rillig   3794:     char eflags_str[VarEvalFlags_ToStringSize];
1.527     rillig   3795:     VarExprFlags exprFlags = 0;
1.432     rillig   3796:
1.626     rillig   3797:     VAR_DEBUG2("Var_Parse: %s with %s\n", start,
1.547     rillig   3798:               Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags,
                   3799:                                  VarEvalFlags_ToStringSpecs));
1.1       cgd      3800:
1.625     rillig   3801:     *out_val_freeIt = NULL;
1.412     rillig   3802:     extramodifiers = NULL;     /* extra modifiers to apply first */
1.108     sjg      3803:     dynamic = FALSE;
1.1       cgd      3804:
1.510     martin   3805:     /* Appease GCC, which thinks that the variable might not be
1.473     rillig   3806:      * initialized. */
                   3807:     endc = '\0';
                   3808:
1.497     rillig   3809:     startc = start[1];
1.521     rillig   3810:     if (startc != '(' && startc != '{') {
1.623     rillig   3811:        VarParseResult res;
1.624     rillig   3812:        if (!ParseVarnameShort(startc, pp, ctxt, eflags, &res, out_val, &v))
1.622     rillig   3813:            return res;
                   3814:        haveModifier = FALSE;
                   3815:        p = start + 1;
1.123     apb      3816:     } else {
1.623     rillig   3817:        VarParseResult res;
                   3818:        if (!ParseVarnameLong(pp, startc, ctxt, eflags,
1.625     rillig   3819:                              &res, out_val, out_val_freeIt,
1.623     rillig   3820:                              &endc, &p, &v, &haveModifier, &extramodifiers,
                   3821:                              &dynamic, &exprFlags))
                   3822:            return res;
1.108     sjg      3823:     }
                   3824:
1.615     rillig   3825:     if (v->flags & VAR_IN_USE)
1.188     joerg    3826:        Fatal("Variable %s is recursive.", v->name);
1.401     rillig   3827:
1.188     joerg    3828:     /*
                   3829:      * Before doing any modification, we have to make sure the value
                   3830:      * has been fully expanded. If it looks like recursion might be
                   3831:      * necessary (there's a dollar sign somewhere in the variable's value)
                   3832:      * we just call Var_Subst to do any other substitutions that are
                   3833:      * necessary. Note that the value returned by Var_Subst will have
                   3834:      * been dynamically-allocated, so it will need freeing when we
                   3835:      * return.
                   3836:      */
1.433     rillig   3837:     nstr = Buf_GetAll(&v->val, NULL);
1.507     rillig   3838:     if (strchr(nstr, '$') != NULL && (eflags & VARE_WANTRES)) {
1.571     rillig   3839:        VarEvalFlags nested_eflags = eflags;
                   3840:        if (DEBUG(LINT))
                   3841:            nested_eflags &= ~(unsigned)VARE_UNDEFERR;
1.615     rillig   3842:        v->flags |= VAR_IN_USE;
1.533     rillig   3843:        (void)Var_Subst(nstr, ctxt, nested_eflags, &nstr);
1.615     rillig   3844:        v->flags &= ~(unsigned)VAR_IN_USE;
1.533     rillig   3845:        /* TODO: handle errors */
1.625     rillig   3846:        *out_val_freeIt = nstr;
1.188     joerg    3847:     }
1.187     christos 3848:
1.447     rillig   3849:     if (haveModifier || extramodifiers != NULL) {
1.191     dholland 3850:        void *extraFree;
1.108     sjg      3851:
1.191     dholland 3852:        extraFree = NULL;
                   3853:        if (extramodifiers != NULL) {
1.367     rillig   3854:            const char *em = extramodifiers;
                   3855:            nstr = ApplyModifiers(&em, nstr, '(', ')',
1.527     rillig   3856:                                  v, &exprFlags, ctxt, eflags, &extraFree);
1.191     dholland 3857:        }
                   3858:
                   3859:        if (haveModifier) {
1.240     rillig   3860:            /* Skip initial colon. */
1.497     rillig   3861:            p++;
1.191     dholland 3862:
1.497     rillig   3863:            nstr = ApplyModifiers(&p, nstr, startc, endc,
1.625     rillig   3864:                                  v, &exprFlags, ctxt, eflags, out_val_freeIt);
1.240     rillig   3865:            free(extraFree);
1.191     dholland 3866:        } else {
1.625     rillig   3867:            *out_val_freeIt = extraFree;
1.191     dholland 3868:        }
1.119     sjg      3869:     }
1.438     rillig   3870:
1.519     rillig   3871:     if (*p != '\0')            /* Skip past endc if possible. */
                   3872:        p++;
                   3873:
                   3874:     *pp = p;
1.15      christos 3875:
1.1       cgd      3876:     if (v->flags & VAR_FROM_ENV) {
1.571     rillig   3877:        /* Free the environment variable now since we own it,
                   3878:         * but don't free the variable value if it will be returned. */
1.499     rillig   3879:        Boolean keepValue = nstr == Buf_GetAll(&v->val, NULL);
                   3880:        if (keepValue)
1.625     rillig   3881:            *out_val_freeIt = nstr;
1.499     rillig   3882:        (void)VarFreeEnv(v, !keepValue);
                   3883:
1.527     rillig   3884:     } else if (exprFlags & VEF_UNDEF) {
                   3885:        if (!(exprFlags & VEF_DEF)) {
1.625     rillig   3886:            if (*out_val_freeIt != NULL) {
                   3887:                free(*out_val_freeIt);
                   3888:                *out_val_freeIt = NULL;
1.40      sjg      3889:            }
                   3890:            if (dynamic) {
1.519     rillig   3891:                nstr = bmake_strsedup(start, p);
1.625     rillig   3892:                *out_val_freeIt = nstr;
1.40      sjg      3893:            } else {
1.528     rillig   3894:                /* The expression is still undefined, therefore discard the
1.536     rillig   3895:                 * actual value and return an error marker instead. */
                   3896:                nstr = (eflags & VARE_UNDEFERR) ? var_Error : varUndefined;
1.40      sjg      3897:            }
1.34      christos 3898:        }
1.433     rillig   3899:        if (nstr != Buf_GetAll(&v->val, NULL))
1.146     dsl      3900:            Buf_Destroy(&v->val, TRUE);
1.570     rillig   3901:        free(v->name_freeIt);
1.98      christos 3902:        free(v);
1.1       cgd      3903:     }
1.514     rillig   3904:     *out_val = nstr;
1.526     rillig   3905:     return VPR_UNKNOWN;
1.1       cgd      3906: }
                   3907:
1.484     rillig   3908: /* Substitute for all variables in the given string in the given context.
                   3909:  *
                   3910:  * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined
                   3911:  * variable is encountered.
                   3912:  *
                   3913:  * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=,
                   3914:  * :sh or !cmd! take place.
1.1       cgd      3915:  *
1.70      wiz      3916:  * Input:
                   3917:  *     str             the string which to substitute
                   3918:  *     ctxt            the context wherein to find variables
1.333     rillig   3919:  *     eflags          VARE_UNDEFERR   if undefineds are an error
1.259     rillig   3920:  *                     VARE_WANTRES    if we actually want the result
                   3921:  *                     VARE_ASSIGN     if we are in a := assignment
1.70      wiz      3922:  *
1.1       cgd      3923:  * Results:
                   3924:  *     The resulting string.
                   3925:  */
1.533     rillig   3926: VarParseResult
                   3927: Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res)
1.1       cgd      3928: {
1.537     rillig   3929:     const char *p = str;
1.401     rillig   3930:     Buffer buf;                        /* Buffer for forming things */
1.1       cgd      3931:
1.401     rillig   3932:     /* Set true if an error has already been reported,
                   3933:      * to prevent a plethora of messages when recursing */
                   3934:     static Boolean errorReported;
1.412     rillig   3935:
1.433     rillig   3936:     Buf_Init(&buf, 0);
1.1       cgd      3937:     errorReported = FALSE;
                   3938:
1.537     rillig   3939:     while (*p != '\0') {
                   3940:        if (p[0] == '$' && p[1] == '$') {
1.567     rillig   3941:            /* A dollar sign may be escaped with another dollar sign. */
1.333     rillig   3942:            if (save_dollars && (eflags & VARE_ASSIGN))
1.381     rillig   3943:                Buf_AddByte(&buf, '$');
                   3944:            Buf_AddByte(&buf, '$');
1.537     rillig   3945:            p += 2;
                   3946:        } else if (*p != '$') {
1.1       cgd      3947:            /*
                   3948:             * Skip as many characters as possible -- either to the end of
1.503     rillig   3949:             * the string or to the next dollar sign (variable expression).
1.1       cgd      3950:             */
1.537     rillig   3951:            const char *plainStart = p;
1.1       cgd      3952:
1.537     rillig   3953:            for (p++; *p != '$' && *p != '\0'; p++)
1.5       cgd      3954:                continue;
1.537     rillig   3955:            Buf_AddBytesBetween(&buf, plainStart, p);
1.1       cgd      3956:        } else {
1.537     rillig   3957:            const char *nested_p = p;
1.406     rillig   3958:            void *freeIt;
1.514     rillig   3959:            const char *val;
1.537     rillig   3960:            (void)Var_Parse(&nested_p, ctxt, eflags, &val, &freeIt);
1.514     rillig   3961:            /* TODO: handle errors */
1.1       cgd      3962:
1.536     rillig   3963:            if (val == var_Error || val == varUndefined) {
1.1       cgd      3964:                /*
                   3965:                 * If performing old-time variable substitution, skip over
                   3966:                 * the variable and continue with the substitution. Otherwise,
                   3967:                 * store the dollar sign and advance str so we continue with
                   3968:                 * the string...
                   3969:                 */
                   3970:                if (oldVars) {
1.537     rillig   3971:                    p = nested_p;
1.333     rillig   3972:                } else if ((eflags & VARE_UNDEFERR) || val == var_Error) {
1.1       cgd      3973:                    /*
                   3974:                     * If variable is undefined, complain and skip the
                   3975:                     * variable. The complaint will stop us from doing anything
                   3976:                     * when the file is parsed.
                   3977:                     */
                   3978:                    if (!errorReported) {
1.231     rillig   3979:                        Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",
1.537     rillig   3980:                                    (int)(size_t)(nested_p - p), p);
1.1       cgd      3981:                    }
1.537     rillig   3982:                    p = nested_p;
1.1       cgd      3983:                    errorReported = TRUE;
                   3984:                } else {
1.538     rillig   3985:                    /* Copy the initial '$' of the undefined expression,
                   3986:                     * thereby deferring expansion of the expression, but
                   3987:                     * expand nested expressions if already possible.
                   3988:                     * See unit-tests/varparse-undef-partial.mk. */
1.537     rillig   3989:                    Buf_AddByte(&buf, *p);
                   3990:                    p++;
1.1       cgd      3991:                }
                   3992:            } else {
1.537     rillig   3993:                p = nested_p;
1.534     rillig   3994:                Buf_AddStr(&buf, val);
1.104     christos 3995:            }
1.196     christos 3996:            free(freeIt);
                   3997:            freeIt = NULL;
1.1       cgd      3998:        }
                   3999:     }
1.15      christos 4000:
1.533     rillig   4001:     *out_res = Buf_DestroyCompact(&buf);
                   4002:     return VPR_OK;
1.1       cgd      4003: }
                   4004:
1.572     rillig   4005: /* Initialize the variables module. */
1.1       cgd      4006: void
1.70      wiz      4007: Var_Init(void)
1.1       cgd      4008: {
1.184     sjg      4009:     VAR_INTERNAL = Targ_NewGN("Internal");
1.92      christos 4010:     VAR_GLOBAL = Targ_NewGN("Global");
1.594     rillig   4011:     VAR_CMDLINE = Targ_NewGN("Command");
1.6       jtc      4012: }
                   4013:
1.572     rillig   4014: /* Clean up the variables module. */
1.6       jtc      4015: void
1.70      wiz      4016: Var_End(void)
1.6       jtc      4017: {
1.286     sjg      4018:     Var_Stats();
                   4019: }
                   4020:
                   4021: void
                   4022: Var_Stats(void)
                   4023: {
1.588     rillig   4024:     HashTable_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL");
1.1       cgd      4025: }
1.15      christos 4026:
1.573     rillig   4027: /* Print all variables in a context, sorted by name. */
1.5       cgd      4028: void
1.70      wiz      4029: Var_Dump(GNode *ctxt)
1.1       cgd      4030: {
1.585     rillig   4031:     Vector /* of const char * */ vec;
1.575     rillig   4032:     HashIter hi;
1.573     rillig   4033:     size_t i;
1.585     rillig   4034:     const char **varnames;
1.573     rillig   4035:
1.585     rillig   4036:     Vector_Init(&vec, sizeof(const char *));
1.575     rillig   4037:
                   4038:     HashIter_Init(&hi, &ctxt->context);
1.603     rillig   4039:     while (HashIter_Next(&hi) != NULL)
                   4040:        *(const char **)Vector_Push(&vec) = hi.entry->key;
1.585     rillig   4041:     varnames = vec.items;
1.573     rillig   4042:
1.585     rillig   4043:     qsort(varnames, vec.len, sizeof varnames[0], str_cmp_asc);
1.573     rillig   4044:
1.585     rillig   4045:     for (i = 0; i < vec.len; i++) {
1.599     rillig   4046:        const char *varname = varnames[i];
                   4047:        Var *var = HashTable_FindValue(&ctxt->context, varname);
1.573     rillig   4048:        debug_printf("%-16s = %s\n", varname, Buf_GetAll(&var->val, NULL));
                   4049:     }
                   4050:
1.585     rillig   4051:     Vector_Done(&vec);
1.1       cgd      4052: }

CVSweb <webmaster@jp.NetBSD.org>