[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.948

1.948   ! rillig      1: /*     $NetBSD: var.c,v 1.947 2021/08/14 13:11:33 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:  *
1.798     rillig     83:  *     Var_Set
                     84:  *     Var_SetExpand
                     85:  *                     Set the value of the variable, creating it if
1.592     rillig     86:  *                     necessary.
                     87:  *
1.794     rillig     88:  *     Var_Append
                     89:  *     Var_AppendExpand
                     90:  *                     Append more characters to the variable, creating it if
1.592     rillig     91:  *                     necessary. A space is placed between the old value and
                     92:  *                     the new one.
1.1       cgd        93:  *
1.796     rillig     94:  *     Var_Exists
                     95:  *     Var_ExistsExpand
                     96:  *                     See if a variable exists.
1.1       cgd        97:  *
1.592     rillig     98:  *     Var_Value       Return the unexpanded value of a variable, or NULL if
                     99:  *                     the variable is undefined.
                    100:  *
                    101:  *     Var_Subst       Substitute all variable expressions in a string.
                    102:  *
                    103:  *     Var_Parse       Parse a variable expression such as ${VAR:Mpattern}.
1.1       cgd       104:  *
1.797     rillig    105:  *     Var_Delete
                    106:  *     Var_DeleteExpand
                    107:  *                     Delete a variable.
1.1       cgd       108:  *
1.725     rillig    109:  *     Var_ReexportVars
                    110:  *                     Export some or even all variables to the environment
1.592     rillig    111:  *                     of this process and its child processes.
1.1       cgd       112:  *
1.592     rillig    113:  *     Var_Export      Export the variable to the environment of this process
                    114:  *                     and its child processes.
1.1       cgd       115:  *
1.592     rillig    116:  *     Var_UnExport    Don't export the variable anymore.
1.1       cgd       117:  *
                    118:  * Debugging:
1.592     rillig    119:  *     Var_Stats       Print out hashing statistics if in -dh mode.
                    120:  *
1.802     rillig    121:  *     Var_Dump        Print out all variables defined in the given scope.
1.1       cgd       122:  *
1.827     rillig    123:  * XXX: There's a lot of almost duplicate code in these functions that only
                    124:  *  differs in subtle details that are not mentioned in the manual page.
1.1       cgd       125:  */
                    126:
1.630     rillig    127: #include <sys/stat.h>
1.31      gwr       128: #ifndef NO_REGEX
1.630     rillig    129: #include <sys/types.h>
                    130: #include <regex.h>
1.17      christos  131: #endif
1.631     rillig    132: #include <errno.h>
1.630     rillig    133: #include <inttypes.h>
                    134: #include <limits.h>
                    135: #include <time.h>
                    136:
                    137: #include "make.h"
                    138: #include "dir.h"
                    139: #include "job.h"
                    140: #include "metachar.h"
1.1       cgd       141:
1.512     rillig    142: /*     "@(#)var.c      8.3 (Berkeley) 3/19/94" */
1.948   ! rillig    143: MAKE_RCSID("$NetBSD: var.c,v 1.947 2021/08/14 13:11:33 rillig Exp $");
1.228     rillig    144:
1.778     rillig    145: /*
                    146:  * Variables are defined using one of the VAR=value assignments.  Their
1.570     rillig    147:  * value can be queried by expressions such as $V, ${VAR}, or with modifiers
                    148:  * such as ${VAR:S,from,to,g:Q}.
                    149:  *
1.802     rillig    150:  * There are 3 kinds of variables: scope variables, environment variables,
1.570     rillig    151:  * undefined variables.
                    152:  *
1.802     rillig    153:  * Scope variables are stored in a GNode.scope.  The only way to undefine
                    154:  * a scope variable is using the .undef directive.  In particular, it must
1.570     rillig    155:  * not be possible to undefine a variable during the evaluation of an
                    156:  * expression, or Var.name might point nowhere.
                    157:  *
                    158:  * Environment variables are temporary.  They are returned by VarFind, and
                    159:  * after using them, they must be freed using VarFreeEnv.
                    160:  *
                    161:  * Undefined variables occur during evaluation of variable expressions such
                    162:  * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
                    163:  */
1.1       cgd       164: typedef struct Var {
1.703     rillig    165:        /*
                    166:         * The name of the variable, once set, doesn't change anymore.
1.802     rillig    167:         * For scope variables, it aliases the corresponding HashEntry name.
1.703     rillig    168:         * For environment and undefined variables, it is allocated.
                    169:         */
1.711     rillig    170:        FStr name;
1.570     rillig    171:
1.703     rillig    172:        /* The unexpanded value of the variable. */
                    173:        Buffer val;
1.902     rillig    174:
                    175:        /* The variable came from the command line. */
                    176:        bool fromCmd: 1;
                    177:
                    178:        /*
                    179:         * The variable comes from the environment.
                    180:         * These variables are not registered in any GNode, therefore they
                    181:         * must be freed as soon as they are not used anymore.
                    182:         */
                    183:        bool fromEnv: 1;
                    184:
                    185:        /*
                    186:         * The variable value cannot be changed anymore, and the variable
                    187:         * cannot be deleted.  Any attempts to do so are silently ignored,
                    188:         * they are logged with -dv though.
                    189:         *
                    190:         * See VAR_SET_READONLY.
                    191:         */
                    192:        bool readOnly: 1;
                    193:
                    194:        /*
                    195:        * The variable's value is currently being used by Var_Parse or
                    196:        * Var_Subst.  This marker is used to avoid endless recursion.
                    197:        */
                    198:        bool inUse: 1;
                    199:
                    200:        /*
                    201:         * The variable is exported to the environment, to be used by child
                    202:         * processes.
                    203:         */
                    204:        bool exported: 1;
                    205:
                    206:        /*
                    207:         * At the point where this variable was exported, it contained an
                    208:         * unresolved reference to another variable.  Before any child
                    209:         * process is started, it needs to be exported again, in the hope
                    210:         * that the referenced variable can then be resolved.
                    211:         */
                    212:        bool reexport: 1;
1.417     rillig    213: } Var;
1.1       cgd       214:
1.710     rillig    215: /*
1.830     rillig    216:  * Exporting variables is expensive and may leak memory, so skip it if we
                    217:  * can.
                    218:  *
                    219:  * To avoid this, it might be worth encapsulating the environment variables
                    220:  * in a separate data structure called EnvVars.
1.710     rillig    221:  */
                    222: typedef enum VarExportedMode {
                    223:        VAR_EXPORTED_NONE,
                    224:        VAR_EXPORTED_SOME,
                    225:        VAR_EXPORTED_ALL
                    226: } VarExportedMode;
                    227:
1.713     rillig    228: typedef enum UnexportWhat {
1.830     rillig    229:        /* Unexport the variables given by name. */
1.713     rillig    230:        UNEXPORT_NAMED,
1.830     rillig    231:        /*
                    232:         * Unexport all globals previously exported, but keep the environment
                    233:         * inherited from the parent.
                    234:         */
1.713     rillig    235:        UNEXPORT_ALL,
1.830     rillig    236:        /*
                    237:         * Unexport all globals previously exported and clear the environment
                    238:         * inherited from the parent.
                    239:         */
1.713     rillig    240:        UNEXPORT_ENV
                    241: } UnexportWhat;
                    242:
1.261     rillig    243: /* Flags for pattern matching in the :S and :C modifiers */
1.927     rillig    244: typedef struct PatternFlags {
1.903     rillig    245:        bool subGlobal: 1;      /* 'g': replace as often as possible */
                    246:        bool subOnce: 1;        /* '1': replace only once */
                    247:        bool anchorStart: 1;    /* '^': match only at start of word */
                    248:        bool anchorEnd: 1;      /* '$': match only at end of word */
1.927     rillig    249: } PatternFlags;
1.16      christos  250:
1.830     rillig    251: /* SepBuf builds a string from words interleaved with separators. */
1.710     rillig    252: typedef struct SepBuf {
                    253:        Buffer buf;
1.895     rillig    254:        bool needSep;
1.710     rillig    255:        /* Usually ' ', but see the ':ts' modifier. */
                    256:        char sep;
                    257: } SepBuf;
                    258:
                    259:
                    260: /*
                    261:  * This lets us tell if we have replaced the original environ
                    262:  * (which we cannot free).
                    263:  */
                    264: char **savedEnv = NULL;
                    265:
1.778     rillig    266: /*
                    267:  * Special return value for Var_Parse, indicating a parse error.  It may be
1.710     rillig    268:  * caused by an undefined variable, a syntax error in a modifier or
1.778     rillig    269:  * something entirely different.
                    270:  */
1.710     rillig    271: char var_Error[] = "";
                    272:
1.778     rillig    273: /*
                    274:  * Special return value for Var_Parse, indicating an undefined variable in
1.917     rillig    275:  * a case where VARE_UNDEFERR is not set.  This undefined variable is
1.710     rillig    276:  * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
1.778     rillig    277:  * be deferred until it is defined in an actual target.
1.830     rillig    278:  *
1.917     rillig    279:  * See VARE_EVAL_KEEP_UNDEF.
1.778     rillig    280:  */
1.710     rillig    281: static char varUndefined[] = "";
                    282:
                    283: /*
                    284:  * Traditionally this make consumed $$ during := like any other expansion.
                    285:  * Other make's do not, and this make follows straight since 2016-01-09.
                    286:  *
1.895     rillig    287:  * This knob allows controlling the behavior:
                    288:  *     false to consume $$ during := assignment.
                    289:  *     true to preserve $$ during := assignment.
1.710     rillig    290:  */
                    291: #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
1.895     rillig    292: static bool save_dollars = true;
1.710     rillig    293:
                    294: /*
1.807     rillig    295:  * A scope collects variable names and their values.
                    296:  *
                    297:  * The main scope is SCOPE_GLOBAL, which contains the variables that are set
                    298:  * in the makefiles.  SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and
                    299:  * contains some internal make variables.  These internal variables can thus
                    300:  * be overridden, they can also be restored by undefining the overriding
                    301:  * variable.
                    302:  *
                    303:  * SCOPE_CMDLINE contains variables from the command line arguments.  These
                    304:  * override variables from SCOPE_GLOBAL.
                    305:  *
                    306:  * There is no scope for environment variables, these are generated on-the-fly
                    307:  * whenever they are referenced.  If there were such a scope, each change to
                    308:  * environment variables would have to be reflected in that scope, which may
                    309:  * be simpler or more complex than the current implementation.
                    310:  *
                    311:  * Each target has its own scope, containing the 7 target-local variables
                    312:  * .TARGET, .ALLSRC, etc.  No other variables are in these scopes.
                    313:  */
                    314:
                    315: GNode *SCOPE_CMDLINE;
                    316: GNode *SCOPE_GLOBAL;
                    317: GNode *SCOPE_INTERNAL;
1.710     rillig    318:
                    319: static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
                    320:
1.906     rillig    321: static const char *VarEvalMode_Name[] = {
                    322:        "parse-only",
                    323:        "eval",
                    324:        "eval-defined",
                    325:        "eval-keep-dollar",
                    326:        "eval-keep-undefined",
                    327:        "eval-keep-dollar-and-undefined",
                    328: };
1.711     rillig    329:
1.904     rillig    330:
1.569     rillig    331: static Var *
1.901     rillig    332: VarNew(FStr name, const char *value, bool fromEnv, bool readOnly)
1.569     rillig    333: {
1.703     rillig    334:        size_t value_len = strlen(value);
                    335:        Var *var = bmake_malloc(sizeof *var);
1.744     rillig    336:        var->name = name;
1.703     rillig    337:        Buf_InitSize(&var->val, value_len + 1);
                    338:        Buf_AddBytes(&var->val, value, value_len);
1.902     rillig    339:        var->fromCmd = false;
                    340:        var->fromEnv = fromEnv;
                    341:        var->readOnly = readOnly;
                    342:        var->inUse = false;
                    343:        var->exported = false;
                    344:        var->reexport = false;
1.703     rillig    345:        return var;
1.569     rillig    346: }
                    347:
1.916     rillig    348: static Substring
                    349: CanonicalVarname(Substring name)
1.1       cgd       350: {
1.916     rillig    351:
                    352:        if (!(Substring_Length(name) > 0 && name.start[0] == '.'))
                    353:                return name;
                    354:
                    355:        if (Substring_Equals(name, ".ALLSRC"))
                    356:                return Substring_InitStr(ALLSRC);
                    357:        if (Substring_Equals(name, ".ARCHIVE"))
                    358:                return Substring_InitStr(ARCHIVE);
                    359:        if (Substring_Equals(name, ".IMPSRC"))
                    360:                return Substring_InitStr(IMPSRC);
                    361:        if (Substring_Equals(name, ".MEMBER"))
                    362:                return Substring_InitStr(MEMBER);
                    363:        if (Substring_Equals(name, ".OODATE"))
                    364:                return Substring_InitStr(OODATE);
                    365:        if (Substring_Equals(name, ".PREFIX"))
                    366:                return Substring_InitStr(PREFIX);
                    367:        if (Substring_Equals(name, ".TARGET"))
                    368:                return Substring_InitStr(TARGET);
                    369:
                    370:        if (Substring_Equals(name, ".SHELL") && shellPath == NULL)
                    371:                Shell_Init();
1.242     rillig    372:
1.703     rillig    373:        /* GNU make has an additional alias $^ == ${.ALLSRC}. */
1.580     rillig    374:
1.703     rillig    375:        return name;
1.580     rillig    376: }
                    377:
1.587     rillig    378: static Var *
1.916     rillig    379: GNode_FindVar(GNode *scope, Substring varname, unsigned int hash)
1.587     rillig    380: {
1.916     rillig    381:        return HashTable_FindValueBySubstringHash(&scope->vars, varname, hash);
1.587     rillig    382: }
                    383:
1.778     rillig    384: /*
1.802     rillig    385:  * Find the variable in the scope, and maybe in other scopes as well.
1.580     rillig    386:  *
                    387:  * Input:
1.607     rillig    388:  *     name            name to find, is not expanded any further
1.802     rillig    389:  *     scope           scope in which to look first
1.895     rillig    390:  *     elsewhere       true to look in other scopes as well
1.580     rillig    391:  *
                    392:  * Results:
1.605     rillig    393:  *     The found variable, or NULL if the variable does not exist.
                    394:  *     If the variable is an environment variable, it must be freed using
                    395:  *     VarFreeEnv after use.
1.580     rillig    396:  */
                    397: static Var *
1.916     rillig    398: VarFindSubstring(Substring name, GNode *scope, bool elsewhere)
1.580     rillig    399: {
1.703     rillig    400:        Var *var;
                    401:        unsigned int nameHash;
                    402:
1.830     rillig    403:        /* Replace '.TARGET' with '@', likewise for other local variables. */
1.703     rillig    404:        name = CanonicalVarname(name);
1.916     rillig    405:        nameHash = Hash_Substring(name);
1.580     rillig    406:
1.802     rillig    407:        var = GNode_FindVar(scope, name, nameHash);
1.703     rillig    408:        if (!elsewhere)
                    409:                return var;
1.160     christos  410:
1.802     rillig    411:        if (var == NULL && scope != SCOPE_CMDLINE)
1.801     rillig    412:                var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
1.1       cgd       413:
1.802     rillig    414:        if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
1.801     rillig    415:                var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
1.802     rillig    416:                if (var == NULL && scope != SCOPE_INTERNAL) {
1.801     rillig    417:                        /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
                    418:                        var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
1.703     rillig    419:                }
1.184     sjg       420:        }
1.399     rillig    421:
1.703     rillig    422:        if (var == NULL) {
1.916     rillig    423:                FStr envName;
                    424:                const char *envValue;
1.703     rillig    425:
1.913     rillig    426:                /*
                    427:                 * TODO: try setting an environment variable with the empty
                    428:                 *  name, which should be technically possible, just to see
                    429:                 *  how make reacts.  All .for loops should be broken then.
                    430:                 */
1.916     rillig    431:                envName = Substring_Str(name);
                    432:                envValue = getenv(envName.str);
                    433:                if (envValue != NULL)
                    434:                        return VarNew(envName, envValue, true, false);
                    435:                FStr_Done(&envName);
1.1       cgd       436:
1.802     rillig    437:                if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
1.801     rillig    438:                        var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
1.802     rillig    439:                        if (var == NULL && scope != SCOPE_INTERNAL)
1.801     rillig    440:                                var = GNode_FindVar(SCOPE_INTERNAL, name,
1.703     rillig    441:                                    nameHash);
                    442:                        return var;
                    443:                }
1.399     rillig    444:
1.703     rillig    445:                return NULL;
1.1       cgd       446:        }
1.399     rillig    447:
1.703     rillig    448:        return var;
1.1       cgd       449: }
                    450:
1.916     rillig    451: /* TODO: Replace these calls with VarFindSubstring, as far as possible. */
                    452: static Var *
                    453: VarFind(const char *name, GNode *scope, bool elsewhere)
                    454: {
                    455:        return VarFindSubstring(Substring_InitStr(name), scope, elsewhere);
                    456: }
                    457:
1.883     rillig    458: /* If the variable is an environment variable, free it, including its value. */
1.837     rillig    459: static void
                    460: VarFreeEnv(Var *v)
1.105     christos  461: {
1.902     rillig    462:        if (!v->fromEnv)
1.837     rillig    463:                return;
1.605     rillig    464:
1.711     rillig    465:        FStr_Done(&v->name);
1.837     rillig    466:        Buf_Done(&v->val);
1.703     rillig    467:        free(v);
1.105     christos  468: }
                    469:
1.831     rillig    470: /* Add a new variable of the given name and value to the given scope. */
1.833     rillig    471: static Var *
1.831     rillig    472: VarAdd(const char *name, const char *value, GNode *scope, VarSetFlags flags)
1.1       cgd       473: {
1.802     rillig    474:        HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
1.831     rillig    475:        Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value,
1.901     rillig    476:            false, (flags & VAR_SET_READONLY) != 0);
1.703     rillig    477:        HashEntry_Set(he, v);
1.911     rillig    478:        DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, value);
1.833     rillig    479:        return v;
1.1       cgd       480: }
                    481:
1.736     rillig    482: /*
1.802     rillig    483:  * Remove a variable from a scope, freeing all related memory as well.
1.736     rillig    484:  * The variable name is kept as-is, it is not expanded.
                    485:  */
                    486: void
1.805     rillig    487: Var_Delete(GNode *scope, const char *varname)
1.736     rillig    488: {
1.802     rillig    489:        HashEntry *he = HashTable_FindEntry(&scope->vars, varname);
1.736     rillig    490:        Var *v;
                    491:
                    492:        if (he == NULL) {
1.802     rillig    493:                DEBUG2(VAR, "%s:delete %s (not found)\n", scope->name, varname);
1.736     rillig    494:                return;
                    495:        }
                    496:
1.802     rillig    497:        DEBUG2(VAR, "%s:delete %s\n", scope->name, varname);
1.831     rillig    498:        v = he->value;
1.902     rillig    499:        if (v->exported)
1.736     rillig    500:                unsetenv(v->name.str);
                    501:        if (strcmp(v->name.str, MAKE_EXPORTED) == 0)
                    502:                var_exportedVars = VAR_EXPORTED_NONE;
                    503:        assert(v->name.freeIt == NULL);
1.802     rillig    504:        HashTable_DeleteEntry(&scope->vars, he);
1.784     rillig    505:        Buf_Done(&v->val);
1.736     rillig    506:        free(v);
                    507: }
                    508:
1.778     rillig    509: /*
1.802     rillig    510:  * Remove a variable from a scope, freeing all related memory as well.
1.778     rillig    511:  * The variable name is expanded once.
                    512:  */
1.1       cgd       513: void
1.805     rillig    514: Var_DeleteExpand(GNode *scope, const char *name)
1.1       cgd       515: {
1.746     rillig    516:        FStr varname = FStr_InitRefer(name);
1.412     rillig    517:
1.746     rillig    518:        if (strchr(varname.str, '$') != NULL) {
                    519:                char *expanded;
1.801     rillig    520:                (void)Var_Subst(varname.str, SCOPE_GLOBAL, VARE_WANTRES,
1.746     rillig    521:                    &expanded);
1.703     rillig    522:                /* TODO: handle errors */
1.746     rillig    523:                varname = FStr_InitOwn(expanded);
1.703     rillig    524:        }
1.397     rillig    525:
1.805     rillig    526:        Var_Delete(scope, varname.str);
1.746     rillig    527:        FStr_Done(&varname);
1.1       cgd       528: }
                    529:
1.737     rillig    530: /*
1.762     rillig    531:  * Undefine one or more variables from the global scope.
                    532:  * The argument is expanded exactly once and then split into words.
1.737     rillig    533:  */
1.735     rillig    534: void
1.762     rillig    535: Var_Undef(const char *arg)
1.735     rillig    536: {
1.762     rillig    537:        VarParseResult vpr;
                    538:        char *expanded;
                    539:        Words varnames;
                    540:        size_t i;
                    541:
                    542:        if (arg[0] == '\0') {
                    543:                Parse_Error(PARSE_FATAL,
                    544:                    "The .undef directive requires an argument");
                    545:                return;
                    546:        }
1.735     rillig    547:
1.801     rillig    548:        vpr = Var_Subst(arg, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
1.762     rillig    549:        if (vpr != VPR_OK) {
1.737     rillig    550:                Parse_Error(PARSE_FATAL,
1.762     rillig    551:                    "Error in variable names to be undefined");
                    552:                return;
                    553:        }
                    554:
1.895     rillig    555:        varnames = Str_Words(expanded, false);
1.762     rillig    556:        if (varnames.len == 1 && varnames.words[0][0] == '\0')
                    557:                varnames.len = 0;
                    558:
                    559:        for (i = 0; i < varnames.len; i++) {
                    560:                const char *varname = varnames.words[i];
1.804     rillig    561:                Global_Delete(varname);
1.737     rillig    562:        }
1.735     rillig    563:
1.762     rillig    564:        Words_Free(varnames);
1.763     rillig    565:        free(expanded);
1.735     rillig    566: }
                    567:
1.895     rillig    568: static bool
1.598     rillig    569: MayExport(const char *name)
1.118     sjg       570: {
1.703     rillig    571:        if (name[0] == '.')
1.895     rillig    572:                return false;   /* skip internals */
1.703     rillig    573:        if (name[0] == '-')
1.895     rillig    574:                return false;   /* skip misnamed variables */
1.703     rillig    575:        if (name[1] == '\0') {
                    576:                /*
                    577:                 * A single char.
1.802     rillig    578:                 * If it is one of the variables that should only appear in
                    579:                 * local scope, skip it, else we can get Var_Subst
1.703     rillig    580:                 * into a loop.
                    581:                 */
                    582:                switch (name[0]) {
                    583:                case '@':
                    584:                case '%':
                    585:                case '*':
                    586:                case '!':
1.895     rillig    587:                        return false;
1.703     rillig    588:                }
1.118     sjg       589:        }
1.895     rillig    590:        return true;
1.598     rillig    591: }
                    592:
1.895     rillig    593: static bool
1.776     rillig    594: ExportVarEnv(Var *v)
                    595: {
                    596:        const char *name = v->name.str;
1.777     rillig    597:        char *val = v->val.data;
                    598:        char *expr;
1.776     rillig    599:
1.902     rillig    600:        if (v->exported && !v->reexport)
1.895     rillig    601:                return false;   /* nothing to do */
1.776     rillig    602:
1.777     rillig    603:        if (strchr(val, '$') == NULL) {
1.902     rillig    604:                if (!v->exported)
1.776     rillig    605:                        setenv(name, val, 1);
1.895     rillig    606:                return true;
1.776     rillig    607:        }
                    608:
1.902     rillig    609:        if (v->inUse) {
1.777     rillig    610:                /*
                    611:                 * We recursed while exporting in a child.
                    612:                 * This isn't going to end well, just skip it.
                    613:                 */
1.895     rillig    614:                return false;
1.777     rillig    615:        }
1.776     rillig    616:
1.777     rillig    617:        /* XXX: name is injected without escaping it */
                    618:        expr = str_concat3("${", name, "}");
1.801     rillig    619:        (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &val);
1.777     rillig    620:        /* TODO: handle errors */
                    621:        setenv(name, val, 1);
                    622:        free(val);
                    623:        free(expr);
1.895     rillig    624:        return true;
1.776     rillig    625: }
                    626:
1.895     rillig    627: static bool
1.776     rillig    628: ExportVarPlain(Var *v)
1.598     rillig    629: {
1.777     rillig    630:        if (strchr(v->val.data, '$') == NULL) {
                    631:                setenv(v->name.str, v->val.data, 1);
1.902     rillig    632:                v->exported = true;
                    633:                v->reexport = false;
1.895     rillig    634:                return true;
1.776     rillig    635:        }
                    636:
1.777     rillig    637:        /*
                    638:         * Flag the variable as something we need to re-export.
                    639:         * No point actually exporting it now though,
                    640:         * the child process can do it at the last minute.
1.830     rillig    641:         * Avoid calling setenv more often than necessary since it can leak.
1.777     rillig    642:         */
1.902     rillig    643:        v->exported = true;
                    644:        v->reexport = true;
1.895     rillig    645:        return true;
1.776     rillig    646: }
1.401     rillig    647:
1.895     rillig    648: static bool
1.776     rillig    649: ExportVarLiteral(Var *v)
                    650: {
1.902     rillig    651:        if (v->exported && !v->reexport)
1.895     rillig    652:                return false;
1.401     rillig    653:
1.902     rillig    654:        if (!v->exported)
1.777     rillig    655:                setenv(v->name.str, v->val.data, 1);
1.605     rillig    656:
1.895     rillig    657:        return true;
1.118     sjg       658: }
                    659:
                    660: /*
1.830     rillig    661:  * Mark a single variable to be exported later for subprocesses.
1.776     rillig    662:  *
1.830     rillig    663:  * Internal variables (those starting with '.') are not exported.
1.776     rillig    664:  */
1.895     rillig    665: static bool
1.776     rillig    666: ExportVar(const char *name, VarExportMode mode)
                    667: {
                    668:        Var *v;
                    669:
                    670:        if (!MayExport(name))
1.895     rillig    671:                return false;
1.776     rillig    672:
1.895     rillig    673:        v = VarFind(name, SCOPE_GLOBAL, false);
1.776     rillig    674:        if (v == NULL)
1.895     rillig    675:                return false;
1.776     rillig    676:
                    677:        if (mode == VEM_ENV)
                    678:                return ExportVarEnv(v);
                    679:        else if (mode == VEM_PLAIN)
                    680:                return ExportVarPlain(v);
                    681:        else
                    682:                return ExportVarLiteral(v);
                    683: }
                    684:
                    685: /*
1.765     rillig    686:  * Actually export the variables that have been marked as needing to be
                    687:  * re-exported.
1.118     sjg       688:  */
                    689: void
1.725     rillig    690: Var_ReexportVars(void)
1.118     sjg       691: {
1.775     rillig    692:        char *xvarnames;
1.412     rillig    693:
1.703     rillig    694:        /*
                    695:         * Several make implementations support this sort of mechanism for
                    696:         * tracking recursion - but each uses a different name.
                    697:         * We allow the makefiles to update MAKELEVEL and ensure
                    698:         * children see a correctly incremented value.
                    699:         */
1.831     rillig    700:        char tmp[21];
1.703     rillig    701:        snprintf(tmp, sizeof tmp, "%d", makelevel + 1);
                    702:        setenv(MAKE_LEVEL_ENV, tmp, 1);
1.182     christos  703:
1.703     rillig    704:        if (var_exportedVars == VAR_EXPORTED_NONE)
                    705:                return;
1.118     sjg       706:
1.703     rillig    707:        if (var_exportedVars == VAR_EXPORTED_ALL) {
                    708:                HashIter hi;
1.575     rillig    709:
1.831     rillig    710:                /* Ouch! Exporting all variables at once is crazy. */
1.801     rillig    711:                HashIter_Init(&hi, &SCOPE_GLOBAL->vars);
1.703     rillig    712:                while (HashIter_Next(&hi) != NULL) {
                    713:                        Var *var = hi.entry->value;
1.765     rillig    714:                        ExportVar(var->name.str, VEM_ENV);
1.703     rillig    715:                }
                    716:                return;
1.575     rillig    717:        }
1.369     rillig    718:
1.801     rillig    719:        (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL, VARE_WANTRES,
1.775     rillig    720:            &xvarnames);
1.703     rillig    721:        /* TODO: handle errors */
1.775     rillig    722:        if (xvarnames[0] != '\0') {
1.895     rillig    723:                Words varnames = Str_Words(xvarnames, false);
1.703     rillig    724:                size_t i;
                    725:
1.775     rillig    726:                for (i = 0; i < varnames.len; i++)
                    727:                        ExportVar(varnames.words[i], VEM_ENV);
                    728:                Words_Free(varnames);
1.703     rillig    729:        }
1.775     rillig    730:        free(xvarnames);
1.118     sjg       731: }
                    732:
1.726     rillig    733: static void
1.895     rillig    734: ExportVars(const char *varnames, bool isExport, VarExportMode mode)
1.831     rillig    735: /* TODO: try to combine the parameters 'isExport' and 'mode'. */
1.726     rillig    736: {
1.895     rillig    737:        Words words = Str_Words(varnames, false);
1.727     rillig    738:        size_t i;
                    739:
                    740:        if (words.len == 1 && words.words[0][0] == '\0')
                    741:                words.len = 0;
                    742:
                    743:        for (i = 0; i < words.len; i++) {
                    744:                const char *varname = words.words[i];
1.730     rillig    745:                if (!ExportVar(varname, mode))
1.727     rillig    746:                        continue;
                    747:
                    748:                if (var_exportedVars == VAR_EXPORTED_NONE)
                    749:                        var_exportedVars = VAR_EXPORTED_SOME;
1.726     rillig    750:
1.765     rillig    751:                if (isExport && mode == VEM_PLAIN)
1.795     rillig    752:                        Global_Append(MAKE_EXPORTED, varname);
1.726     rillig    753:        }
1.727     rillig    754:        Words_Free(words);
1.726     rillig    755: }
                    756:
1.728     rillig    757: static void
1.895     rillig    758: ExportVarsExpand(const char *uvarnames, bool isExport, VarExportMode mode)
1.728     rillig    759: {
                    760:        char *xvarnames;
                    761:
1.801     rillig    762:        (void)Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_WANTRES, &xvarnames);
1.728     rillig    763:        /* TODO: handle errors */
1.730     rillig    764:        ExportVars(xvarnames, isExport, mode);
1.728     rillig    765:        free(xvarnames);
                    766: }
                    767:
1.731     rillig    768: /* Export the named variables, or all variables. */
1.118     sjg       769: void
1.731     rillig    770: Var_Export(VarExportMode mode, const char *varnames)
1.118     sjg       771: {
1.765     rillig    772:        if (mode == VEM_PLAIN && varnames[0] == '\0') {
1.703     rillig    773:                var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
                    774:                return;
                    775:        }
1.118     sjg       776:
1.895     rillig    777:        ExportVarsExpand(varnames, true, mode);
1.729     rillig    778: }
                    779:
                    780: void
                    781: Var_ExportVars(const char *varnames)
                    782: {
1.895     rillig    783:        ExportVarsExpand(varnames, false, VEM_PLAIN);
1.118     sjg       784: }
                    785:
1.155     sjg       786:
1.257     rillig    787: extern char **environ;
                    788:
1.700     rillig    789: static void
1.714     rillig    790: ClearEnv(void)
1.701     rillig    791: {
                    792:        const char *cp;
                    793:        char **newenv;
                    794:
                    795:        cp = getenv(MAKE_LEVEL_ENV);    /* we should preserve this */
                    796:        if (environ == savedEnv) {
                    797:                /* we have been here before! */
                    798:                newenv = bmake_realloc(environ, 2 * sizeof(char *));
                    799:        } else {
                    800:                if (savedEnv != NULL) {
                    801:                        free(savedEnv);
                    802:                        savedEnv = NULL;
                    803:                }
                    804:                newenv = bmake_malloc(2 * sizeof(char *));
                    805:        }
                    806:
                    807:        /* Note: we cannot safely free() the original environ. */
                    808:        environ = savedEnv = newenv;
                    809:        newenv[0] = NULL;
                    810:        newenv[1] = NULL;
1.780     rillig    811:        if (cp != NULL && *cp != '\0')
1.701     rillig    812:                setenv(MAKE_LEVEL_ENV, cp, 1);
                    813: }
                    814:
                    815: static void
1.895     rillig    816: GetVarnamesToUnexport(bool isEnv, const char *arg,
1.715     rillig    817:                      FStr *out_varnames, UnexportWhat *out_what)
1.714     rillig    818: {
                    819:        UnexportWhat what;
1.739     rillig    820:        FStr varnames = FStr_InitRefer("");
1.714     rillig    821:
1.732     rillig    822:        if (isEnv) {
                    823:                if (arg[0] != '\0') {
1.723     rillig    824:                        Parse_Error(PARSE_FATAL,
                    825:                            "The directive .unexport-env does not take "
                    826:                            "arguments");
1.830     rillig    827:                        /* continue anyway */
1.723     rillig    828:                }
1.714     rillig    829:                what = UNEXPORT_ENV;
1.723     rillig    830:
1.732     rillig    831:        } else {
                    832:                what = arg[0] != '\0' ? UNEXPORT_NAMED : UNEXPORT_ALL;
1.714     rillig    833:                if (what == UNEXPORT_NAMED)
1.739     rillig    834:                        varnames = FStr_InitRefer(arg);
1.714     rillig    835:        }
                    836:
                    837:        if (what != UNEXPORT_NAMED) {
                    838:                char *expanded;
                    839:                /* Using .MAKE.EXPORTED */
1.801     rillig    840:                (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL,
1.714     rillig    841:                    VARE_WANTRES, &expanded);
                    842:                /* TODO: handle errors */
1.739     rillig    843:                varnames = FStr_InitOwn(expanded);
1.714     rillig    844:        }
                    845:
                    846:        *out_varnames = varnames;
                    847:        *out_what = what;
                    848: }
                    849:
                    850: static void
1.713     rillig    851: UnexportVar(const char *varname, UnexportWhat what)
1.700     rillig    852: {
1.895     rillig    853:        Var *v = VarFind(varname, SCOPE_GLOBAL, false);
1.700     rillig    854:        if (v == NULL) {
1.708     rillig    855:                DEBUG1(VAR, "Not unexporting \"%s\" (not found)\n", varname);
1.700     rillig    856:                return;
                    857:        }
                    858:
1.708     rillig    859:        DEBUG1(VAR, "Unexporting \"%s\"\n", varname);
1.902     rillig    860:        if (what != UNEXPORT_ENV && v->exported && !v->reexport)
1.711     rillig    861:                unsetenv(v->name.str);
1.902     rillig    862:        v->exported = false;
                    863:        v->reexport = false;
1.700     rillig    864:
1.713     rillig    865:        if (what == UNEXPORT_NAMED) {
                    866:                /* Remove the variable names from .MAKE.EXPORTED. */
1.700     rillig    867:                /* XXX: v->name is injected without escaping it */
1.711     rillig    868:                char *expr = str_concat3("${" MAKE_EXPORTED ":N",
                    869:                    v->name.str, "}");
1.700     rillig    870:                char *cp;
1.801     rillig    871:                (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &cp);
1.700     rillig    872:                /* TODO: handle errors */
1.792     rillig    873:                Global_Set(MAKE_EXPORTED, cp);
1.700     rillig    874:                free(cp);
                    875:                free(expr);
                    876:        }
                    877: }
                    878:
1.716     rillig    879: static void
                    880: UnexportVars(FStr *varnames, UnexportWhat what)
                    881: {
                    882:        size_t i;
1.717     rillig    883:        Words words;
                    884:
                    885:        if (what == UNEXPORT_ENV)
                    886:                ClearEnv();
1.716     rillig    887:
1.895     rillig    888:        words = Str_Words(varnames->str, false);
1.716     rillig    889:        for (i = 0; i < words.len; i++) {
                    890:                const char *varname = words.words[i];
                    891:                UnexportVar(varname, what);
                    892:        }
                    893:        Words_Free(words);
                    894:
                    895:        if (what != UNEXPORT_NAMED)
1.804     rillig    896:                Global_Delete(MAKE_EXPORTED);
1.716     rillig    897: }
                    898:
1.155     sjg       899: /*
                    900:  * This is called when .unexport[-env] is seen.
1.338     rillig    901:  *
                    902:  * str must have the form "unexport[-env] varname...".
1.155     sjg       903:  */
                    904: void
1.895     rillig    905: Var_UnExport(bool isEnv, const char *arg)
1.155     sjg       906: {
1.713     rillig    907:        UnexportWhat what;
1.714     rillig    908:        FStr varnames;
1.155     sjg       909:
1.732     rillig    910:        GetVarnamesToUnexport(isEnv, arg, &varnames, &what);
1.716     rillig    911:        UnexportVars(&varnames, what);
1.712     rillig    912:        FStr_Done(&varnames);
1.155     sjg       913: }
                    914:
1.834     rillig    915: /*
                    916:  * When there is a variable of the same name in the command line scope, the
                    917:  * global variable would not be visible anywhere.  Therefore there is no
                    918:  * point in setting it at all.
                    919:  *
                    920:  * See 'scope == SCOPE_CMDLINE' in Var_SetWithFlags.
                    921:  */
1.895     rillig    922: static bool
1.834     rillig    923: ExistsInCmdline(const char *name, const char *val)
                    924: {
                    925:        Var *v;
                    926:
1.895     rillig    927:        v = VarFind(name, SCOPE_CMDLINE, false);
1.834     rillig    928:        if (v == NULL)
1.895     rillig    929:                return false;
1.834     rillig    930:
1.902     rillig    931:        if (v->fromCmd) {
1.911     rillig    932:                DEBUG3(VAR, "%s: %s = %s ignored!\n",
1.834     rillig    933:                    SCOPE_GLOBAL->name, name, val);
1.895     rillig    934:                return true;
1.834     rillig    935:        }
                    936:
1.837     rillig    937:        VarFreeEnv(v);
1.895     rillig    938:        return false;
1.834     rillig    939: }
                    940:
1.747     rillig    941: /* Set the variable to the value; the name is not expanded. */
1.800     rillig    942: void
1.805     rillig    943: Var_SetWithFlags(GNode *scope, const char *name, const char *val,
1.800     rillig    944:                 VarSetFlags flags)
1.1       cgd       945: {
1.704     rillig    946:        Var *v;
1.142     dsl       947:
1.793     rillig    948:        assert(val != NULL);
                    949:        if (name[0] == '\0') {
                    950:                DEBUG0(VAR, "SetVar: variable name is empty - ignored\n");
                    951:                return;
                    952:        }
                    953:
1.834     rillig    954:        if (scope == SCOPE_GLOBAL && ExistsInCmdline(name, val))
                    955:                return;
1.400     rillig    956:
1.704     rillig    957:        /*
1.802     rillig    958:         * Only look for a variable in the given scope since anything set
                    959:         * here will override anything in a lower scope, so there's not much
1.830     rillig    960:         * point in searching them all.
1.704     rillig    961:         */
1.895     rillig    962:        v = VarFind(name, scope, false);
1.704     rillig    963:        if (v == NULL) {
1.802     rillig    964:                if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
1.704     rillig    965:                        /*
                    966:                         * This var would normally prevent the same name being
1.801     rillig    967:                         * added to SCOPE_GLOBAL, so delete it from there if
1.704     rillig    968:                         * needed. Otherwise -V name may show the wrong value.
1.832     rillig    969:                         *
1.835     rillig    970:                         * See ExistsInCmdline.
1.704     rillig    971:                         */
1.835     rillig    972:                        Var_Delete(SCOPE_GLOBAL, name);
1.704     rillig    973:                }
1.833     rillig    974:                v = VarAdd(name, val, scope, flags);
1.704     rillig    975:        } else {
1.902     rillig    976:                if (v->readOnly && !(flags & VAR_SET_READONLY)) {
1.911     rillig    977:                        DEBUG3(VAR, "%s: %s = %s ignored (read-only)\n",
1.802     rillig    978:                            scope->name, name, val);
1.747     rillig    979:                        return;
1.704     rillig    980:                }
                    981:                Buf_Empty(&v->val);
                    982:                Buf_AddStr(&v->val, val);
                    983:
1.911     rillig    984:                DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, val);
1.902     rillig    985:                if (v->exported)
1.765     rillig    986:                        ExportVar(name, VEM_PLAIN);
1.183     sjg       987:        }
1.833     rillig    988:
1.71      thorpej   989:        /*
1.704     rillig    990:         * Any variables given on the command line are automatically exported
1.833     rillig    991:         * to the environment (as per POSIX standard), except for internals.
1.71      thorpej   992:         */
1.802     rillig    993:        if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT) &&
1.704     rillig    994:            name[0] != '.') {
1.902     rillig    995:                v->fromCmd = true;
1.704     rillig    996:
                    997:                /*
                    998:                 * If requested, don't export these in the environment
                    999:                 * individually.  We still put them in MAKEOVERRIDES so
                   1000:                 * that the command-line settings continue to override
                   1001:                 * Makefile settings.
                   1002:                 */
                   1003:                if (!opts.varNoExportEnv)
                   1004:                        setenv(name, val, 1);
1.836     rillig   1005:                /* XXX: What about .MAKE.EXPORTED? */
                   1006:                /* XXX: Why not just mark the variable for needing export,
                   1007:                 *  as in ExportVarPlain? */
1.62      sjg      1008:
1.795     rillig   1009:                Global_Append(MAKEOVERRIDES, name);
1.704     rillig   1010:        }
1.833     rillig   1011:
1.704     rillig   1012:        if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
                   1013:                save_dollars = ParseBoolean(val, save_dollars);
1.205     sjg      1014:
1.704     rillig   1015:        if (v != NULL)
1.837     rillig   1016:                VarFreeEnv(v);
1.1       cgd      1017: }
                   1018:
1.747     rillig   1019: /* See Var_Set for documentation. */
                   1020: void
1.805     rillig   1021: Var_SetExpandWithFlags(GNode *scope, const char *name, const char *val,
                   1022:                       VarSetFlags flags)
1.747     rillig   1023: {
                   1024:        const char *unexpanded_name = name;
1.748     rillig   1025:        FStr varname = FStr_InitRefer(name);
1.747     rillig   1026:
                   1027:        assert(val != NULL);
                   1028:
1.748     rillig   1029:        if (strchr(varname.str, '$') != NULL) {
                   1030:                char *expanded;
1.802     rillig   1031:                (void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded);
1.747     rillig   1032:                /* TODO: handle errors */
1.748     rillig   1033:                varname = FStr_InitOwn(expanded);
1.747     rillig   1034:        }
                   1035:
1.748     rillig   1036:        if (varname.str[0] == '\0') {
1.914     rillig   1037:                DEBUG2(VAR,
                   1038:                    "Var_SetExpand: variable name \"%s\" expands "
                   1039:                    "to empty string, with value \"%s\" - ignored\n",
1.747     rillig   1040:                    unexpanded_name, val);
1.748     rillig   1041:        } else
1.805     rillig   1042:                Var_SetWithFlags(scope, varname.str, val, flags);
1.747     rillig   1043:
1.748     rillig   1044:        FStr_Done(&varname);
1.747     rillig   1045: }
                   1046:
1.798     rillig   1047: void
1.805     rillig   1048: Var_Set(GNode *scope, const char *name, const char *val)
1.798     rillig   1049: {
1.805     rillig   1050:        Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1.798     rillig   1051: }
                   1052:
1.718     rillig   1053: /*
1.802     rillig   1054:  * Set the variable name to the value val in the given scope.
1.230     rillig   1055:  *
1.718     rillig   1056:  * If the variable doesn't yet exist, it is created.
                   1057:  * Otherwise the new value overwrites and replaces the old value.
1.483     rillig   1058:  *
1.230     rillig   1059:  * Input:
1.607     rillig   1060:  *     name            name of the variable to set, is expanded once
1.230     rillig   1061:  *     val             value to give to the variable
1.802     rillig   1062:  *     scope           scope in which to set it
1.230     rillig   1063:  */
                   1064: void
1.805     rillig   1065: Var_SetExpand(GNode *scope, const char *name, const char *val)
1.230     rillig   1066: {
1.805     rillig   1067:        Var_SetExpandWithFlags(scope, name, val, VAR_SET_NONE);
1.230     rillig   1068: }
                   1069:
1.791     rillig   1070: void
1.792     rillig   1071: Global_Set(const char *name, const char *value)
                   1072: {
1.805     rillig   1073:        Var_Set(SCOPE_GLOBAL, name, value);
1.792     rillig   1074: }
                   1075:
                   1076: void
1.791     rillig   1077: Global_SetExpand(const char *name, const char *value)
                   1078: {
1.805     rillig   1079:        Var_SetExpand(SCOPE_GLOBAL, name, value);
1.791     rillig   1080: }
                   1081:
1.804     rillig   1082: void
                   1083: Global_Delete(const char *name)
                   1084: {
1.805     rillig   1085:        Var_Delete(SCOPE_GLOBAL, name);
1.804     rillig   1086: }
                   1087:
1.718     rillig   1088: /*
1.794     rillig   1089:  * Append the value to the named variable.
                   1090:  *
                   1091:  * If the variable doesn't exist, it is created.  Otherwise a single space
                   1092:  * and the given value are appended.
                   1093:  */
                   1094: void
1.805     rillig   1095: Var_Append(GNode *scope, const char *name, const char *val)
1.794     rillig   1096: {
                   1097:        Var *v;
                   1098:
1.802     rillig   1099:        v = VarFind(name, scope, scope == SCOPE_GLOBAL);
1.794     rillig   1100:
                   1101:        if (v == NULL) {
1.805     rillig   1102:                Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
1.902     rillig   1103:        } else if (v->readOnly) {
1.794     rillig   1104:                DEBUG1(VAR, "Ignoring append to %s since it is read-only\n",
                   1105:                    name);
1.902     rillig   1106:        } else if (scope == SCOPE_CMDLINE || !v->fromCmd) {
1.794     rillig   1107:                Buf_AddByte(&v->val, ' ');
                   1108:                Buf_AddStr(&v->val, val);
                   1109:
1.911     rillig   1110:                DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, v->val.data);
1.794     rillig   1111:
1.902     rillig   1112:                if (v->fromEnv) {
1.794     rillig   1113:                        /*
                   1114:                         * If the original variable came from the environment,
1.802     rillig   1115:                         * we have to install it in the global scope (we
1.794     rillig   1116:                         * could place it in the environment, but then we
                   1117:                         * should provide a way to export other variables...)
                   1118:                         */
1.902     rillig   1119:                        v->fromEnv = false;
1.794     rillig   1120:                        /*
                   1121:                         * This is the only place where a variable is
                   1122:                         * created whose v->name is not the same as
1.802     rillig   1123:                         * scope->vars->key.
1.794     rillig   1124:                         */
1.802     rillig   1125:                        HashTable_Set(&scope->vars, name, v);
1.794     rillig   1126:                }
                   1127:        }
                   1128: }
                   1129:
                   1130: /*
1.718     rillig   1131:  * The variable of the given name has the given value appended to it in the
1.802     rillig   1132:  * given scope.
1.1       cgd      1133:  *
1.718     rillig   1134:  * If the variable doesn't exist, it is created. Otherwise the strings are
                   1135:  * concatenated, with a space in between.
1.483     rillig   1136:  *
1.70      wiz      1137:  * Input:
1.607     rillig   1138:  *     name            name of the variable to modify, is expanded once
1.400     rillig   1139:  *     val             string to append to it
1.802     rillig   1140:  *     scope           scope in which this should occur
1.70      wiz      1141:  *
1.1       cgd      1142:  * Notes:
1.802     rillig   1143:  *     Only if the variable is being sought in the global scope is the
1.1       cgd      1144:  *     environment searched.
1.802     rillig   1145:  *     XXX: Knows its calling circumstances in that if called with scope
                   1146:  *     an actual target, it will only search that scope since only
1.1       cgd      1147:  *     a local variable could be being appended to. This is actually
                   1148:  *     a big win and must be tolerated.
                   1149:  */
                   1150: void
1.805     rillig   1151: Var_AppendExpand(GNode *scope, const char *name, const char *val)
1.1       cgd      1152: {
1.838     rillig   1153:        FStr xname = FStr_InitRefer(name);
1.1       cgd      1154:
1.704     rillig   1155:        assert(val != NULL);
1.460     rillig   1156:
1.704     rillig   1157:        if (strchr(name, '$') != NULL) {
1.838     rillig   1158:                char *expanded;
                   1159:                (void)Var_Subst(name, scope, VARE_WANTRES, &expanded);
1.704     rillig   1160:                /* TODO: handle errors */
1.838     rillig   1161:                xname = FStr_InitOwn(expanded);
                   1162:                if (expanded[0] == '\0') {
1.914     rillig   1163:                        DEBUG2(VAR,
                   1164:                            "Var_AppendExpand: variable name \"%s\" expands "
                   1165:                            "to empty string, with value \"%s\" - ignored\n",
1.838     rillig   1166:                            name, val);
                   1167:                        FStr_Done(&xname);
1.704     rillig   1168:                        return;
                   1169:                }
1.139     dsl      1170:        }
1.142     dsl      1171:
1.838     rillig   1172:        Var_Append(scope, xname.str, val);
1.1       cgd      1173:
1.838     rillig   1174:        FStr_Done(&xname);
1.1       cgd      1175: }
                   1176:
1.791     rillig   1177: void
1.795     rillig   1178: Global_Append(const char *name, const char *value)
1.791     rillig   1179: {
1.805     rillig   1180:        Var_Append(SCOPE_GLOBAL, name, value);
1.791     rillig   1181: }
                   1182:
1.895     rillig   1183: bool
1.805     rillig   1184: Var_Exists(GNode *scope, const char *name)
1.796     rillig   1185: {
1.895     rillig   1186:        Var *v = VarFind(name, scope, true);
1.796     rillig   1187:        if (v == NULL)
1.895     rillig   1188:                return false;
1.796     rillig   1189:
1.837     rillig   1190:        VarFreeEnv(v);
1.895     rillig   1191:        return true;
1.796     rillig   1192: }
                   1193:
1.778     rillig   1194: /*
1.802     rillig   1195:  * See if the given variable exists, in the given scope or in other
                   1196:  * fallback scopes.
1.1       cgd      1197:  *
1.70      wiz      1198:  * Input:
1.607     rillig   1199:  *     name            Variable to find, is expanded once
1.802     rillig   1200:  *     scope           Scope in which to start search
1.1       cgd      1201:  */
1.895     rillig   1202: bool
1.805     rillig   1203: Var_ExistsExpand(GNode *scope, const char *name)
1.1       cgd      1204: {
1.747     rillig   1205:        FStr varname = FStr_InitRefer(name);
1.895     rillig   1206:        bool exists;
1.412     rillig   1207:
1.747     rillig   1208:        if (strchr(varname.str, '$') != NULL) {
                   1209:                char *expanded;
1.802     rillig   1210:                (void)Var_Subst(varname.str, scope, VARE_WANTRES, &expanded);
1.703     rillig   1211:                /* TODO: handle errors */
1.747     rillig   1212:                varname = FStr_InitOwn(expanded);
1.703     rillig   1213:        }
1.1       cgd      1214:
1.805     rillig   1215:        exists = Var_Exists(scope, varname.str);
1.747     rillig   1216:        FStr_Done(&varname);
1.796     rillig   1217:        return exists;
1.1       cgd      1218: }
                   1219:
1.718     rillig   1220: /*
1.802     rillig   1221:  * Return the unexpanded value of the given variable in the given scope,
                   1222:  * or the usual scopes.
1.1       cgd      1223:  *
1.70      wiz      1224:  * Input:
1.607     rillig   1225:  *     name            name to find, is not expanded any further
1.802     rillig   1226:  *     scope           scope in which to search for it
1.70      wiz      1227:  *
1.1       cgd      1228:  * Results:
1.337     rillig   1229:  *     The value if the variable exists, NULL if it doesn't.
1.830     rillig   1230:  *     The value is valid until the next modification to any variable.
1.1       cgd      1231:  */
1.745     rillig   1232: FStr
1.805     rillig   1233: Var_Value(GNode *scope, const char *name)
1.1       cgd      1234: {
1.895     rillig   1235:        Var *v = VarFind(name, scope, true);
1.703     rillig   1236:        char *value;
                   1237:
                   1238:        if (v == NULL)
1.745     rillig   1239:                return FStr_InitRefer(NULL);
1.412     rillig   1240:
1.902     rillig   1241:        if (!v->fromEnv)
1.837     rillig   1242:                return FStr_InitRefer(v->val.data);
                   1243:
                   1244:        /* Since environment variables are short-lived, free it now. */
                   1245:        FStr_Done(&v->name);
                   1246:        value = Buf_DoneData(&v->val);
                   1247:        free(v);
                   1248:        return FStr_InitOwn(value);
1.1       cgd      1249: }
                   1250:
1.778     rillig   1251: /*
                   1252:  * Return the unexpanded variable value from this node, without trying to look
1.802     rillig   1253:  * up the variable in any other scope.
1.778     rillig   1254:  */
1.616     rillig   1255: const char *
1.803     rillig   1256: GNode_ValueDirect(GNode *gn, const char *name)
1.616     rillig   1257: {
1.895     rillig   1258:        Var *v = VarFind(name, gn, false);
1.785     rillig   1259:        return v != NULL ? v->val.data : NULL;
1.616     rillig   1260: }
                   1261:
1.906     rillig   1262: static VarEvalMode
                   1263: VarEvalMode_WithoutKeepDollar(VarEvalMode emode)
                   1264: {
                   1265:        if (emode == VARE_KEEP_DOLLAR_UNDEF)
                   1266:                return VARE_EVAL_KEEP_UNDEF;
                   1267:        if (emode == VARE_EVAL_KEEP_DOLLAR)
                   1268:                return VARE_WANTRES;
                   1269:        return emode;
                   1270: }
                   1271:
                   1272: static VarEvalMode
                   1273: VarEvalMode_UndefOk(VarEvalMode emode)
                   1274: {
                   1275:        return emode == VARE_UNDEFERR ? VARE_WANTRES : emode;
                   1276: }
1.244     rillig   1277:
1.905     rillig   1278: static bool
1.906     rillig   1279: VarEvalMode_ShouldEval(VarEvalMode emode)
1.905     rillig   1280: {
1.906     rillig   1281:        return emode != VARE_PARSE_ONLY;
                   1282: }
                   1283:
                   1284: static bool
                   1285: VarEvalMode_ShouldKeepUndef(VarEvalMode emode)
                   1286: {
                   1287:        return emode == VARE_EVAL_KEEP_UNDEF ||
                   1288:               emode == VARE_KEEP_DOLLAR_UNDEF;
                   1289: }
                   1290:
                   1291: static bool
                   1292: VarEvalMode_ShouldKeepDollar(VarEvalMode emode)
                   1293: {
                   1294:        return emode == VARE_EVAL_KEEP_DOLLAR ||
                   1295:               emode == VARE_KEEP_DOLLAR_UNDEF;
1.905     rillig   1296: }
                   1297:
                   1298:
1.278     rillig   1299: static void
                   1300: SepBuf_Init(SepBuf *buf, char sep)
                   1301: {
1.703     rillig   1302:        Buf_InitSize(&buf->buf, 32);
1.895     rillig   1303:        buf->needSep = false;
1.703     rillig   1304:        buf->sep = sep;
1.278     rillig   1305: }
                   1306:
                   1307: static void
                   1308: SepBuf_Sep(SepBuf *buf)
                   1309: {
1.895     rillig   1310:        buf->needSep = true;
1.278     rillig   1311: }
                   1312:
                   1313: static void
1.314     rillig   1314: SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1.278     rillig   1315: {
1.703     rillig   1316:        if (mem_size == 0)
                   1317:                return;
                   1318:        if (buf->needSep && buf->sep != '\0') {
                   1319:                Buf_AddByte(&buf->buf, buf->sep);
1.895     rillig   1320:                buf->needSep = false;
1.703     rillig   1321:        }
                   1322:        Buf_AddBytes(&buf->buf, mem, mem_size);
1.278     rillig   1323: }
                   1324:
1.314     rillig   1325: static void
                   1326: SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end)
                   1327: {
1.703     rillig   1328:        SepBuf_AddBytes(buf, start, (size_t)(end - start));
1.314     rillig   1329: }
                   1330:
                   1331: static void
                   1332: SepBuf_AddStr(SepBuf *buf, const char *str)
                   1333: {
1.703     rillig   1334:        SepBuf_AddBytes(buf, str, strlen(str));
1.314     rillig   1335: }
                   1336:
1.919     rillig   1337: static void
                   1338: SepBuf_AddSubstring(SepBuf *buf, Substring sub)
                   1339: {
                   1340:        SepBuf_AddBytesBetween(buf, sub.start, sub.end);
                   1341: }
                   1342:
1.278     rillig   1343: static char *
1.784     rillig   1344: SepBuf_DoneData(SepBuf *buf)
1.278     rillig   1345: {
1.784     rillig   1346:        return Buf_DoneData(&buf->buf);
1.278     rillig   1347: }
                   1348:
                   1349:
1.778     rillig   1350: /*
                   1351:  * This callback for ModifyWords gets a single word from a variable expression
1.609     rillig   1352:  * and typically adds a modification of this word to the buffer. It may also
                   1353:  * do nothing or add several words.
                   1354:  *
1.822     rillig   1355:  * For example, when evaluating the modifier ':M*b' in ${:Ua b c:M*b}, the
                   1356:  * callback is called 3 times, once for "a", "b" and "c".
1.919     rillig   1357:  *
                   1358:  * Some ModifyWord functions assume that they are always passed a
                   1359:  * null-terminated substring, which is currently guaranteed but may change in
                   1360:  * the future.
1.778     rillig   1361:  */
1.919     rillig   1362: typedef void (*ModifyWordProc)(Substring word, SepBuf *buf, void *data);
1.244     rillig   1363:
                   1364:
1.778     rillig   1365: /*
                   1366:  * Callback for ModifyWords to implement the :H modifier.
                   1367:  * Add the dirname of the given word to the buffer.
                   1368:  */
1.779     rillig   1369: /*ARGSUSED*/
1.278     rillig   1370: static void
1.919     rillig   1371: ModifyWord_Head(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1372: {
1.919     rillig   1373:        SepBuf_AddSubstring(buf, Substring_Dirname(word));
1.1       cgd      1374: }
                   1375:
1.778     rillig   1376: /*
                   1377:  * Callback for ModifyWords to implement the :T modifier.
                   1378:  * Add the basename of the given word to the buffer.
                   1379:  */
1.779     rillig   1380: /*ARGSUSED*/
1.278     rillig   1381: static void
1.919     rillig   1382: ModifyWord_Tail(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1383: {
1.919     rillig   1384:        SepBuf_AddSubstring(buf, Substring_Basename(word));
1.1       cgd      1385: }
                   1386:
1.778     rillig   1387: /*
                   1388:  * Callback for ModifyWords to implement the :E modifier.
                   1389:  * Add the filename suffix of the given word to the buffer, if it exists.
                   1390:  */
1.779     rillig   1391: /*ARGSUSED*/
1.278     rillig   1392: static void
1.919     rillig   1393: ModifyWord_Suffix(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1394: {
1.919     rillig   1395:        const char *lastDot = Substring_LastIndex(word, '.');
1.703     rillig   1396:        if (lastDot != NULL)
1.919     rillig   1397:                SepBuf_AddBytesBetween(buf, lastDot + 1, word.end);
1.1       cgd      1398: }
                   1399:
1.778     rillig   1400: /*
                   1401:  * Callback for ModifyWords to implement the :R modifier.
1.830     rillig   1402:  * Add the filename without extension of the given word to the buffer.
1.778     rillig   1403:  */
1.779     rillig   1404: /*ARGSUSED*/
1.278     rillig   1405: static void
1.919     rillig   1406: ModifyWord_Root(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1407: {
1.919     rillig   1408:        const char *lastDot, *end;
                   1409:
                   1410:        lastDot = Substring_LastIndex(word, '.');
                   1411:        end = lastDot != NULL ? lastDot : word.end;
                   1412:        SepBuf_AddBytesBetween(buf, word.start, end);
1.1       cgd      1413: }
                   1414:
1.778     rillig   1415: /*
                   1416:  * Callback for ModifyWords to implement the :M modifier.
                   1417:  * Place the word in the buffer if it matches the given pattern.
                   1418:  */
1.278     rillig   1419: static void
1.919     rillig   1420: ModifyWord_Match(Substring word, SepBuf *buf, void *data)
1.1       cgd      1421: {
1.703     rillig   1422:        const char *pattern = data;
1.908     rillig   1423:
1.919     rillig   1424:        assert(word.end[0] == '\0');    /* assume null-terminated word */
                   1425:        if (Str_Match(word.start, pattern))
                   1426:                SepBuf_AddSubstring(buf, word);
1.1       cgd      1427: }
                   1428:
1.778     rillig   1429: /*
                   1430:  * Callback for ModifyWords to implement the :N modifier.
                   1431:  * Place the word in the buffer if it doesn't match the given pattern.
                   1432:  */
1.291     rillig   1433: static void
1.919     rillig   1434: ModifyWord_NoMatch(Substring word, SepBuf *buf, void *data)
1.291     rillig   1435: {
1.703     rillig   1436:        const char *pattern = data;
1.908     rillig   1437:
1.919     rillig   1438:        assert(word.end[0] == '\0');    /* assume null-terminated word */
                   1439:        if (!Str_Match(word.start, pattern))
                   1440:                SepBuf_AddSubstring(buf, word);
1.291     rillig   1441: }
                   1442:
1.13      christos 1443: #ifdef SYSVVARSUB
1.926     rillig   1444: struct ModifyWord_SysVSubstArgs {
1.806     rillig   1445:        GNode *scope;
1.925     rillig   1446:        Substring lhsPrefix;
                   1447:        bool lhsPercent;
                   1448:        Substring lhsSuffix;
1.703     rillig   1449:        const char *rhs;
1.541     rillig   1450: };
1.276     rillig   1451:
1.291     rillig   1452: /* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1.278     rillig   1453: static void
1.926     rillig   1454: ModifyWord_SysVSubst(Substring word, SepBuf *buf, void *data)
1.5       cgd      1455: {
1.926     rillig   1456:        const struct ModifyWord_SysVSubstArgs *args = data;
1.925     rillig   1457:        FStr rhs;
                   1458:        char *rhsExp;
1.703     rillig   1459:        const char *percent;
1.919     rillig   1460:
1.925     rillig   1461:        if (Substring_IsEmpty(word))
1.703     rillig   1462:                return;
1.925     rillig   1463:
                   1464:        if (!Substring_HasPrefix(word, args->lhsPrefix))
                   1465:                goto no_match;
                   1466:        if (!Substring_HasSuffix(word, args->lhsSuffix))
                   1467:                goto no_match;
                   1468:
                   1469:        rhs = FStr_InitRefer(args->rhs);
                   1470:        if (strchr(rhs.str, '$') != NULL) {
                   1471:                (void)Var_Subst(args->rhs, args->scope, VARE_WANTRES, &rhsExp);
                   1472:                /* TODO: handle errors */
                   1473:                rhs = FStr_InitOwn(rhsExp);
1.703     rillig   1474:        }
1.379     rillig   1475:
1.925     rillig   1476:        percent = args->lhsPercent ? strchr(rhs.str, '%') : NULL;
1.379     rillig   1477:
1.925     rillig   1478:        if (percent != NULL)
                   1479:                SepBuf_AddBytesBetween(buf, rhs.str, percent);
                   1480:        if (percent != NULL || !args->lhsPercent)
                   1481:                SepBuf_AddBytesBetween(buf,
                   1482:                    word.start + Substring_Length(args->lhsPrefix),
                   1483:                    word.end - Substring_Length(args->lhsSuffix));
                   1484:        SepBuf_AddStr(buf, percent != NULL ? percent + 1 : rhs.str);
1.379     rillig   1485:
1.925     rillig   1486:        FStr_Done(&rhs);
                   1487:        return;
1.379     rillig   1488:
1.925     rillig   1489: no_match:
                   1490:        SepBuf_AddSubstring(buf, word);
1.5       cgd      1491: }
1.13      christos 1492: #endif
1.5       cgd      1493:
1.1       cgd      1494:
1.541     rillig   1495: struct ModifyWord_SubstArgs {
1.918     rillig   1496:        Substring lhs;
                   1497:        Substring rhs;
1.927     rillig   1498:        PatternFlags pflags;
1.895     rillig   1499:        bool matched;
1.541     rillig   1500: };
1.291     rillig   1501:
1.918     rillig   1502: static const char *
                   1503: Substring_Find(Substring haystack, Substring needle)
                   1504: {
                   1505:        size_t len, needleLen, i;
                   1506:
                   1507:        len = Substring_Length(haystack);
                   1508:        needleLen = Substring_Length(needle);
                   1509:        for (i = 0; i + needleLen <= len; i++)
                   1510:                if (memcmp(haystack.start + i, needle.start, needleLen) == 0)
                   1511:                        return haystack.start + i;
                   1512:        return NULL;
                   1513: }
                   1514:
1.778     rillig   1515: /*
                   1516:  * Callback for ModifyWords to implement the :S,from,to, modifier.
                   1517:  * Perform a string substitution on the given word.
                   1518:  */
1.278     rillig   1519: static void
1.919     rillig   1520: ModifyWord_Subst(Substring word, SepBuf *buf, void *data)
1.1       cgd      1521: {
1.703     rillig   1522:        struct ModifyWord_SubstArgs *args = data;
1.918     rillig   1523:        size_t wordLen, lhsLen;
                   1524:        const char *wordEnd, *match;
1.703     rillig   1525:
1.919     rillig   1526:        wordLen = Substring_Length(word);
                   1527:        wordEnd = word.end;
1.788     rillig   1528:        if (args->pflags.subOnce && args->matched)
1.703     rillig   1529:                goto nosub;
                   1530:
1.918     rillig   1531:        lhsLen = Substring_Length(args->lhs);
1.788     rillig   1532:        if (args->pflags.anchorStart) {
1.918     rillig   1533:                if (wordLen < lhsLen ||
1.919     rillig   1534:                    memcmp(word.start, args->lhs.start, lhsLen) != 0)
1.703     rillig   1535:                        goto nosub;
                   1536:
1.918     rillig   1537:                if (args->pflags.anchorEnd && wordLen != lhsLen)
1.703     rillig   1538:                        goto nosub;
                   1539:
                   1540:                /* :S,^prefix,replacement, or :S,^whole$,replacement, */
1.919     rillig   1541:                SepBuf_AddSubstring(buf, args->rhs);
                   1542:                SepBuf_AddBytesBetween(buf, word.start + lhsLen, wordEnd);
1.895     rillig   1543:                args->matched = true;
1.703     rillig   1544:                return;
                   1545:        }
1.1       cgd      1546:
1.788     rillig   1547:        if (args->pflags.anchorEnd) {
1.918     rillig   1548:                if (wordLen < lhsLen)
1.703     rillig   1549:                        goto nosub;
1.918     rillig   1550:                if (memcmp(wordEnd - lhsLen, args->lhs.start, lhsLen) != 0)
1.703     rillig   1551:                        goto nosub;
                   1552:
                   1553:                /* :S,suffix$,replacement, */
1.919     rillig   1554:                SepBuf_AddBytesBetween(buf, word.start, wordEnd - lhsLen);
                   1555:                SepBuf_AddSubstring(buf, args->rhs);
1.895     rillig   1556:                args->matched = true;
1.703     rillig   1557:                return;
                   1558:        }
1.315     rillig   1559:
1.921     rillig   1560:        if (Substring_IsEmpty(args->lhs))
1.703     rillig   1561:                goto nosub;
1.279     rillig   1562:
1.703     rillig   1563:        /* unanchored case, may match more than once */
1.919     rillig   1564:        while ((match = Substring_Find(word, args->lhs)) != NULL) {
                   1565:                SepBuf_AddBytesBetween(buf, word.start, match);
                   1566:                SepBuf_AddSubstring(buf, args->rhs);
1.895     rillig   1567:                args->matched = true;
1.921     rillig   1568:                word.start = match + lhsLen;
1.919     rillig   1569:                if (Substring_IsEmpty(word) || !args->pflags.subGlobal)
1.703     rillig   1570:                        break;
                   1571:        }
1.242     rillig   1572: nosub:
1.919     rillig   1573:        SepBuf_AddSubstring(buf, word);
1.1       cgd      1574: }
                   1575:
1.31      gwr      1576: #ifndef NO_REGEX
1.400     rillig   1577: /* Print the error caused by a regcomp or regexec call. */
1.16      christos 1578: static void
1.672     rillig   1579: VarREError(int reerr, const regex_t *pat, const char *str)
1.16      christos 1580: {
1.703     rillig   1581:        size_t errlen = regerror(reerr, pat, NULL, 0);
                   1582:        char *errbuf = bmake_malloc(errlen);
                   1583:        regerror(reerr, pat, errbuf, errlen);
                   1584:        Error("%s: %s", str, errbuf);
                   1585:        free(errbuf);
1.16      christos 1586: }
                   1587:
1.937     rillig   1588: /*
                   1589:  * Replacement of regular expressions is not specified by POSIX, therefore
                   1590:  * re-implement it here.
                   1591:  */
                   1592: static void
                   1593: RegexReplace(const char *replace, SepBuf *buf, const char *wp,
                   1594:             const regmatch_t *m, size_t nsub)
                   1595: {
                   1596:        const char *rp;
1.938     rillig   1597:        unsigned int n;
1.937     rillig   1598:
                   1599:        for (rp = replace; *rp != '\0'; rp++) {
                   1600:                if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
                   1601:                        SepBuf_AddBytes(buf, rp + 1, 1);
                   1602:                        rp++;
                   1603:                        continue;
                   1604:                }
                   1605:
                   1606:                if (*rp == '&') {
                   1607:                        SepBuf_AddBytesBetween(buf,
1.948   ! rillig   1608:                            wp + (size_t)m[0].rm_so,
        !          1609:                            wp + (size_t)m[0].rm_eo);
1.937     rillig   1610:                        continue;
                   1611:                }
                   1612:
                   1613:                if (*rp != '\\' || !ch_isdigit(rp[1])) {
                   1614:                        SepBuf_AddBytes(buf, rp, 1);
                   1615:                        continue;
                   1616:                }
                   1617:
                   1618:                /* \0 to \9 backreference */
1.938     rillig   1619:                n = rp[1] - '0';
1.937     rillig   1620:                rp++;
                   1621:
                   1622:                if (n >= nsub) {
1.938     rillig   1623:                        Error("No subexpression \\%u", n);
1.937     rillig   1624:                } else if (m[n].rm_so == -1) {
                   1625:                        if (opts.strict) {
1.938     rillig   1626:                                Error("No match for subexpression \\%u", n);
1.937     rillig   1627:                        }
                   1628:                } else {
                   1629:                        SepBuf_AddBytesBetween(buf,
1.948   ! rillig   1630:                            wp + (size_t)m[n].rm_so,
        !          1631:                            wp + (size_t)m[n].rm_eo);
1.937     rillig   1632:                }
                   1633:        }
                   1634: }
                   1635:
1.541     rillig   1636: struct ModifyWord_SubstRegexArgs {
1.703     rillig   1637:        regex_t re;
                   1638:        size_t nsub;
1.921     rillig   1639:        const char *replace;
1.927     rillig   1640:        PatternFlags pflags;
1.895     rillig   1641:        bool matched;
1.541     rillig   1642: };
1.291     rillig   1643:
1.778     rillig   1644: /*
                   1645:  * Callback for ModifyWords to implement the :C/from/to/ modifier.
                   1646:  * Perform a regex substitution on the given word.
                   1647:  */
1.278     rillig   1648: static void
1.919     rillig   1649: ModifyWord_SubstRegex(Substring word, SepBuf *buf, void *data)
1.16      christos 1650: {
1.704     rillig   1651:        struct ModifyWord_SubstRegexArgs *args = data;
                   1652:        int xrv;
1.919     rillig   1653:        const char *wp;
1.704     rillig   1654:        int flags = 0;
                   1655:        regmatch_t m[10];
1.16      christos 1656:
1.919     rillig   1657:        assert(word.end[0] == '\0');    /* assume null-terminated word */
                   1658:        wp = word.start;
1.936     rillig   1659:        if (args->pflags.subOnce && args->matched)
                   1660:                goto no_match;
1.307     rillig   1661:
1.935     rillig   1662: again:
1.704     rillig   1663:        xrv = regexec(&args->re, wp, args->nsub, m, flags);
1.935     rillig   1664:        if (xrv == 0)
                   1665:                goto ok;
                   1666:        if (xrv != REG_NOMATCH)
                   1667:                VarREError(xrv, &args->re, "Unexpected regex error");
1.936     rillig   1668: no_match:
                   1669:        SepBuf_AddStr(buf, wp);
                   1670:        return;
1.16      christos 1671:
1.935     rillig   1672: ok:
                   1673:        args->matched = true;
                   1674:        SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
1.704     rillig   1675:
1.937     rillig   1676:        RegexReplace(args->replace, buf, wp, m, args->nsub);
1.445     rillig   1677:
1.948   ! rillig   1678:        wp += (size_t)m[0].rm_eo;
1.935     rillig   1679:        if (args->pflags.subGlobal) {
                   1680:                flags |= REG_NOTBOL;
                   1681:                if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
                   1682:                        SepBuf_AddBytes(buf, wp, 1);
                   1683:                        wp++;
1.704     rillig   1684:                }
                   1685:                if (*wp != '\0')
1.935     rillig   1686:                        goto again;
                   1687:        }
                   1688:        if (*wp != '\0')
1.704     rillig   1689:                SepBuf_AddStr(buf, wp);
1.16      christos 1690: }
1.17      christos 1691: #endif
1.16      christos 1692:
                   1693:
1.541     rillig   1694: struct ModifyWord_LoopArgs {
1.806     rillig   1695:        GNode *scope;
1.928     rillig   1696:        const char *var;        /* name of the temporary variable */
                   1697:        const char *body;       /* string to expand */
1.906     rillig   1698:        VarEvalMode emode;
1.541     rillig   1699: };
1.291     rillig   1700:
                   1701: /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1.278     rillig   1702: static void
1.919     rillig   1703: ModifyWord_Loop(Substring word, SepBuf *buf, void *data)
1.40      sjg      1704: {
1.703     rillig   1705:        const struct ModifyWord_LoopArgs *args;
                   1706:        char *s;
1.412     rillig   1707:
1.919     rillig   1708:        if (Substring_IsEmpty(word))
1.703     rillig   1709:                return;
1.278     rillig   1710:
1.703     rillig   1711:        args = data;
1.919     rillig   1712:        assert(word.end[0] == '\0');    /* assume null-terminated word */
1.928     rillig   1713:        Var_SetWithFlags(args->scope, args->var, word.start,
1.919     rillig   1714:            VAR_SET_NO_EXPORT);
1.928     rillig   1715:        (void)Var_Subst(args->body, args->scope, args->emode, &s);
1.703     rillig   1716:        /* TODO: handle errors */
1.64      sjg      1717:
1.919     rillig   1718:        assert(word.end[0] == '\0');    /* assume null-terminated word */
1.708     rillig   1719:        DEBUG4(VAR, "ModifyWord_Loop: "
                   1720:                    "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n",
1.928     rillig   1721:            word.start, args->var, args->body, s);
1.703     rillig   1722:
                   1723:        if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
1.895     rillig   1724:                buf->needSep = false;
1.703     rillig   1725:        SepBuf_AddStr(buf, s);
                   1726:        free(s);
1.40      sjg      1727: }
                   1728:
1.81      sjg      1729:
1.778     rillig   1730: /*
                   1731:  * The :[first..last] modifier selects words from the expression.
                   1732:  * It can also reverse the words.
                   1733:  */
1.81      sjg      1734: static char *
1.840     rillig   1735: VarSelectWords(const char *str, int first, int last,
1.895     rillig   1736:               char sep, bool oneBigWord)
1.81      sjg      1737: {
1.703     rillig   1738:        Words words;
                   1739:        int len, start, end, step;
                   1740:        int i;
                   1741:
                   1742:        SepBuf buf;
                   1743:        SepBuf_Init(&buf, sep);
                   1744:
                   1745:        if (oneBigWord) {
                   1746:                /* fake what Str_Words() would do if there were only one word */
                   1747:                words.len = 1;
                   1748:                words.words = bmake_malloc(
                   1749:                    (words.len + 1) * sizeof(words.words[0]));
                   1750:                words.freeIt = bmake_strdup(str);
                   1751:                words.words[0] = words.freeIt;
                   1752:                words.words[1] = NULL;
                   1753:        } else {
1.895     rillig   1754:                words = Str_Words(str, false);
1.703     rillig   1755:        }
1.81      sjg      1756:
1.703     rillig   1757:        /*
                   1758:         * Now sanitize the given range.  If first or last are negative,
                   1759:         * convert them to the positive equivalents (-1 gets converted to len,
                   1760:         * -2 gets converted to (len - 1), etc.).
                   1761:         */
                   1762:        len = (int)words.len;
                   1763:        if (first < 0)
                   1764:                first += len + 1;
                   1765:        if (last < 0)
                   1766:                last += len + 1;
                   1767:
                   1768:        /* We avoid scanning more of the list than we need to. */
                   1769:        if (first > last) {
                   1770:                start = (first > len ? len : first) - 1;
                   1771:                end = last < 1 ? 0 : last - 1;
                   1772:                step = -1;
                   1773:        } else {
                   1774:                start = first < 1 ? 0 : first - 1;
                   1775:                end = last > len ? len : last;
                   1776:                step = 1;
                   1777:        }
1.81      sjg      1778:
1.703     rillig   1779:        for (i = start; (step < 0) == (i >= end); i += step) {
                   1780:                SepBuf_AddStr(&buf, words.words[i]);
                   1781:                SepBuf_Sep(&buf);
                   1782:        }
1.81      sjg      1783:
1.703     rillig   1784:        Words_Free(words);
1.81      sjg      1785:
1.784     rillig   1786:        return SepBuf_DoneData(&buf);
1.81      sjg      1787: }
                   1788:
1.156     sjg      1789:
1.778     rillig   1790: /*
                   1791:  * Callback for ModifyWords to implement the :tA modifier.
                   1792:  * Replace each word with the result of realpath() if successful.
                   1793:  */
1.779     rillig   1794: /*ARGSUSED*/
1.278     rillig   1795: static void
1.919     rillig   1796: ModifyWord_Realpath(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.156     sjg      1797: {
1.703     rillig   1798:        struct stat st;
                   1799:        char rbuf[MAXPATHLEN];
1.919     rillig   1800:        const char *rp;
1.231     rillig   1801:
1.919     rillig   1802:        assert(word.end[0] == '\0');    /* assume null-terminated word */
                   1803:        rp = cached_realpath(word.start, rbuf);
1.703     rillig   1804:        if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1.919     rillig   1805:                SepBuf_AddStr(buf, rp);
                   1806:        else
                   1807:                SepBuf_AddSubstring(buf, word);
1.156     sjg      1808: }
                   1809:
1.35      christos 1810:
1.403     rillig   1811: static char *
1.479     rillig   1812: Words_JoinFree(Words words)
1.403     rillig   1813: {
1.703     rillig   1814:        Buffer buf;
                   1815:        size_t i;
1.412     rillig   1816:
1.703     rillig   1817:        Buf_Init(&buf);
1.403     rillig   1818:
1.703     rillig   1819:        for (i = 0; i < words.len; i++) {
                   1820:                if (i != 0) {
1.891     rillig   1821:                        /* XXX: Use ch->sep instead of ' ', for consistency. */
1.703     rillig   1822:                        Buf_AddByte(&buf, ' ');
                   1823:                }
                   1824:                Buf_AddStr(&buf, words.words[i]);
                   1825:        }
1.403     rillig   1826:
1.703     rillig   1827:        Words_Free(words);
1.403     rillig   1828:
1.784     rillig   1829:        return Buf_DoneData(&buf);
1.403     rillig   1830: }
                   1831:
1.55      christos 1832:
1.778     rillig   1833: /*
                   1834:  * Quote shell meta-characters and space characters in the string.
                   1835:  * If quoteDollar is set, also quote and double any '$' characters.
                   1836:  */
1.924     rillig   1837: static void
                   1838: VarQuote(const char *str, bool quoteDollar, LazyBuf *buf)
1.16      christos 1839: {
1.924     rillig   1840:        const char *p;
1.193     christos 1841:
1.924     rillig   1842:        LazyBuf_Init(buf, str);
                   1843:        for (p = str; *p != '\0'; p++) {
                   1844:                if (*p == '\n') {
1.703     rillig   1845:                        const char *newline = Shell_GetNewline();
                   1846:                        if (newline == NULL)
                   1847:                                newline = "\\\n";
1.924     rillig   1848:                        LazyBuf_AddStr(buf, newline);
1.703     rillig   1849:                        continue;
                   1850:                }
1.924     rillig   1851:                if (ch_isspace(*p) || is_shell_metachar((unsigned char)*p))
                   1852:                        LazyBuf_Add(buf, '\\');
                   1853:                LazyBuf_Add(buf, *p);
                   1854:                if (quoteDollar && *p == '$')
                   1855:                        LazyBuf_AddStr(buf, "\\$");
1.193     christos 1856:        }
1.16      christos 1857: }
                   1858:
1.778     rillig   1859: /*
                   1860:  * Compute the 32-bit hash of the given string, using the MurmurHash3
                   1861:  * algorithm. Output is encoded as 8 hex digits, in Little Endian order.
                   1862:  */
1.163     joerg    1863: static char *
1.252     rillig   1864: VarHash(const char *str)
1.163     joerg    1865: {
1.703     rillig   1866:        static const char hexdigits[16] = "0123456789abcdef";
                   1867:        const unsigned char *ustr = (const unsigned char *)str;
                   1868:
                   1869:        uint32_t h = 0x971e137bU;
                   1870:        uint32_t c1 = 0x95543787U;
                   1871:        uint32_t c2 = 0x2ad7eb25U;
                   1872:        size_t len2 = strlen(str);
1.163     joerg    1873:
1.703     rillig   1874:        char *buf;
                   1875:        size_t i;
                   1876:
                   1877:        size_t len;
1.781     rillig   1878:        for (len = len2; len != 0;) {
1.703     rillig   1879:                uint32_t k = 0;
                   1880:                switch (len) {
                   1881:                default:
                   1882:                        k = ((uint32_t)ustr[3] << 24) |
                   1883:                            ((uint32_t)ustr[2] << 16) |
                   1884:                            ((uint32_t)ustr[1] << 8) |
                   1885:                            (uint32_t)ustr[0];
                   1886:                        len -= 4;
                   1887:                        ustr += 4;
                   1888:                        break;
                   1889:                case 3:
                   1890:                        k |= (uint32_t)ustr[2] << 16;
                   1891:                        /* FALLTHROUGH */
                   1892:                case 2:
                   1893:                        k |= (uint32_t)ustr[1] << 8;
                   1894:                        /* FALLTHROUGH */
                   1895:                case 1:
                   1896:                        k |= (uint32_t)ustr[0];
                   1897:                        len = 0;
                   1898:                }
                   1899:                c1 = c1 * 5 + 0x7b7d159cU;
                   1900:                c2 = c2 * 5 + 0x6bce6396U;
                   1901:                k *= c1;
                   1902:                k = (k << 11) ^ (k >> 21);
                   1903:                k *= c2;
                   1904:                h = (h << 13) ^ (h >> 19);
                   1905:                h = h * 5 + 0x52dce729U;
                   1906:                h ^= k;
                   1907:        }
                   1908:        h ^= (uint32_t)len2;
                   1909:        h *= 0x85ebca6b;
                   1910:        h ^= h >> 13;
                   1911:        h *= 0xc2b2ae35;
                   1912:        h ^= h >> 16;
                   1913:
                   1914:        buf = bmake_malloc(9);
                   1915:        for (i = 0; i < 8; i++) {
                   1916:                buf[i] = hexdigits[h & 0x0f];
                   1917:                h >>= 4;
                   1918:        }
                   1919:        buf[8] = '\0';
                   1920:        return buf;
1.163     joerg    1921: }
                   1922:
1.164     sjg      1923: static char *
1.895     rillig   1924: VarStrftime(const char *fmt, bool zulu, time_t tim)
1.164     sjg      1925: {
1.703     rillig   1926:        char buf[BUFSIZ];
1.164     sjg      1927:
1.703     rillig   1928:        if (tim == 0)
                   1929:                time(&tim);
                   1930:        if (*fmt == '\0')
                   1931:                fmt = "%c";
                   1932:        strftime(buf, sizeof buf, fmt, zulu ? gmtime(&tim) : localtime(&tim));
1.235     rillig   1933:
1.703     rillig   1934:        buf[sizeof buf - 1] = '\0';
                   1935:        return bmake_strdup(buf);
1.164     sjg      1936: }
                   1937:
1.687     rillig   1938: /*
                   1939:  * The ApplyModifier functions take an expression that is being evaluated.
1.830     rillig   1940:  * Their task is to apply a single modifier to the expression.  This involves
                   1941:  * parsing the modifier, evaluating it and finally updating the value of the
                   1942:  * expression.
1.467     rillig   1943:  *
                   1944:  * Parsing the modifier
                   1945:  *
                   1946:  * If parsing succeeds, the parsing position *pp is updated to point to the
                   1947:  * first character following the modifier, which typically is either ':' or
1.891     rillig   1948:  * ch->endc.  The modifier doesn't have to check for this delimiter character,
1.687     rillig   1949:  * this is done by ApplyModifiers.
                   1950:  *
                   1951:  * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not
                   1952:  * need to be followed by a ':' or endc; this was an unintended mistake.
1.467     rillig   1953:  *
                   1954:  * If parsing fails because of a missing delimiter (as in the :S, :C or :@
1.530     rillig   1955:  * modifiers), return AMR_CLEANUP.
1.467     rillig   1956:  *
                   1957:  * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
                   1958:  * try the SysV modifier ${VAR:from=to} as fallback.  This should only be
                   1959:  * done as long as there have been no side effects from evaluating nested
                   1960:  * variables, to avoid evaluating them more than once.  In this case, the
1.687     rillig   1961:  * parsing position may or may not be updated.  (XXX: Why not? The original
                   1962:  * parsing position is well-known in ApplyModifiers.)
1.467     rillig   1963:  *
                   1964:  * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
                   1965:  * as a fallback, either issue an error message using Error or Parse_Error
                   1966:  * and then return AMR_CLEANUP, or return AMR_BAD for the default error
                   1967:  * message.  Both of these return values will stop processing the variable
                   1968:  * expression.  (XXX: As of 2020-08-23, evaluation of the whole string
                   1969:  * continues nevertheless after skipping a few bytes, which essentially is
1.830     rillig   1970:  * undefined behavior.  Not in the sense of C, but still the resulting string
                   1971:  * is garbage.)
1.467     rillig   1972:  *
                   1973:  * Evaluating the modifier
                   1974:  *
                   1975:  * After parsing, the modifier is evaluated.  The side effects from evaluating
                   1976:  * nested variable expressions in the modifier text often already happen
1.830     rillig   1977:  * during parsing though.  For most modifiers this doesn't matter since their
                   1978:  * only noticeable effect is that the update the value of the expression.
                   1979:  * Some modifiers such as ':sh' or '::=' have noticeable side effects though.
1.467     rillig   1980:  *
                   1981:  * Evaluating the modifier usually takes the current value of the variable
1.891     rillig   1982:  * expression from ch->expr->value, or the variable name from ch->var->name
1.824     rillig   1983:  * and stores the result back in expr->value via Expr_SetValueOwn or
1.821     rillig   1984:  * Expr_SetValueRefer.
1.467     rillig   1985:  *
                   1986:  * If evaluating fails (as of 2020-08-23), an error message is printed using
                   1987:  * Error.  This function has no side-effects, it really just prints the error
                   1988:  * message.  Processing the expression continues as if everything were ok.
                   1989:  * XXX: This should be fixed by adding proper error handling to Var_Subst,
                   1990:  * Var_Parse, ApplyModifiers and ModifyWords.
                   1991:  *
                   1992:  * Housekeeping
                   1993:  *
1.528     rillig   1994:  * Some modifiers such as :D and :U turn undefined expressions into defined
1.821     rillig   1995:  * expressions (see Expr_Define).
1.467     rillig   1996:  *
                   1997:  * Some modifiers need to free some memory.
1.350     rillig   1998:  */
1.409     rillig   1999:
1.825     rillig   2000: typedef enum ExprDefined {
1.816     rillig   2001:        /* The variable expression is based on a regular, defined variable. */
1.825     rillig   2002:        DEF_REGULAR,
1.703     rillig   2003:        /* The variable expression is based on an undefined variable. */
1.825     rillig   2004:        DEF_UNDEF,
1.703     rillig   2005:        /*
                   2006:         * The variable expression started as an undefined expression, but one
1.825     rillig   2007:         * of the modifiers (such as ':D' or ':U') has turned the expression
                   2008:         * from undefined to defined.
1.703     rillig   2009:         */
1.825     rillig   2010:        DEF_DEFINED
                   2011: } ExprDefined;
1.527     rillig   2012:
1.825     rillig   2013: static const char *const ExprDefined_Name[] = {
1.826     rillig   2014:        "regular",
                   2015:        "undefined",
                   2016:        "defined"
1.789     rillig   2017: };
1.527     rillig   2018:
1.897     rillig   2019: #if __STDC_VERSION__ >= 199901L
                   2020: #define const_member const
                   2021: #else
                   2022: #define const_member /* no const possible */
                   2023: #endif
                   2024:
1.823     rillig   2025: /* A variable expression such as $@ or ${VAR:Mpattern:Q}. */
                   2026: typedef struct Expr {
1.898     rillig   2027:        const char *name;
1.823     rillig   2028:        FStr value;
1.906     rillig   2029:        VarEvalMode const_member emode;
1.897     rillig   2030:        GNode *const_member scope;
1.825     rillig   2031:        ExprDefined defined;
1.823     rillig   2032: } Expr;
                   2033:
                   2034: /*
1.890     rillig   2035:  * The status of applying a chain of modifiers to an expression.
1.823     rillig   2036:  *
1.890     rillig   2037:  * The modifiers of an expression are broken into chains of modifiers,
1.892     rillig   2038:  * starting a new nested chain whenever an indirect modifier starts.  There
                   2039:  * are at most 2 nesting levels: the outer one for the direct modifiers, and
                   2040:  * the inner one for the indirect modifiers.
1.890     rillig   2041:  *
1.892     rillig   2042:  * For example, the expression ${VAR:M*:${IND1}:${IND2}:O:u} has 3 chains of
1.889     rillig   2043:  * modifiers:
                   2044:  *
1.892     rillig   2045:  *     Chain 1 starts with the single modifier ':M*'.
                   2046:  *       Chain 2 starts with all modifiers from ${IND1}.
                   2047:  *       Chain 2 ends at the ':' between ${IND1} and ${IND2}.
1.893     rillig   2048:  *       Chain 3 starts with all modifiers from ${IND2}.
                   2049:  *       Chain 3 ends at the ':' after ${IND2}.
1.942     rillig   2050:  *     Chain 1 continues with the 2 modifiers ':O' and ':u'.
1.892     rillig   2051:  *     Chain 1 ends at the final '}' of the expression.
1.890     rillig   2052:  *
1.892     rillig   2053:  * After such a chain ends, its properties no longer have any effect.
1.889     rillig   2054:  *
1.887     rillig   2055:  * It may or may not have been intended that 'defined' has scope Expr while
                   2056:  * 'sep' and 'oneBigWord' have smaller scope.
1.823     rillig   2057:  *
                   2058:  * See varmod-indirect.mk.
                   2059:  */
1.891     rillig   2060: typedef struct ModChain {
1.823     rillig   2061:        Expr *expr;
1.703     rillig   2062:        /* '\0' or '{' or '(' */
1.897     rillig   2063:        char const_member startc;
1.703     rillig   2064:        /* '\0' or '}' or ')' */
1.897     rillig   2065:        char const_member endc;
1.703     rillig   2066:        /* Word separator in expansions (see the :ts modifier). */
                   2067:        char sep;
                   2068:        /*
1.895     rillig   2069:         * True if some modifiers that otherwise split the variable value
1.703     rillig   2070:         * into words, like :S and :C, treat the variable value as a single
                   2071:         * big word, possibly containing spaces.
                   2072:         */
1.895     rillig   2073:        bool oneBigWord;
1.891     rillig   2074: } ModChain;
1.236     rillig   2075:
1.525     rillig   2076: static void
1.812     rillig   2077: Expr_Define(Expr *expr)
1.525     rillig   2078: {
1.825     rillig   2079:        if (expr->defined == DEF_UNDEF)
                   2080:                expr->defined = DEF_DEFINED;
1.525     rillig   2081: }
                   2082:
1.813     rillig   2083: static void
1.921     rillig   2084: Expr_SetValue(Expr *expr, FStr value)
                   2085: {
                   2086:        FStr_Done(&expr->value);
                   2087:        expr->value = value;
                   2088: }
                   2089:
                   2090: static void
1.813     rillig   2091: Expr_SetValueOwn(Expr *expr, char *value)
                   2092: {
1.921     rillig   2093:        Expr_SetValue(expr, FStr_InitOwn(value));
1.813     rillig   2094: }
                   2095:
                   2096: static void
                   2097: Expr_SetValueRefer(Expr *expr, const char *value)
                   2098: {
1.921     rillig   2099:        Expr_SetValue(expr, FStr_InitRefer(value));
1.813     rillig   2100: }
                   2101:
1.905     rillig   2102: static bool
                   2103: Expr_ShouldEval(const Expr *expr)
                   2104: {
1.906     rillig   2105:        return VarEvalMode_ShouldEval(expr->emode);
1.905     rillig   2106: }
                   2107:
                   2108: static bool
                   2109: ModChain_ShouldEval(const ModChain *ch)
                   2110: {
                   2111:        return Expr_ShouldEval(ch->expr);
                   2112: }
                   2113:
                   2114:
1.578     rillig   2115: typedef enum ApplyModifierResult {
1.703     rillig   2116:        /* Continue parsing */
                   2117:        AMR_OK,
1.830     rillig   2118:        /* Not a match, try other modifiers as well. */
1.703     rillig   2119:        AMR_UNKNOWN,
1.830     rillig   2120:        /* Error out with "Bad modifier" message. */
1.703     rillig   2121:        AMR_BAD,
1.830     rillig   2122:        /* Error out without the standard error message. */
1.703     rillig   2123:        AMR_CLEANUP
1.356     rillig   2124: } ApplyModifierResult;
                   2125:
1.703     rillig   2126: /*
                   2127:  * Allow backslashes to escape the delimiter, $, and \, but don't touch other
                   2128:  * backslashes.
                   2129:  */
1.895     rillig   2130: static bool
1.620     rillig   2131: IsEscapedModifierPart(const char *p, char delim,
                   2132:                      struct ModifyWord_SubstArgs *subst)
                   2133: {
1.703     rillig   2134:        if (p[0] != '\\')
1.895     rillig   2135:                return false;
1.703     rillig   2136:        if (p[1] == delim || p[1] == '\\' || p[1] == '$')
1.895     rillig   2137:                return true;
1.703     rillig   2138:        return p[1] == '&' && subst != NULL;
1.620     rillig   2139: }
                   2140:
1.934     rillig   2141: /* See ParseModifierPart for the documentation. */
1.531     rillig   2142: static VarParseResult
1.760     rillig   2143: ParseModifierPartSubst(
1.703     rillig   2144:     const char **pp,
                   2145:     char delim,
1.906     rillig   2146:     VarEvalMode emode,
1.891     rillig   2147:     ModChain *ch,
1.921     rillig   2148:     LazyBuf *part,
1.934     rillig   2149:     /* For the first part of the modifier ':S', set anchorEnd if the last
                   2150:      * character of the pattern is a $. */
1.927     rillig   2151:     PatternFlags *out_pflags,
1.703     rillig   2152:     /* For the second part of the :S modifier, allow ampersands to be
                   2153:      * escaped and replace unescaped ampersands with subst->lhs. */
1.541     rillig   2154:     struct ModifyWord_SubstArgs *subst
1.704     rillig   2155: )
                   2156: {
                   2157:        const char *p;
                   2158:
1.921     rillig   2159:        p = *pp;
1.923     rillig   2160:        LazyBuf_Init(part, p);
1.704     rillig   2161:
                   2162:        /*
                   2163:         * Skim through until the matching delimiter is found; pick up
                   2164:         * variable expressions on the way.
                   2165:         */
                   2166:        while (*p != '\0' && *p != delim) {
                   2167:                const char *varstart;
                   2168:
                   2169:                if (IsEscapedModifierPart(p, delim, subst)) {
1.921     rillig   2170:                        LazyBuf_Add(part, p[1]);
1.704     rillig   2171:                        p += 2;
                   2172:                        continue;
                   2173:                }
                   2174:
                   2175:                if (*p != '$') {        /* Unescaped, simple text */
                   2176:                        if (subst != NULL && *p == '&')
1.921     rillig   2177:                                LazyBuf_AddSubstring(part, subst->lhs);
1.704     rillig   2178:                        else
1.921     rillig   2179:                                LazyBuf_Add(part, *p);
1.704     rillig   2180:                        p++;
                   2181:                        continue;
                   2182:                }
1.529     rillig   2183:
1.704     rillig   2184:                if (p[1] == delim) {    /* Unescaped $ at end of pattern */
                   2185:                        if (out_pflags != NULL)
1.895     rillig   2186:                                out_pflags->anchorEnd = true;
1.704     rillig   2187:                        else
1.921     rillig   2188:                                LazyBuf_Add(part, *p);
1.704     rillig   2189:                        p++;
                   2190:                        continue;
                   2191:                }
1.529     rillig   2192:
1.906     rillig   2193:                if (VarEvalMode_ShouldEval(emode)) {
                   2194:                        /* Nested variable, evaluated */
1.704     rillig   2195:                        const char *nested_p = p;
1.743     rillig   2196:                        FStr nested_val;
1.529     rillig   2197:
1.891     rillig   2198:                        (void)Var_Parse(&nested_p, ch->expr->scope,
1.906     rillig   2199:                            VarEvalMode_WithoutKeepDollar(emode), &nested_val);
1.704     rillig   2200:                        /* TODO: handle errors */
1.921     rillig   2201:                        LazyBuf_AddStr(part, nested_val.str);
1.743     rillig   2202:                        FStr_Done(&nested_val);
1.704     rillig   2203:                        p += nested_p - p;
                   2204:                        continue;
                   2205:                }
                   2206:
1.705     rillig   2207:                /*
                   2208:                 * XXX: This whole block is very similar to Var_Parse without
1.917     rillig   2209:                 * VARE_WANTRES.  There may be subtle edge cases
1.885     rillig   2210:                 * though that are not yet covered in the unit tests and that
                   2211:                 * are parsed differently, depending on whether they are
                   2212:                 * evaluated or not.
1.704     rillig   2213:                 *
                   2214:                 * This subtle difference is not documented in the manual
                   2215:                 * page, neither is the difference between parsing :D and
                   2216:                 * :M documented. No code should ever depend on these
                   2217:                 * details, but who knows.
                   2218:                 */
                   2219:
1.705     rillig   2220:                varstart = p;   /* Nested variable, only parsed */
1.704     rillig   2221:                if (p[1] == '(' || p[1] == '{') {
                   2222:                        /*
                   2223:                         * Find the end of this variable reference
                   2224:                         * and suck it in without further ado.
                   2225:                         * It will be interpreted later.
                   2226:                         */
                   2227:                        char startc = p[1];
                   2228:                        int endc = startc == '(' ? ')' : '}';
                   2229:                        int depth = 1;
                   2230:
                   2231:                        for (p += 2; *p != '\0' && depth > 0; p++) {
                   2232:                                if (p[-1] != '\\') {
                   2233:                                        if (*p == startc)
                   2234:                                                depth++;
                   2235:                                        if (*p == endc)
                   2236:                                                depth--;
                   2237:                                }
                   2238:                        }
1.921     rillig   2239:                        LazyBuf_AddBytesBetween(part, varstart, p);
1.704     rillig   2240:                } else {
1.921     rillig   2241:                        LazyBuf_Add(part, *varstart);
1.704     rillig   2242:                        p++;
1.529     rillig   2243:                }
                   2244:        }
                   2245:
1.704     rillig   2246:        if (*p != delim) {
                   2247:                *pp = p;
1.842     rillig   2248:                Error("Unfinished modifier for \"%s\" ('%c' missing)",
1.898     rillig   2249:                    ch->expr->name, delim);
1.921     rillig   2250:                LazyBuf_Done(part);
1.767     rillig   2251:                return VPR_ERR;
1.704     rillig   2252:        }
                   2253:
1.787     rillig   2254:        *pp = p + 1;
1.529     rillig   2255:
1.921     rillig   2256:        {
                   2257:                Substring sub = LazyBuf_Get(part);
                   2258:                DEBUG2(VAR, "Modifier part: \"%.*s\"\n",
                   2259:                    (int)Substring_Length(sub), sub.start);
                   2260:        }
                   2261:
1.704     rillig   2262:        return VPR_OK;
1.529     rillig   2263: }
                   2264:
1.760     rillig   2265: /*
                   2266:  * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
                   2267:  * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
                   2268:  * including the next unescaped delimiter.  The delimiter, as well as the
                   2269:  * backslash or the dollar, can be escaped with a backslash.
                   2270:  *
1.934     rillig   2271:  * Return VPR_OK if parsing succeeded, together with the parsed (and possibly
                   2272:  * expanded) part.  In that case, pp points right after the delimiter.  The
                   2273:  * delimiter is not included in the part though.
1.760     rillig   2274:  */
                   2275: static VarParseResult
                   2276: ParseModifierPart(
                   2277:     /* The parsing position, updated upon return */
                   2278:     const char **pp,
                   2279:     /* Parsing stops at this delimiter */
                   2280:     char delim,
1.906     rillig   2281:     /* Mode for evaluating nested variables. */
                   2282:     VarEvalMode emode,
1.891     rillig   2283:     ModChain *ch,
1.921     rillig   2284:     LazyBuf *part
1.760     rillig   2285: )
                   2286: {
1.921     rillig   2287:        return ParseModifierPartSubst(pp, delim, emode, ch, part, NULL, NULL);
1.760     rillig   2288: }
                   2289:
1.895     rillig   2290: MAKE_INLINE bool
1.891     rillig   2291: IsDelimiter(char c, const ModChain *ch)
1.859     rillig   2292: {
1.891     rillig   2293:        return c == ':' || c == ch->endc;
1.859     rillig   2294: }
                   2295:
1.400     rillig   2296: /* Test whether mod starts with modname, followed by a delimiter. */
1.895     rillig   2297: MAKE_INLINE bool
1.891     rillig   2298: ModMatch(const char *mod, const char *modname, const ModChain *ch)
1.340     rillig   2299: {
1.703     rillig   2300:        size_t n = strlen(modname);
1.891     rillig   2301:        return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], ch);
1.340     rillig   2302: }
                   2303:
1.400     rillig   2304: /* Test whether mod starts with modname, followed by a delimiter or '='. */
1.895     rillig   2305: MAKE_INLINE bool
1.891     rillig   2306: ModMatchEq(const char *mod, const char *modname, const ModChain *ch)
1.340     rillig   2307: {
1.703     rillig   2308:        size_t n = strlen(modname);
                   2309:        return strncmp(mod, modname, n) == 0 &&
1.891     rillig   2310:               (IsDelimiter(mod[n], ch) || mod[n] == '=');
1.340     rillig   2311: }
1.236     rillig   2312:
1.895     rillig   2313: static bool
1.635     rillig   2314: TryParseIntBase0(const char **pp, int *out_num)
                   2315: {
1.703     rillig   2316:        char *end;
                   2317:        long n;
1.635     rillig   2318:
1.703     rillig   2319:        errno = 0;
                   2320:        n = strtol(*pp, &end, 0);
1.865     rillig   2321:
                   2322:        if (end == *pp)
1.895     rillig   2323:                return false;
1.703     rillig   2324:        if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
1.895     rillig   2325:                return false;
1.703     rillig   2326:        if (n < INT_MIN || n > INT_MAX)
1.895     rillig   2327:                return false;
1.635     rillig   2328:
1.703     rillig   2329:        *pp = end;
                   2330:        *out_num = (int)n;
1.895     rillig   2331:        return true;
1.635     rillig   2332: }
                   2333:
1.895     rillig   2334: static bool
1.635     rillig   2335: TryParseSize(const char **pp, size_t *out_num)
                   2336: {
1.703     rillig   2337:        char *end;
                   2338:        unsigned long n;
1.635     rillig   2339:
1.703     rillig   2340:        if (!ch_isdigit(**pp))
1.895     rillig   2341:                return false;
1.635     rillig   2342:
1.703     rillig   2343:        errno = 0;
                   2344:        n = strtoul(*pp, &end, 10);
                   2345:        if (n == ULONG_MAX && errno == ERANGE)
1.895     rillig   2346:                return false;
1.703     rillig   2347:        if (n > SIZE_MAX)
1.895     rillig   2348:                return false;
1.635     rillig   2349:
1.703     rillig   2350:        *pp = end;
                   2351:        *out_num = (size_t)n;
1.895     rillig   2352:        return true;
1.635     rillig   2353: }
                   2354:
1.895     rillig   2355: static bool
1.635     rillig   2356: TryParseChar(const char **pp, int base, char *out_ch)
                   2357: {
1.703     rillig   2358:        char *end;
                   2359:        unsigned long n;
1.635     rillig   2360:
1.703     rillig   2361:        if (!ch_isalnum(**pp))
1.895     rillig   2362:                return false;
1.635     rillig   2363:
1.703     rillig   2364:        errno = 0;
                   2365:        n = strtoul(*pp, &end, base);
                   2366:        if (n == ULONG_MAX && errno == ERANGE)
1.895     rillig   2367:                return false;
1.703     rillig   2368:        if (n > UCHAR_MAX)
1.895     rillig   2369:                return false;
1.635     rillig   2370:
1.703     rillig   2371:        *pp = end;
                   2372:        *out_ch = (char)n;
1.895     rillig   2373:        return true;
1.635     rillig   2374: }
                   2375:
1.820     rillig   2376: /*
1.822     rillig   2377:  * Modify each word of the expression using the given function and place the
                   2378:  * result back in the expression.
1.820     rillig   2379:  */
                   2380: static void
1.891     rillig   2381: ModifyWords(ModChain *ch,
1.822     rillig   2382:            ModifyWordProc modifyWord, void *modifyWord_args,
1.895     rillig   2383:            bool oneBigWord)
1.820     rillig   2384: {
1.891     rillig   2385:        Expr *expr = ch->expr;
1.823     rillig   2386:        const char *val = expr->value.str;
1.820     rillig   2387:        SepBuf result;
1.920     rillig   2388:        SubstringWords words;
1.820     rillig   2389:        size_t i;
1.919     rillig   2390:        Substring word;
1.820     rillig   2391:
                   2392:        if (oneBigWord) {
1.891     rillig   2393:                SepBuf_Init(&result, ch->sep);
1.919     rillig   2394:                /* XXX: performance: Substring_InitStr calls strlen */
                   2395:                word = Substring_InitStr(val);
                   2396:                modifyWord(word, &result, modifyWord_args);
1.820     rillig   2397:                goto done;
                   2398:        }
                   2399:
1.920     rillig   2400:        words = Substring_Words(val, false);
1.820     rillig   2401:
                   2402:        DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n",
1.823     rillig   2403:            val, (unsigned)words.len);
1.820     rillig   2404:
1.891     rillig   2405:        SepBuf_Init(&result, ch->sep);
1.820     rillig   2406:        for (i = 0; i < words.len; i++) {
1.920     rillig   2407:                modifyWord(words.words[i], &result, modifyWord_args);
1.820     rillig   2408:                if (result.buf.len > 0)
                   2409:                        SepBuf_Sep(&result);
                   2410:        }
                   2411:
1.920     rillig   2412:        SubstringWords_Free(words);
1.820     rillig   2413:
                   2414: done:
1.823     rillig   2415:        Expr_SetValueOwn(expr, SepBuf_DoneData(&result));
1.820     rillig   2416: }
                   2417:
1.236     rillig   2418: /* :@var@...${var}...@ */
1.356     rillig   2419: static ApplyModifierResult
1.891     rillig   2420: ApplyModifier_Loop(const char **pp, ModChain *ch)
1.417     rillig   2421: {
1.891     rillig   2422:        Expr *expr = ch->expr;
1.703     rillig   2423:        struct ModifyWord_LoopArgs args;
                   2424:        char prev_sep;
                   2425:        VarParseResult res;
1.921     rillig   2426:        LazyBuf tvarBuf, strBuf;
                   2427:        FStr tvar, str;
1.703     rillig   2428:
1.823     rillig   2429:        args.scope = expr->scope;
1.703     rillig   2430:
                   2431:        (*pp)++;                /* Skip the first '@' */
1.921     rillig   2432:        res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &tvarBuf);
1.703     rillig   2433:        if (res != VPR_OK)
                   2434:                return AMR_CLEANUP;
1.921     rillig   2435:        tvar = LazyBuf_DoneGet(&tvarBuf);
1.928     rillig   2436:        args.var = tvar.str;
                   2437:        if (strchr(args.var, '$') != NULL) {
1.703     rillig   2438:                Parse_Error(PARSE_FATAL,
1.410     rillig   2439:                    "In the :@ modifier of \"%s\", the variable name \"%s\" "
                   2440:                    "must not contain a dollar.",
1.928     rillig   2441:                    expr->name, args.var);
1.703     rillig   2442:                return AMR_CLEANUP;
                   2443:        }
1.236     rillig   2444:
1.921     rillig   2445:        res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &strBuf);
1.703     rillig   2446:        if (res != VPR_OK)
                   2447:                return AMR_CLEANUP;
1.921     rillig   2448:        str = LazyBuf_DoneGet(&strBuf);
1.928     rillig   2449:        args.body = str.str;
1.703     rillig   2450:
1.906     rillig   2451:        if (!Expr_ShouldEval(expr))
1.870     rillig   2452:                goto done;
                   2453:
1.906     rillig   2454:        args.emode = VarEvalMode_WithoutKeepDollar(expr->emode);
1.891     rillig   2455:        prev_sep = ch->sep;
                   2456:        ch->sep = ' ';          /* XXX: should be ch->sep for consistency */
                   2457:        ModifyWords(ch, ModifyWord_Loop, &args, ch->oneBigWord);
                   2458:        ch->sep = prev_sep;
1.928     rillig   2459:        /* XXX: Consider restoring the previous value instead of deleting. */
                   2460:        Var_Delete(expr->scope, args.var);
1.870     rillig   2461:
                   2462: done:
1.921     rillig   2463:        FStr_Done(&tvar);
                   2464:        FStr_Done(&str);
1.703     rillig   2465:        return AMR_OK;
1.236     rillig   2466: }
                   2467:
                   2468: /* :Ddefined or :Uundefined */
1.356     rillig   2469: static ApplyModifierResult
1.891     rillig   2470: ApplyModifier_Defined(const char **pp, ModChain *ch)
1.236     rillig   2471: {
1.891     rillig   2472:        Expr *expr = ch->expr;
1.929     rillig   2473:        LazyBuf buf;
1.703     rillig   2474:        const char *p;
1.412     rillig   2475:
1.906     rillig   2476:        VarEvalMode emode = VARE_PARSE_ONLY;
                   2477:        if (Expr_ShouldEval(expr))
1.825     rillig   2478:                if ((**pp == 'D') == (expr->defined == DEF_REGULAR))
1.906     rillig   2479:                        emode = expr->emode;
1.703     rillig   2480:
                   2481:        p = *pp + 1;
1.929     rillig   2482:        LazyBuf_Init(&buf, p);
1.891     rillig   2483:        while (!IsDelimiter(*p, ch) && *p != '\0') {
1.703     rillig   2484:
                   2485:                /* XXX: This code is similar to the one in Var_Parse.
                   2486:                 * See if the code can be merged.
1.830     rillig   2487:                 * See also ApplyModifier_Match and ParseModifierPart. */
1.703     rillig   2488:
                   2489:                /* Escaped delimiter or other special character */
1.830     rillig   2490:                /* See Buf_AddEscaped in for.c. */
1.703     rillig   2491:                if (*p == '\\') {
                   2492:                        char c = p[1];
1.891     rillig   2493:                        if (IsDelimiter(c, ch) || c == '$' || c == '\\') {
1.929     rillig   2494:                                LazyBuf_Add(&buf, c);
1.703     rillig   2495:                                p += 2;
                   2496:                                continue;
                   2497:                        }
                   2498:                }
1.236     rillig   2499:
1.703     rillig   2500:                /* Nested variable expression */
                   2501:                if (*p == '$') {
1.743     rillig   2502:                        FStr nested_val;
1.466     rillig   2503:
1.906     rillig   2504:                        (void)Var_Parse(&p, expr->scope, emode, &nested_val);
1.703     rillig   2505:                        /* TODO: handle errors */
1.906     rillig   2506:                        if (Expr_ShouldEval(expr))
1.929     rillig   2507:                                LazyBuf_AddStr(&buf, nested_val.str);
1.743     rillig   2508:                        FStr_Done(&nested_val);
1.703     rillig   2509:                        continue;
                   2510:                }
1.687     rillig   2511:
1.703     rillig   2512:                /* Ordinary text */
1.929     rillig   2513:                LazyBuf_Add(&buf, *p);
1.703     rillig   2514:                p++;
1.466     rillig   2515:        }
1.703     rillig   2516:        *pp = p;
1.466     rillig   2517:
1.823     rillig   2518:        Expr_Define(expr);
1.236     rillig   2519:
1.906     rillig   2520:        if (VarEvalMode_ShouldEval(emode))
1.929     rillig   2521:                Expr_SetValue(expr, Substring_Str(LazyBuf_Get(&buf)));
1.821     rillig   2522:        else
1.929     rillig   2523:                LazyBuf_Done(&buf);
1.821     rillig   2524:
1.703     rillig   2525:        return AMR_OK;
1.236     rillig   2526: }
                   2527:
1.567     rillig   2528: /* :L */
                   2529: static ApplyModifierResult
1.891     rillig   2530: ApplyModifier_Literal(const char **pp, ModChain *ch)
1.567     rillig   2531: {
1.891     rillig   2532:        Expr *expr = ch->expr;
1.864     rillig   2533:
                   2534:        (*pp)++;
                   2535:
1.905     rillig   2536:        if (Expr_ShouldEval(expr)) {
1.872     rillig   2537:                Expr_Define(expr);
1.898     rillig   2538:                Expr_SetValueOwn(expr, bmake_strdup(expr->name));
1.872     rillig   2539:        }
1.864     rillig   2540:
1.703     rillig   2541:        return AMR_OK;
1.567     rillig   2542: }
                   2543:
1.895     rillig   2544: static bool
1.633     rillig   2545: TryParseTime(const char **pp, time_t *out_time)
1.631     rillig   2546: {
1.703     rillig   2547:        char *end;
                   2548:        unsigned long n;
1.631     rillig   2549:
1.703     rillig   2550:        if (!ch_isdigit(**pp))
1.895     rillig   2551:                return false;
1.631     rillig   2552:
1.703     rillig   2553:        errno = 0;
                   2554:        n = strtoul(*pp, &end, 10);
                   2555:        if (n == ULONG_MAX && errno == ERANGE)
1.895     rillig   2556:                return false;
1.631     rillig   2557:
1.703     rillig   2558:        *pp = end;
                   2559:        *out_time = (time_t)n;  /* ignore possible truncation for now */
1.895     rillig   2560:        return true;
1.631     rillig   2561: }
                   2562:
1.236     rillig   2563: /* :gmtime */
1.356     rillig   2564: static ApplyModifierResult
1.891     rillig   2565: ApplyModifier_Gmtime(const char **pp, ModChain *ch)
1.236     rillig   2566: {
1.703     rillig   2567:        time_t utc;
1.412     rillig   2568:
1.703     rillig   2569:        const char *mod = *pp;
1.891     rillig   2570:        if (!ModMatchEq(mod, "gmtime", ch))
1.703     rillig   2571:                return AMR_UNKNOWN;
                   2572:
                   2573:        if (mod[6] == '=') {
1.843     rillig   2574:                const char *p = mod + 7;
                   2575:                if (!TryParseTime(&p, &utc)) {
1.703     rillig   2576:                        Parse_Error(PARSE_FATAL,
1.761     rillig   2577:                            "Invalid time value: %s", mod + 7);
1.703     rillig   2578:                        return AMR_CLEANUP;
                   2579:                }
1.843     rillig   2580:                *pp = p;
1.703     rillig   2581:        } else {
                   2582:                utc = 0;
                   2583:                *pp = mod + 6;
1.631     rillig   2584:        }
1.864     rillig   2585:
1.905     rillig   2586:        if (ModChain_ShouldEval(ch))
1.891     rillig   2587:                Expr_SetValueOwn(ch->expr,
1.895     rillig   2588:                    VarStrftime(ch->expr->value.str, true, utc));
1.864     rillig   2589:
1.703     rillig   2590:        return AMR_OK;
1.236     rillig   2591: }
                   2592:
                   2593: /* :localtime */
1.505     rillig   2594: static ApplyModifierResult
1.891     rillig   2595: ApplyModifier_Localtime(const char **pp, ModChain *ch)
1.236     rillig   2596: {
1.703     rillig   2597:        time_t utc;
1.412     rillig   2598:
1.703     rillig   2599:        const char *mod = *pp;
1.891     rillig   2600:        if (!ModMatchEq(mod, "localtime", ch))
1.703     rillig   2601:                return AMR_UNKNOWN;
                   2602:
                   2603:        if (mod[9] == '=') {
1.843     rillig   2604:                const char *p = mod + 10;
                   2605:                if (!TryParseTime(&p, &utc)) {
1.703     rillig   2606:                        Parse_Error(PARSE_FATAL,
1.761     rillig   2607:                            "Invalid time value: %s", mod + 10);
1.703     rillig   2608:                        return AMR_CLEANUP;
                   2609:                }
1.843     rillig   2610:                *pp = p;
1.703     rillig   2611:        } else {
                   2612:                utc = 0;
                   2613:                *pp = mod + 9;
1.631     rillig   2614:        }
1.864     rillig   2615:
1.905     rillig   2616:        if (ModChain_ShouldEval(ch))
1.891     rillig   2617:                Expr_SetValueOwn(ch->expr,
1.895     rillig   2618:                    VarStrftime(ch->expr->value.str, false, utc));
1.864     rillig   2619:
1.703     rillig   2620:        return AMR_OK;
1.236     rillig   2621: }
                   2622:
                   2623: /* :hash */
1.356     rillig   2624: static ApplyModifierResult
1.891     rillig   2625: ApplyModifier_Hash(const char **pp, ModChain *ch)
1.236     rillig   2626: {
1.891     rillig   2627:        if (!ModMatch(*pp, "hash", ch))
1.703     rillig   2628:                return AMR_UNKNOWN;
1.864     rillig   2629:        *pp += 4;
1.340     rillig   2630:
1.905     rillig   2631:        if (ModChain_ShouldEval(ch))
1.891     rillig   2632:                Expr_SetValueOwn(ch->expr, VarHash(ch->expr->value.str));
1.864     rillig   2633:
1.703     rillig   2634:        return AMR_OK;
1.236     rillig   2635: }
                   2636:
                   2637: /* :P */
1.356     rillig   2638: static ApplyModifierResult
1.891     rillig   2639: ApplyModifier_Path(const char **pp, ModChain *ch)
1.236     rillig   2640: {
1.891     rillig   2641:        Expr *expr = ch->expr;
1.703     rillig   2642:        GNode *gn;
                   2643:        char *path;
1.412     rillig   2644:
1.864     rillig   2645:        (*pp)++;
                   2646:
1.905     rillig   2647:        if (!ModChain_ShouldEval(ch))
1.873     rillig   2648:                return AMR_OK;
                   2649:
1.823     rillig   2650:        Expr_Define(expr);
1.409     rillig   2651:
1.898     rillig   2652:        gn = Targ_FindNode(expr->name);
1.703     rillig   2653:        if (gn == NULL || gn->type & OP_NOPATH) {
                   2654:                path = NULL;
                   2655:        } else if (gn->path != NULL) {
                   2656:                path = bmake_strdup(gn->path);
                   2657:        } else {
                   2658:                SearchPath *searchPath = Suff_FindPath(gn);
1.898     rillig   2659:                path = Dir_FindFile(expr->name, searchPath);
1.703     rillig   2660:        }
                   2661:        if (path == NULL)
1.898     rillig   2662:                path = bmake_strdup(expr->name);
1.823     rillig   2663:        Expr_SetValueOwn(expr, path);
1.409     rillig   2664:
1.703     rillig   2665:        return AMR_OK;
1.236     rillig   2666: }
                   2667:
                   2668: /* :!cmd! */
1.356     rillig   2669: static ApplyModifierResult
1.891     rillig   2670: ApplyModifier_ShellCommand(const char **pp, ModChain *ch)
1.236     rillig   2671: {
1.891     rillig   2672:        Expr *expr = ch->expr;
1.703     rillig   2673:        const char *errfmt;
                   2674:        VarParseResult res;
1.921     rillig   2675:        LazyBuf cmdBuf;
                   2676:        FStr cmd;
1.703     rillig   2677:
                   2678:        (*pp)++;
1.921     rillig   2679:        res = ParseModifierPart(pp, '!', expr->emode, ch, &cmdBuf);
1.703     rillig   2680:        if (res != VPR_OK)
                   2681:                return AMR_CLEANUP;
1.921     rillig   2682:        cmd = LazyBuf_DoneGet(&cmdBuf);
                   2683:
1.703     rillig   2684:
                   2685:        errfmt = NULL;
1.905     rillig   2686:        if (Expr_ShouldEval(expr))
1.921     rillig   2687:                Expr_SetValueOwn(expr, Cmd_Exec(cmd.str, &errfmt));
1.703     rillig   2688:        else
1.823     rillig   2689:                Expr_SetValueRefer(expr, "");
1.703     rillig   2690:        if (errfmt != NULL)
1.921     rillig   2691:                Error(errfmt, cmd.str); /* XXX: why still return AMR_OK? */
                   2692:        FStr_Done(&cmd);
1.864     rillig   2693:        Expr_Define(expr);
1.274     rillig   2694:
1.703     rillig   2695:        return AMR_OK;
1.236     rillig   2696: }
                   2697:
1.778     rillig   2698: /*
                   2699:  * The :range modifier generates an integer sequence as long as the words.
                   2700:  * The :range=7 modifier generates an integer sequence from 1 to 7.
                   2701:  */
1.356     rillig   2702: static ApplyModifierResult
1.891     rillig   2703: ApplyModifier_Range(const char **pp, ModChain *ch)
1.236     rillig   2704: {
1.703     rillig   2705:        size_t n;
                   2706:        Buffer buf;
                   2707:        size_t i;
1.412     rillig   2708:
1.703     rillig   2709:        const char *mod = *pp;
1.891     rillig   2710:        if (!ModMatchEq(mod, "range", ch))
1.703     rillig   2711:                return AMR_UNKNOWN;
                   2712:
                   2713:        if (mod[5] == '=') {
                   2714:                const char *p = mod + 6;
                   2715:                if (!TryParseSize(&p, &n)) {
                   2716:                        Parse_Error(PARSE_FATAL,
1.844     rillig   2717:                            "Invalid number \"%s\" for ':range' modifier",
                   2718:                            mod + 6);
1.703     rillig   2719:                        return AMR_CLEANUP;
                   2720:                }
                   2721:                *pp = p;
                   2722:        } else {
                   2723:                n = 0;
                   2724:                *pp = mod + 5;
1.635     rillig   2725:        }
1.386     rillig   2726:
1.905     rillig   2727:        if (!ModChain_ShouldEval(ch))
1.873     rillig   2728:                return AMR_OK;
                   2729:
1.703     rillig   2730:        if (n == 0) {
1.895     rillig   2731:                Words words = Str_Words(ch->expr->value.str, false);
1.703     rillig   2732:                n = words.len;
                   2733:                Words_Free(words);
                   2734:        }
1.386     rillig   2735:
1.703     rillig   2736:        Buf_Init(&buf);
1.386     rillig   2737:
1.703     rillig   2738:        for (i = 0; i < n; i++) {
                   2739:                if (i != 0) {
1.891     rillig   2740:                        /* XXX: Use ch->sep instead of ' ', for consistency. */
1.703     rillig   2741:                        Buf_AddByte(&buf, ' ');
                   2742:                }
                   2743:                Buf_AddInt(&buf, 1 + (int)i);
                   2744:        }
1.386     rillig   2745:
1.891     rillig   2746:        Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf));
1.703     rillig   2747:        return AMR_OK;
1.236     rillig   2748: }
                   2749:
1.845     rillig   2750: /* Parse a ':M' or ':N' modifier. */
                   2751: static void
1.891     rillig   2752: ParseModifier_Match(const char **pp, const ModChain *ch,
1.845     rillig   2753:                    char **out_pattern)
1.236     rillig   2754: {
1.845     rillig   2755:        const char *mod = *pp;
1.891     rillig   2756:        Expr *expr = ch->expr;
1.895     rillig   2757:        bool copy = false;      /* pattern should be, or has been, copied */
                   2758:        bool needSubst = false;
1.703     rillig   2759:        const char *endpat;
                   2760:        char *pattern;
1.412     rillig   2761:
1.703     rillig   2762:        /*
                   2763:         * In the loop below, ignore ':' unless we are at (or back to) the
                   2764:         * original brace level.
                   2765:         * XXX: This will likely not work right if $() and ${} are intermixed.
                   2766:         */
1.845     rillig   2767:        /*
                   2768:         * XXX: This code is similar to the one in Var_Parse.
1.703     rillig   2769:         * See if the code can be merged.
1.845     rillig   2770:         * See also ApplyModifier_Defined.
                   2771:         */
1.703     rillig   2772:        int nest = 0;
                   2773:        const char *p;
                   2774:        for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) {
                   2775:                if (*p == '\\' &&
1.891     rillig   2776:                    (IsDelimiter(p[1], ch) || p[1] == ch->startc)) {
1.703     rillig   2777:                        if (!needSubst)
1.895     rillig   2778:                                copy = true;
1.703     rillig   2779:                        p++;
                   2780:                        continue;
                   2781:                }
                   2782:                if (*p == '$')
1.895     rillig   2783:                        needSubst = true;
1.703     rillig   2784:                if (*p == '(' || *p == '{')
                   2785:                        nest++;
                   2786:                if (*p == ')' || *p == '}') {
                   2787:                        nest--;
                   2788:                        if (nest < 0)
                   2789:                                break;
                   2790:                }
1.236     rillig   2791:        }
1.703     rillig   2792:        *pp = p;
                   2793:        endpat = p;
                   2794:
                   2795:        if (copy) {
                   2796:                char *dst;
                   2797:                const char *src;
                   2798:
                   2799:                /* Compress the \:'s out of the pattern. */
                   2800:                pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
                   2801:                dst = pattern;
                   2802:                src = mod + 1;
                   2803:                for (; src < endpat; src++, dst++) {
                   2804:                        if (src[0] == '\\' && src + 1 < endpat &&
1.891     rillig   2805:                            /* XXX: ch->startc is missing here; see above */
                   2806:                            IsDelimiter(src[1], ch))
1.703     rillig   2807:                                src++;
                   2808:                        *dst = *src;
                   2809:                }
                   2810:                *dst = '\0';
                   2811:        } else {
                   2812:                pattern = bmake_strsedup(mod + 1, endpat);
1.236     rillig   2813:        }
1.288     rillig   2814:
1.703     rillig   2815:        if (needSubst) {
                   2816:                char *old_pattern = pattern;
1.906     rillig   2817:                (void)Var_Subst(pattern, expr->scope, expr->emode, &pattern);
1.703     rillig   2818:                /* TODO: handle errors */
                   2819:                free(old_pattern);
1.236     rillig   2820:        }
1.346     rillig   2821:
1.908     rillig   2822:        DEBUG2(VAR, "Pattern for ':%c' is \"%s\"\n", mod[0], pattern);
1.346     rillig   2823:
1.845     rillig   2824:        *out_pattern = pattern;
                   2825: }
                   2826:
                   2827: /* :Mpattern or :Npattern */
                   2828: static ApplyModifierResult
1.891     rillig   2829: ApplyModifier_Match(const char **pp, ModChain *ch)
1.845     rillig   2830: {
1.876     rillig   2831:        const char mod = **pp;
1.845     rillig   2832:        char *pattern;
                   2833:
1.891     rillig   2834:        ParseModifier_Match(pp, ch, &pattern);
1.845     rillig   2835:
1.905     rillig   2836:        if (ModChain_ShouldEval(ch)) {
1.876     rillig   2837:                ModifyWordProc modifyWord =
                   2838:                    mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
1.891     rillig   2839:                ModifyWords(ch, modifyWord, pattern, ch->oneBigWord);
1.876     rillig   2840:        }
                   2841:
1.703     rillig   2842:        free(pattern);
                   2843:        return AMR_OK;
1.236     rillig   2844: }
                   2845:
1.860     rillig   2846: static void
1.927     rillig   2847: ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord)
1.860     rillig   2848: {
                   2849:        for (;; (*pp)++) {
                   2850:                if (**pp == 'g')
1.895     rillig   2851:                        pflags->subGlobal = true;
1.860     rillig   2852:                else if (**pp == '1')
1.895     rillig   2853:                        pflags->subOnce = true;
1.860     rillig   2854:                else if (**pp == 'W')
1.895     rillig   2855:                        *oneBigWord = true;
1.860     rillig   2856:                else
                   2857:                        break;
                   2858:        }
                   2859: }
                   2860:
1.927     rillig   2861: MAKE_INLINE PatternFlags
                   2862: PatternFlags_None(void)
1.897     rillig   2863: {
1.927     rillig   2864:        PatternFlags pflags = { false, false, false, false };
1.897     rillig   2865:        return pflags;
                   2866: }
                   2867:
1.236     rillig   2868: /* :S,from,to, */
1.356     rillig   2869: static ApplyModifierResult
1.891     rillig   2870: ApplyModifier_Subst(const char **pp, ModChain *ch)
1.236     rillig   2871: {
1.703     rillig   2872:        struct ModifyWord_SubstArgs args;
1.895     rillig   2873:        bool oneBigWord;
1.703     rillig   2874:        VarParseResult res;
1.921     rillig   2875:        LazyBuf lhsBuf, rhsBuf;
1.299     rillig   2876:
1.703     rillig   2877:        char delim = (*pp)[1];
                   2878:        if (delim == '\0') {
1.846     rillig   2879:                Error("Missing delimiter for modifier ':S'");
1.703     rillig   2880:                (*pp)++;
                   2881:                return AMR_CLEANUP;
                   2882:        }
1.236     rillig   2883:
1.703     rillig   2884:        *pp += 2;
1.236     rillig   2885:
1.927     rillig   2886:        args.pflags = PatternFlags_None();
1.895     rillig   2887:        args.matched = false;
1.236     rillig   2888:
1.703     rillig   2889:        if (**pp == '^') {
1.895     rillig   2890:                args.pflags.anchorStart = true;
1.703     rillig   2891:                (*pp)++;
                   2892:        }
                   2893:
1.921     rillig   2894:        res = ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &lhsBuf,
                   2895:            &args.pflags, NULL);
1.703     rillig   2896:        if (res != VPR_OK)
                   2897:                return AMR_CLEANUP;
1.921     rillig   2898:        args.lhs = LazyBuf_Get(&lhsBuf);
1.703     rillig   2899:
1.921     rillig   2900:        res = ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &rhsBuf,
                   2901:            NULL, &args);
                   2902:        if (res != VPR_OK) {
                   2903:                LazyBuf_Done(&lhsBuf);
1.703     rillig   2904:                return AMR_CLEANUP;
1.921     rillig   2905:        }
                   2906:        args.rhs = LazyBuf_Get(&rhsBuf);
1.703     rillig   2907:
1.891     rillig   2908:        oneBigWord = ch->oneBigWord;
1.860     rillig   2909:        ParsePatternFlags(pp, &args.pflags, &oneBigWord);
1.236     rillig   2910:
1.891     rillig   2911:        ModifyWords(ch, ModifyWord_Subst, &args, oneBigWord);
1.236     rillig   2912:
1.921     rillig   2913:        LazyBuf_Done(&lhsBuf);
                   2914:        LazyBuf_Done(&rhsBuf);
1.703     rillig   2915:        return AMR_OK;
1.236     rillig   2916: }
                   2917:
                   2918: #ifndef NO_REGEX
1.291     rillig   2919:
1.236     rillig   2920: /* :C,from,to, */
1.356     rillig   2921: static ApplyModifierResult
1.891     rillig   2922: ApplyModifier_Regex(const char **pp, ModChain *ch)
1.236     rillig   2923: {
1.703     rillig   2924:        struct ModifyWord_SubstRegexArgs args;
1.895     rillig   2925:        bool oneBigWord;
1.703     rillig   2926:        int error;
                   2927:        VarParseResult res;
1.921     rillig   2928:        LazyBuf reBuf, replaceBuf;
                   2929:        FStr re, replace;
1.703     rillig   2930:
                   2931:        char delim = (*pp)[1];
                   2932:        if (delim == '\0') {
                   2933:                Error("Missing delimiter for :C modifier");
                   2934:                (*pp)++;
                   2935:                return AMR_CLEANUP;
                   2936:        }
                   2937:
                   2938:        *pp += 2;
1.236     rillig   2939:
1.921     rillig   2940:        res = ParseModifierPart(pp, delim, ch->expr->emode, ch, &reBuf);
1.703     rillig   2941:        if (res != VPR_OK)
                   2942:                return AMR_CLEANUP;
1.921     rillig   2943:        re = LazyBuf_DoneGet(&reBuf);
1.703     rillig   2944:
1.921     rillig   2945:        res = ParseModifierPart(pp, delim, ch->expr->emode, ch, &replaceBuf);
                   2946:        if (res != VPR_OK) {
                   2947:                FStr_Done(&re);
1.703     rillig   2948:                return AMR_CLEANUP;
                   2949:        }
1.921     rillig   2950:        replace = LazyBuf_DoneGet(&replaceBuf);
                   2951:        args.replace = replace.str;
1.703     rillig   2952:
1.927     rillig   2953:        args.pflags = PatternFlags_None();
1.895     rillig   2954:        args.matched = false;
1.891     rillig   2955:        oneBigWord = ch->oneBigWord;
1.860     rillig   2956:        ParsePatternFlags(pp, &args.pflags, &oneBigWord);
1.236     rillig   2957:
1.905     rillig   2958:        if (!ModChain_ShouldEval(ch)) {
1.921     rillig   2959:                FStr_Done(&replace);
                   2960:                FStr_Done(&re);
1.856     rillig   2961:                return AMR_OK;
                   2962:        }
                   2963:
1.921     rillig   2964:        error = regcomp(&args.re, re.str, REG_EXTENDED);
1.703     rillig   2965:        if (error != 0) {
                   2966:                VarREError(error, &args.re, "Regex compilation error");
1.921     rillig   2967:                FStr_Done(&replace);
                   2968:                FStr_Done(&re);
1.703     rillig   2969:                return AMR_CLEANUP;
1.236     rillig   2970:        }
                   2971:
1.703     rillig   2972:        args.nsub = args.re.re_nsub + 1;
                   2973:        if (args.nsub > 10)
                   2974:                args.nsub = 10;
1.820     rillig   2975:
1.891     rillig   2976:        ModifyWords(ch, ModifyWord_SubstRegex, &args, oneBigWord);
1.820     rillig   2977:
1.703     rillig   2978:        regfree(&args.re);
1.921     rillig   2979:        FStr_Done(&replace);
                   2980:        FStr_Done(&re);
1.703     rillig   2981:        return AMR_OK;
                   2982: }
1.236     rillig   2983:
                   2984: #endif
                   2985:
1.555     rillig   2986: /* :Q, :q */
                   2987: static ApplyModifierResult
1.891     rillig   2988: ApplyModifier_Quote(const char **pp, ModChain *ch)
1.555     rillig   2989: {
1.924     rillig   2990:        LazyBuf buf;
                   2991:        bool quoteDollar;
                   2992:
                   2993:        quoteDollar = **pp == 'q';
1.891     rillig   2994:        if (!IsDelimiter((*pp)[1], ch))
1.703     rillig   2995:                return AMR_UNKNOWN;
1.861     rillig   2996:        (*pp)++;
                   2997:
1.924     rillig   2998:        if (!ModChain_ShouldEval(ch))
                   2999:                return AMR_OK;
                   3000:
                   3001:        VarQuote(ch->expr->value.str, quoteDollar, &buf);
                   3002:        if (buf.data != NULL)
                   3003:                Expr_SetValue(ch->expr, LazyBuf_DoneGet(&buf));
                   3004:        else
                   3005:                LazyBuf_Done(&buf);
1.861     rillig   3006:
                   3007:        return AMR_OK;
1.555     rillig   3008: }
                   3009:
1.779     rillig   3010: /*ARGSUSED*/
1.278     rillig   3011: static void
1.919     rillig   3012: ModifyWord_Copy(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.278     rillig   3013: {
1.919     rillig   3014:        SepBuf_AddSubstring(buf, word);
1.275     rillig   3015: }
                   3016:
1.289     rillig   3017: /* :ts<separator> */
1.356     rillig   3018: static ApplyModifierResult
1.891     rillig   3019: ApplyModifier_ToSep(const char **pp, ModChain *ch)
1.289     rillig   3020: {
1.703     rillig   3021:        const char *sep = *pp + 2;
                   3022:
1.873     rillig   3023:        /*
1.885     rillig   3024:         * Even in parse-only mode, proceed as normal since there is
1.873     rillig   3025:         * neither any observable side effect nor a performance penalty.
1.885     rillig   3026:         * Checking for wantRes for every single piece of code in here
1.873     rillig   3027:         * would make the code in this function too hard to read.
                   3028:         */
                   3029:
1.703     rillig   3030:        /* ":ts<any><endc>" or ":ts<any>:" */
1.891     rillig   3031:        if (sep[0] != ch->endc && IsDelimiter(sep[1], ch)) {
1.864     rillig   3032:                *pp = sep + 1;
1.891     rillig   3033:                ch->sep = sep[0];
1.703     rillig   3034:                goto ok;
                   3035:        }
1.468     rillig   3036:
1.703     rillig   3037:        /* ":ts<endc>" or ":ts:" */
1.891     rillig   3038:        if (IsDelimiter(sep[0], ch)) {
1.864     rillig   3039:                *pp = sep;
1.891     rillig   3040:                ch->sep = '\0'; /* no separator */
1.703     rillig   3041:                goto ok;
                   3042:        }
1.468     rillig   3043:
1.703     rillig   3044:        /* ":ts<unrecognised><unrecognised>". */
                   3045:        if (sep[0] != '\\') {
                   3046:                (*pp)++;        /* just for backwards compatibility */
                   3047:                return AMR_BAD;
                   3048:        }
1.468     rillig   3049:
1.703     rillig   3050:        /* ":ts\n" */
                   3051:        if (sep[1] == 'n') {
1.864     rillig   3052:                *pp = sep + 2;
1.891     rillig   3053:                ch->sep = '\n';
1.703     rillig   3054:                goto ok;
                   3055:        }
1.468     rillig   3056:
1.703     rillig   3057:        /* ":ts\t" */
                   3058:        if (sep[1] == 't') {
1.864     rillig   3059:                *pp = sep + 2;
1.891     rillig   3060:                ch->sep = '\t';
1.703     rillig   3061:                goto ok;
                   3062:        }
1.468     rillig   3063:
1.703     rillig   3064:        /* ":ts\x40" or ":ts\100" */
                   3065:        {
                   3066:                const char *p = sep + 1;
                   3067:                int base = 8;   /* assume octal */
1.468     rillig   3068:
1.703     rillig   3069:                if (sep[1] == 'x') {
                   3070:                        base = 16;
                   3071:                        p++;
                   3072:                } else if (!ch_isdigit(sep[1])) {
                   3073:                        (*pp)++;        /* just for backwards compatibility */
                   3074:                        return AMR_BAD; /* ":ts<backslash><unrecognised>". */
                   3075:                }
1.289     rillig   3076:
1.891     rillig   3077:                if (!TryParseChar(&p, base, &ch->sep)) {
1.703     rillig   3078:                        Parse_Error(PARSE_FATAL,
1.761     rillig   3079:                            "Invalid character number: %s", p);
1.703     rillig   3080:                        return AMR_CLEANUP;
                   3081:                }
1.891     rillig   3082:                if (!IsDelimiter(*p, ch)) {
1.703     rillig   3083:                        (*pp)++;        /* just for backwards compatibility */
                   3084:                        return AMR_BAD;
                   3085:                }
1.468     rillig   3086:
1.703     rillig   3087:                *pp = p;
1.556     rillig   3088:        }
1.635     rillig   3089:
1.468     rillig   3090: ok:
1.891     rillig   3091:        ModifyWords(ch, ModifyWord_Copy, NULL, ch->oneBigWord);
1.703     rillig   3092:        return AMR_OK;
1.289     rillig   3093: }
                   3094:
1.738     rillig   3095: static char *
                   3096: str_toupper(const char *str)
                   3097: {
                   3098:        char *res;
                   3099:        size_t i, len;
                   3100:
                   3101:        len = strlen(str);
                   3102:        res = bmake_malloc(len + 1);
                   3103:        for (i = 0; i < len + 1; i++)
                   3104:                res[i] = ch_toupper(str[i]);
                   3105:
                   3106:        return res;
                   3107: }
                   3108:
                   3109: static char *
                   3110: str_tolower(const char *str)
                   3111: {
                   3112:        char *res;
                   3113:        size_t i, len;
                   3114:
                   3115:        len = strlen(str);
                   3116:        res = bmake_malloc(len + 1);
                   3117:        for (i = 0; i < len + 1; i++)
                   3118:                res[i] = ch_tolower(str[i]);
                   3119:
                   3120:        return res;
                   3121: }
                   3122:
1.289     rillig   3123: /* :tA, :tu, :tl, :ts<separator>, etc. */
1.356     rillig   3124: static ApplyModifierResult
1.891     rillig   3125: ApplyModifier_To(const char **pp, ModChain *ch)
1.236     rillig   3126: {
1.891     rillig   3127:        Expr *expr = ch->expr;
1.703     rillig   3128:        const char *mod = *pp;
                   3129:        assert(mod[0] == 't');
1.363     rillig   3130:
1.891     rillig   3131:        if (IsDelimiter(mod[1], ch) || mod[1] == '\0') {
1.703     rillig   3132:                *pp = mod + 1;
                   3133:                return AMR_BAD; /* Found ":t<endc>" or ":t:". */
                   3134:        }
1.289     rillig   3135:
1.703     rillig   3136:        if (mod[1] == 's')
1.891     rillig   3137:                return ApplyModifier_ToSep(pp, ch);
1.289     rillig   3138:
1.891     rillig   3139:        if (!IsDelimiter(mod[2], ch)) {                 /* :t<unrecognized> */
1.703     rillig   3140:                *pp = mod + 1;
1.810     rillig   3141:                return AMR_BAD;
1.703     rillig   3142:        }
1.236     rillig   3143:
1.810     rillig   3144:        if (mod[1] == 'A') {                            /* :tA */
1.864     rillig   3145:                *pp = mod + 2;
1.891     rillig   3146:                ModifyWords(ch, ModifyWord_Realpath, NULL, ch->oneBigWord);
1.703     rillig   3147:                return AMR_OK;
                   3148:        }
1.475     rillig   3149:
1.810     rillig   3150:        if (mod[1] == 'u') {                            /* :tu */
1.864     rillig   3151:                *pp = mod + 2;
1.905     rillig   3152:                if (ModChain_ShouldEval(ch))
1.873     rillig   3153:                        Expr_SetValueOwn(expr, str_toupper(expr->value.str));
1.703     rillig   3154:                return AMR_OK;
                   3155:        }
1.475     rillig   3156:
1.810     rillig   3157:        if (mod[1] == 'l') {                            /* :tl */
1.864     rillig   3158:                *pp = mod + 2;
1.905     rillig   3159:                if (ModChain_ShouldEval(ch))
1.873     rillig   3160:                        Expr_SetValueOwn(expr, str_tolower(expr->value.str));
1.703     rillig   3161:                return AMR_OK;
                   3162:        }
1.475     rillig   3163:
1.810     rillig   3164:        if (mod[1] == 'W' || mod[1] == 'w') {           /* :tW, :tw */
1.864     rillig   3165:                *pp = mod + 2;
1.891     rillig   3166:                ch->oneBigWord = mod[1] == 'W';
1.703     rillig   3167:                return AMR_OK;
                   3168:        }
1.475     rillig   3169:
1.703     rillig   3170:        /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
1.864     rillig   3171:        *pp = mod + 1;          /* XXX: unnecessary but observable */
1.703     rillig   3172:        return AMR_BAD;
1.236     rillig   3173: }
                   3174:
1.634     rillig   3175: /* :[#], :[1], :[-1..1], etc. */
1.356     rillig   3176: static ApplyModifierResult
1.891     rillig   3177: ApplyModifier_Words(const char **pp, ModChain *ch)
1.236     rillig   3178: {
1.891     rillig   3179:        Expr *expr = ch->expr;
1.921     rillig   3180:        const char *estr;
1.703     rillig   3181:        int first, last;
                   3182:        VarParseResult res;
                   3183:        const char *p;
1.921     rillig   3184:        LazyBuf estrBuf;
                   3185:        FStr festr;
1.412     rillig   3186:
1.703     rillig   3187:        (*pp)++;                /* skip the '[' */
1.921     rillig   3188:        res = ParseModifierPart(pp, ']', expr->emode, ch, &estrBuf);
1.703     rillig   3189:        if (res != VPR_OK)
                   3190:                return AMR_CLEANUP;
1.921     rillig   3191:        festr = LazyBuf_DoneGet(&estrBuf);
                   3192:        estr = festr.str;
1.703     rillig   3193:
1.891     rillig   3194:        if (!IsDelimiter(**pp, ch))
1.810     rillig   3195:                goto bad_modifier;              /* Found junk after ']' */
1.703     rillig   3196:
1.905     rillig   3197:        if (!ModChain_ShouldEval(ch))
1.877     rillig   3198:                goto ok;
                   3199:
1.703     rillig   3200:        if (estr[0] == '\0')
1.810     rillig   3201:                goto bad_modifier;                      /* Found ":[]". */
1.703     rillig   3202:
1.810     rillig   3203:        if (estr[0] == '#' && estr[1] == '\0') {        /* Found ":[#]" */
1.891     rillig   3204:                if (ch->oneBigWord) {
1.823     rillig   3205:                        Expr_SetValueRefer(expr, "1");
1.703     rillig   3206:                } else {
                   3207:                        Buffer buf;
1.412     rillig   3208:
1.895     rillig   3209:                        Words words = Str_Words(expr->value.str, false);
1.703     rillig   3210:                        size_t ac = words.len;
                   3211:                        Words_Free(words);
                   3212:
                   3213:                        /* 3 digits + '\0' is usually enough */
                   3214:                        Buf_InitSize(&buf, 4);
                   3215:                        Buf_AddInt(&buf, (int)ac);
1.823     rillig   3216:                        Expr_SetValueOwn(expr, Buf_DoneData(&buf));
1.703     rillig   3217:                }
                   3218:                goto ok;
                   3219:        }
1.494     rillig   3220:
1.810     rillig   3221:        if (estr[0] == '*' && estr[1] == '\0') {        /* Found ":[*]" */
1.895     rillig   3222:                ch->oneBigWord = true;
1.703     rillig   3223:                goto ok;
1.236     rillig   3224:        }
1.288     rillig   3225:
1.810     rillig   3226:        if (estr[0] == '@' && estr[1] == '\0') {        /* Found ":[@]" */
1.895     rillig   3227:                ch->oneBigWord = false;
1.703     rillig   3228:                goto ok;
                   3229:        }
1.288     rillig   3230:
1.703     rillig   3231:        /*
                   3232:         * We expect estr to contain a single integer for :[N], or two
                   3233:         * integers separated by ".." for :[start..end].
                   3234:         */
                   3235:        p = estr;
                   3236:        if (!TryParseIntBase0(&p, &first))
                   3237:                goto bad_modifier;      /* Found junk instead of a number */
                   3238:
                   3239:        if (p[0] == '\0') {             /* Found only one integer in :[N] */
                   3240:                last = first;
                   3241:        } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') {
                   3242:                /* Expecting another integer after ".." */
                   3243:                p += 2;
                   3244:                if (!TryParseIntBase0(&p, &last) || *p != '\0')
                   3245:                        goto bad_modifier; /* Found junk after ".." */
                   3246:        } else
                   3247:                goto bad_modifier;      /* Found junk instead of ".." */
1.288     rillig   3248:
1.703     rillig   3249:        /*
                   3250:         * Now first and last are properly filled in, but we still have to
                   3251:         * check for 0 as a special case.
                   3252:         */
                   3253:        if (first == 0 && last == 0) {
                   3254:                /* ":[0]" or perhaps ":[0..0]" */
1.895     rillig   3255:                ch->oneBigWord = true;
1.703     rillig   3256:                goto ok;
                   3257:        }
1.288     rillig   3258:
1.703     rillig   3259:        /* ":[0..N]" or ":[N..0]" */
                   3260:        if (first == 0 || last == 0)
                   3261:                goto bad_modifier;
                   3262:
                   3263:        /* Normal case: select the words described by first and last. */
1.823     rillig   3264:        Expr_SetValueOwn(expr,
1.840     rillig   3265:            VarSelectWords(expr->value.str, first, last,
1.891     rillig   3266:                ch->sep, ch->oneBigWord));
1.288     rillig   3267:
                   3268: ok:
1.921     rillig   3269:        FStr_Done(&festr);
1.703     rillig   3270:        return AMR_OK;
1.288     rillig   3271:
                   3272: bad_modifier:
1.921     rillig   3273:        FStr_Done(&festr);
1.703     rillig   3274:        return AMR_BAD;
1.236     rillig   3275: }
                   3276:
1.939     sjg      3277: #ifndef NUM_TYPE
                   3278: # define NUM_TYPE long long
                   3279: #endif
                   3280:
                   3281: static NUM_TYPE
                   3282: num_val(const char *s)
                   3283: {
                   3284:        NUM_TYPE val;
                   3285:        char *ep;
                   3286:
                   3287:        val = strtoll(s, &ep, 0);
                   3288:        if (ep != s) {
                   3289:                switch (*ep) {
                   3290:                case 'K':
                   3291:                case 'k':
                   3292:                        val <<= 10;
                   3293:                        break;
                   3294:                case 'M':
                   3295:                case 'm':
                   3296:                        val <<= 20;
                   3297:                        break;
                   3298:                case 'G':
                   3299:                case 'g':
                   3300:                        val <<= 30;
                   3301:                        break;
                   3302:                }
                   3303:        }
                   3304:        return val;
                   3305: }
                   3306:
                   3307: static int
                   3308: num_cmp_asc(const void *sa, const void *sb)
                   3309: {
                   3310:        NUM_TYPE a, b;
                   3311:
                   3312:        a = num_val(*(const char *const *)sa);
                   3313:        b = num_val(*(const char *const *)sb);
                   3314:        return (a > b) ? 1 : (b > a) ? -1 : 0;
                   3315: }
1.940     rillig   3316:
1.939     sjg      3317: static int
                   3318: num_cmp_desc(const void *sa, const void *sb)
                   3319: {
1.941     rillig   3320:        return num_cmp_asc(sb, sa);
1.939     sjg      3321: }
1.940     rillig   3322:
1.404     rillig   3323: static int
                   3324: str_cmp_asc(const void *a, const void *b)
                   3325: {
1.703     rillig   3326:        return strcmp(*(const char *const *)a, *(const char *const *)b);
1.404     rillig   3327: }
                   3328:
                   3329: static int
                   3330: str_cmp_desc(const void *a, const void *b)
                   3331: {
1.941     rillig   3332:        return str_cmp_asc(b, a);
1.404     rillig   3333: }
                   3334:
1.705     rillig   3335: static void
                   3336: ShuffleStrings(char **strs, size_t n)
                   3337: {
                   3338:        size_t i;
                   3339:
                   3340:        for (i = n - 1; i > 0; i--) {
                   3341:                size_t rndidx = (size_t)random() % (i + 1);
                   3342:                char *t = strs[i];
                   3343:                strs[i] = strs[rndidx];
                   3344:                strs[rndidx] = t;
                   3345:        }
                   3346: }
                   3347:
1.943     rillig   3348: /*
                   3349:  * :O          order ascending
                   3350:  * :Or         order descending
                   3351:  * :Ox         shuffle
                   3352:  * :On         numeric ascending
                   3353:  * :Onr, :Orn  numeric descending
1.939     sjg      3354:  */
1.356     rillig   3355: static ApplyModifierResult
1.891     rillig   3356: ApplyModifier_Order(const char **pp, ModChain *ch)
1.236     rillig   3357: {
1.942     rillig   3358:        const char *mod = *pp;
1.878     rillig   3359:        Words words;
1.946     rillig   3360:        int (*cmp)(const void *, const void *);
1.401     rillig   3361:
1.942     rillig   3362:        if (IsDelimiter(mod[1], ch) || mod[1] == '\0') {
1.944     rillig   3363:                cmp = str_cmp_asc;
1.939     sjg      3364:                (*pp)++;
1.942     rillig   3365:        } else if (IsDelimiter(mod[2], ch) || mod[2] == '\0') {
                   3366:                if (mod[1] == 'n')
1.944     rillig   3367:                        cmp = num_cmp_asc;
1.942     rillig   3368:                else if (mod[1] == 'r')
1.944     rillig   3369:                        cmp = str_cmp_desc;
1.942     rillig   3370:                else if (mod[1] == 'x')
1.944     rillig   3371:                        cmp = NULL;
1.942     rillig   3372:                else
                   3373:                        goto bad;
                   3374:                *pp += 2;
                   3375:        } else if (IsDelimiter(mod[3], ch) || mod[3] == '\0') {
                   3376:                if ((mod[1] == 'n' && mod[2] == 'r') ||
1.944     rillig   3377:                    (mod[1] == 'r' && mod[2] == 'n'))
                   3378:                        cmp = num_cmp_desc;
                   3379:                else
1.942     rillig   3380:                        goto bad;
                   3381:                *pp += 3;
                   3382:        } else {
                   3383:                goto bad;
                   3384:        }
1.402     rillig   3385:
1.905     rillig   3386:        if (!ModChain_ShouldEval(ch))
1.879     rillig   3387:                return AMR_OK;
                   3388:
1.895     rillig   3389:        words = Str_Words(ch->expr->value.str, false);
1.944     rillig   3390:        if (cmp == NULL)
1.878     rillig   3391:                ShuffleStrings(words.words, words.len);
                   3392:        else
1.944     rillig   3393:                qsort(words.words, words.len, sizeof(words.words[0]), cmp);
1.891     rillig   3394:        Expr_SetValueOwn(ch->expr, Words_JoinFree(words));
1.878     rillig   3395:
1.705     rillig   3396:        return AMR_OK;
1.942     rillig   3397:
                   3398: bad:
                   3399:        (*pp)++;
                   3400:        return AMR_BAD;
1.236     rillig   3401: }
                   3402:
                   3403: /* :? then : else */
1.356     rillig   3404: static ApplyModifierResult
1.891     rillig   3405: ApplyModifier_IfElse(const char **pp, ModChain *ch)
1.236     rillig   3406: {
1.891     rillig   3407:        Expr *expr = ch->expr;
1.703     rillig   3408:        VarParseResult res;
1.921     rillig   3409:        LazyBuf buf;
                   3410:        FStr then_expr, else_expr;
1.412     rillig   3411:
1.895     rillig   3412:        bool value = false;
1.906     rillig   3413:        VarEvalMode then_emode = VARE_PARSE_ONLY;
                   3414:        VarEvalMode else_emode = VARE_PARSE_ONLY;
1.236     rillig   3415:
1.703     rillig   3416:        int cond_rc = COND_PARSE;       /* anything other than COND_INVALID */
1.905     rillig   3417:        if (Expr_ShouldEval(expr)) {
1.898     rillig   3418:                cond_rc = Cond_EvalCondition(expr->name, &value);
1.703     rillig   3419:                if (cond_rc != COND_INVALID && value)
1.906     rillig   3420:                        then_emode = expr->emode;
1.703     rillig   3421:                if (cond_rc != COND_INVALID && !value)
1.906     rillig   3422:                        else_emode = expr->emode;
1.703     rillig   3423:        }
                   3424:
                   3425:        (*pp)++;                        /* skip past the '?' */
1.921     rillig   3426:        res = ParseModifierPart(pp, ':', then_emode, ch, &buf);
1.703     rillig   3427:        if (res != VPR_OK)
                   3428:                return AMR_CLEANUP;
1.921     rillig   3429:        then_expr = LazyBuf_DoneGet(&buf);
1.703     rillig   3430:
1.921     rillig   3431:        res = ParseModifierPart(pp, ch->endc, else_emode, ch, &buf);
                   3432:        if (res != VPR_OK) {
                   3433:                FStr_Done(&then_expr);
1.703     rillig   3434:                return AMR_CLEANUP;
1.921     rillig   3435:        }
                   3436:        else_expr = LazyBuf_DoneGet(&buf);
1.703     rillig   3437:
1.891     rillig   3438:        (*pp)--;                /* Go back to the ch->endc. */
1.809     rillig   3439:
1.703     rillig   3440:        if (cond_rc == COND_INVALID) {
1.930     rillig   3441:                Error("Bad conditional expression '%s' in '%s?%s:%s'",
1.921     rillig   3442:                    expr->name, expr->name, then_expr.str, else_expr.str);
1.703     rillig   3443:                return AMR_CLEANUP;
                   3444:        }
                   3445:
1.905     rillig   3446:        if (!ModChain_ShouldEval(ch)) {
1.921     rillig   3447:                FStr_Done(&then_expr);
                   3448:                FStr_Done(&else_expr);
1.875     rillig   3449:        } else if (value) {
1.921     rillig   3450:                Expr_SetValue(expr, then_expr);
                   3451:                FStr_Done(&else_expr);
1.703     rillig   3452:        } else {
1.921     rillig   3453:                FStr_Done(&then_expr);
                   3454:                Expr_SetValue(expr, else_expr);
1.703     rillig   3455:        }
1.823     rillig   3456:        Expr_Define(expr);
1.703     rillig   3457:        return AMR_OK;
1.236     rillig   3458: }
                   3459:
1.283     rillig   3460: /*
1.808     rillig   3461:  * The ::= modifiers are special in that they do not read the variable value
                   3462:  * but instead assign to that variable.  They always expand to an empty
                   3463:  * string.
                   3464:  *
                   3465:  * Their main purpose is in supporting .for loops that generate shell commands
                   3466:  * since an ordinary variable assignment at that point would terminate the
                   3467:  * dependency group for these targets.  For example:
1.283     rillig   3468:  *
1.808     rillig   3469:  * list-targets: .USE
1.283     rillig   3470:  * .for i in ${.TARGET} ${.TARGET:R}.gz
1.808     rillig   3471:  *     @${t::=$i}
                   3472:  *     @echo 'The target is ${t:T}.'
1.283     rillig   3473:  * .endfor
                   3474:  *
                   3475:  *       ::=<str>      Assigns <str> as the new value of variable.
                   3476:  *       ::?=<str>     Assigns <str> as value of variable if
                   3477:  *                     it was not already set.
                   3478:  *       ::+=<str>     Appends <str> to variable.
                   3479:  *       ::!=<cmd>     Assigns output of <cmd> as the new value of
                   3480:  *                     variable.
                   3481:  */
1.356     rillig   3482: static ApplyModifierResult
1.891     rillig   3483: ApplyModifier_Assign(const char **pp, ModChain *ch)
1.236     rillig   3484: {
1.891     rillig   3485:        Expr *expr = ch->expr;
1.802     rillig   3486:        GNode *scope;
1.921     rillig   3487:        FStr val;
1.703     rillig   3488:        VarParseResult res;
1.921     rillig   3489:        LazyBuf buf;
1.272     rillig   3490:
1.703     rillig   3491:        const char *mod = *pp;
                   3492:        const char *op = mod + 1;
1.272     rillig   3493:
1.703     rillig   3494:        if (op[0] == '=')
                   3495:                goto ok;
                   3496:        if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=')
                   3497:                goto ok;
                   3498:        return AMR_UNKNOWN;     /* "::<unrecognised>" */
1.862     rillig   3499:
1.703     rillig   3500: ok:
1.898     rillig   3501:        if (expr->name[0] == '\0') {
1.703     rillig   3502:                *pp = mod + 1;
                   3503:                return AMR_BAD;
                   3504:        }
1.272     rillig   3505:
1.273     rillig   3506:        switch (op[0]) {
1.236     rillig   3507:        case '+':
1.272     rillig   3508:        case '?':
1.703     rillig   3509:        case '!':
                   3510:                *pp = mod + 3;
1.272     rillig   3511:                break;
1.236     rillig   3512:        default:
1.703     rillig   3513:                *pp = mod + 2;
                   3514:                break;
                   3515:        }
                   3516:
1.921     rillig   3517:        res = ParseModifierPart(pp, ch->endc, expr->emode, ch, &buf);
1.703     rillig   3518:        if (res != VPR_OK)
                   3519:                return AMR_CLEANUP;
1.921     rillig   3520:        val = LazyBuf_DoneGet(&buf);
1.703     rillig   3521:
1.891     rillig   3522:        (*pp)--;                /* Go back to the ch->endc. */
1.703     rillig   3523:
1.905     rillig   3524:        if (!Expr_ShouldEval(expr))
1.882     rillig   3525:                goto done;
                   3526:
1.881     rillig   3527:        scope = expr->scope;    /* scope where v belongs */
                   3528:        if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL) {
1.898     rillig   3529:                Var *gv = VarFind(expr->name, expr->scope, false);
1.881     rillig   3530:                if (gv == NULL)
                   3531:                        scope = SCOPE_GLOBAL;
                   3532:                else
                   3533:                        VarFreeEnv(gv);
                   3534:        }
                   3535:
1.882     rillig   3536:        switch (op[0]) {
                   3537:        case '+':
1.921     rillig   3538:                Var_Append(scope, expr->name, val.str);
1.882     rillig   3539:                break;
                   3540:        case '!': {
                   3541:                const char *errfmt;
1.921     rillig   3542:                char *cmd_output = Cmd_Exec(val.str, &errfmt);
1.882     rillig   3543:                if (errfmt != NULL)
1.921     rillig   3544:                        Error(errfmt, val.str);
1.882     rillig   3545:                else
1.898     rillig   3546:                        Var_Set(scope, expr->name, cmd_output);
1.882     rillig   3547:                free(cmd_output);
                   3548:                break;
                   3549:        }
                   3550:        case '?':
                   3551:                if (expr->defined == DEF_REGULAR)
1.703     rillig   3552:                        break;
1.882     rillig   3553:                /* FALLTHROUGH */
                   3554:        default:
1.921     rillig   3555:                Var_Set(scope, expr->name, val.str);
1.882     rillig   3556:                break;
1.236     rillig   3557:        }
1.882     rillig   3558:        Expr_SetValueRefer(expr, "");
                   3559:
                   3560: done:
1.921     rillig   3561:        FStr_Done(&val);
1.703     rillig   3562:        return AMR_OK;
1.236     rillig   3563: }
                   3564:
1.778     rillig   3565: /*
                   3566:  * :_=...
                   3567:  * remember current value
                   3568:  */
1.356     rillig   3569: static ApplyModifierResult
1.891     rillig   3570: ApplyModifier_Remember(const char **pp, ModChain *ch)
1.236     rillig   3571: {
1.891     rillig   3572:        Expr *expr = ch->expr;
1.703     rillig   3573:        const char *mod = *pp;
1.868     rillig   3574:        FStr name;
1.866     rillig   3575:
1.891     rillig   3576:        if (!ModMatchEq(mod, "_", ch))
1.703     rillig   3577:                return AMR_UNKNOWN;
                   3578:
1.868     rillig   3579:        name = FStr_InitRefer("_");
1.703     rillig   3580:        if (mod[1] == '=') {
1.847     rillig   3581:                /*
                   3582:                 * XXX: This ad-hoc call to strcspn deviates from the usual
                   3583:                 * behavior defined in ParseModifierPart.  This creates an
                   3584:                 * unnecessary, undocumented inconsistency in make.
                   3585:                 */
1.869     rillig   3586:                const char *arg = mod + 2;
                   3587:                size_t argLen = strcspn(arg, ":)}");
                   3588:                *pp = arg + argLen;
                   3589:                name = FStr_InitOwn(bmake_strldup(arg, argLen));
1.868     rillig   3590:        } else
                   3591:                *pp = mod + 1;
1.864     rillig   3592:
1.905     rillig   3593:        if (Expr_ShouldEval(expr))
1.868     rillig   3594:                Var_Set(expr->scope, name.str, expr->value.str);
                   3595:        FStr_Done(&name);
1.864     rillig   3596:
1.703     rillig   3597:        return AMR_OK;
1.236     rillig   3598: }
                   3599:
1.778     rillig   3600: /*
                   3601:  * Apply the given function to each word of the variable value,
                   3602:  * for a single-letter modifier such as :H, :T.
                   3603:  */
1.434     rillig   3604: static ApplyModifierResult
1.891     rillig   3605: ApplyModifier_WordFunc(const char **pp, ModChain *ch,
1.822     rillig   3606:                       ModifyWordProc modifyWord)
1.434     rillig   3607: {
1.891     rillig   3608:        if (!IsDelimiter((*pp)[1], ch))
1.703     rillig   3609:                return AMR_UNKNOWN;
1.864     rillig   3610:        (*pp)++;
1.703     rillig   3611:
1.905     rillig   3612:        if (ModChain_ShouldEval(ch))
1.891     rillig   3613:                ModifyWords(ch, modifyWord, NULL, ch->oneBigWord);
1.864     rillig   3614:
1.703     rillig   3615:        return AMR_OK;
1.434     rillig   3616: }
                   3617:
1.931     rillig   3618: /* Remove adjacent duplicate words. */
1.567     rillig   3619: static ApplyModifierResult
1.891     rillig   3620: ApplyModifier_Unique(const char **pp, ModChain *ch)
1.567     rillig   3621: {
1.931     rillig   3622:        Words words;
                   3623:
1.891     rillig   3624:        if (!IsDelimiter((*pp)[1], ch))
1.703     rillig   3625:                return AMR_UNKNOWN;
1.862     rillig   3626:        (*pp)++;
                   3627:
1.931     rillig   3628:        if (!ModChain_ShouldEval(ch))
                   3629:                return AMR_OK;
                   3630:
                   3631:        words = Str_Words(ch->expr->value.str, false);
                   3632:
                   3633:        if (words.len > 1) {
1.932     rillig   3634:                size_t si, di;
                   3635:
                   3636:                di = 0;
                   3637:                for (si = 1; si < words.len; si++) {
                   3638:                        if (strcmp(words.words[si], words.words[di]) != 0) {
                   3639:                                di++;
                   3640:                                if (di != si)
                   3641:                                        words.words[di] = words.words[si];
                   3642:                        }
                   3643:                }
                   3644:                words.len = di + 1;
1.931     rillig   3645:        }
                   3646:
                   3647:        Expr_SetValueOwn(ch->expr, Words_JoinFree(words));
1.862     rillig   3648:
                   3649:        return AMR_OK;
1.567     rillig   3650: }
                   3651:
1.236     rillig   3652: #ifdef SYSVVARSUB
                   3653: /* :from=to */
1.356     rillig   3654: static ApplyModifierResult
1.891     rillig   3655: ApplyModifier_SysV(const char **pp, ModChain *ch)
1.236     rillig   3656: {
1.891     rillig   3657:        Expr *expr = ch->expr;
1.703     rillig   3658:        VarParseResult res;
1.925     rillig   3659:        LazyBuf lhsBuf, rhsBuf;
                   3660:        FStr rhs;
1.926     rillig   3661:        struct ModifyWord_SysVSubstArgs args;
1.925     rillig   3662:        Substring lhs;
                   3663:        const char *lhsSuffix;
1.412     rillig   3664:
1.703     rillig   3665:        const char *mod = *pp;
1.895     rillig   3666:        bool eqFound = false;
1.245     rillig   3667:
1.703     rillig   3668:        /*
                   3669:         * First we make a pass through the string trying to verify it is a
                   3670:         * SysV-make-style translation. It must be: <lhs>=<rhs>
                   3671:         */
                   3672:        int depth = 1;
                   3673:        const char *p = mod;
                   3674:        while (*p != '\0' && depth > 0) {
                   3675:                if (*p == '=') {        /* XXX: should also test depth == 1 */
1.895     rillig   3676:                        eqFound = true;
1.891     rillig   3677:                        /* continue looking for ch->endc */
                   3678:                } else if (*p == ch->endc)
1.703     rillig   3679:                        depth--;
1.891     rillig   3680:                else if (*p == ch->startc)
1.703     rillig   3681:                        depth++;
                   3682:                if (depth > 0)
                   3683:                        p++;
                   3684:        }
1.891     rillig   3685:        if (*p != ch->endc || !eqFound)
1.703     rillig   3686:                return AMR_UNKNOWN;
1.236     rillig   3687:
1.925     rillig   3688:        res = ParseModifierPart(pp, '=', expr->emode, ch, &lhsBuf);
1.703     rillig   3689:        if (res != VPR_OK)
                   3690:                return AMR_CLEANUP;
                   3691:
                   3692:        /* The SysV modifier lasts until the end of the variable expression. */
1.925     rillig   3693:        res = ParseModifierPart(pp, ch->endc, expr->emode, ch, &rhsBuf);
1.921     rillig   3694:        if (res != VPR_OK) {
1.925     rillig   3695:                LazyBuf_Done(&lhsBuf);
1.703     rillig   3696:                return AMR_CLEANUP;
1.921     rillig   3697:        }
1.925     rillig   3698:        rhs = LazyBuf_DoneGet(&rhsBuf);
1.703     rillig   3699:
1.891     rillig   3700:        (*pp)--;                /* Go back to the ch->endc. */
1.809     rillig   3701:
1.925     rillig   3702:        /* Do not turn an empty expression into non-empty. */
                   3703:        if (lhsBuf.len == 0 && expr->value.str[0] == '\0')
                   3704:                goto done;
                   3705:
                   3706:        lhs = LazyBuf_Get(&lhsBuf);
                   3707:        lhsSuffix = Substring_SkipFirst(lhs, '%');
                   3708:
                   3709:        args.scope = expr->scope;
                   3710:        args.lhsPrefix = Substring_Init(lhs.start,
                   3711:            lhsSuffix != lhs.start ? lhsSuffix - 1 : lhs.start);
                   3712:        args.lhsPercent = lhsSuffix != lhs.start;
                   3713:        args.lhsSuffix = Substring_Init(lhsSuffix, lhs.end);
                   3714:        args.rhs = rhs.str;
                   3715:
1.926     rillig   3716:        ModifyWords(ch, ModifyWord_SysVSubst, &args, ch->oneBigWord);
1.897     rillig   3717:
1.925     rillig   3718: done:
                   3719:        LazyBuf_Done(&lhsBuf);
1.703     rillig   3720:        return AMR_OK;
1.236     rillig   3721: }
                   3722: #endif
                   3723:
1.548     rillig   3724: #ifdef SUNSHCMD
                   3725: /* :sh */
                   3726: static ApplyModifierResult
1.891     rillig   3727: ApplyModifier_SunShell(const char **pp, ModChain *ch)
1.548     rillig   3728: {
1.891     rillig   3729:        Expr *expr = ch->expr;
1.703     rillig   3730:        const char *p = *pp;
1.891     rillig   3731:        if (!(p[1] == 'h' && IsDelimiter(p[2], ch)))
1.703     rillig   3732:                return AMR_UNKNOWN;
1.864     rillig   3733:        *pp = p + 2;
1.863     rillig   3734:
1.905     rillig   3735:        if (Expr_ShouldEval(expr)) {
1.863     rillig   3736:                const char *errfmt;
                   3737:                char *output = Cmd_Exec(expr->value.str, &errfmt);
                   3738:                if (errfmt != NULL)
                   3739:                        Error(errfmt, expr->value.str);
                   3740:                Expr_SetValueOwn(expr, output);
                   3741:        }
1.864     rillig   3742:
1.863     rillig   3743:        return AMR_OK;
1.548     rillig   3744: }
                   3745: #endif
                   3746:
1.549     rillig   3747: static void
1.891     rillig   3748: LogBeforeApply(const ModChain *ch, const char *mod)
1.549     rillig   3749: {
1.891     rillig   3750:        const Expr *expr = ch->expr;
1.895     rillig   3751:        bool is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], ch);
1.703     rillig   3752:
1.909     rillig   3753:        /*
                   3754:         * At this point, only the first character of the modifier can
                   3755:         * be used since the end of the modifier is not yet known.
                   3756:         */
                   3757:
                   3758:        if (!Expr_ShouldEval(expr)) {
                   3759:                debug_printf("Parsing modifier ${%s:%c%s}\n",
                   3760:                    expr->name, mod[0], is_single_char ? "" : "...");
                   3761:                return;
                   3762:        }
                   3763:
1.910     rillig   3764:        if ((expr->emode == VARE_WANTRES || expr->emode == VARE_UNDEFERR) &&
                   3765:            expr->defined == DEF_REGULAR) {
                   3766:                debug_printf(
                   3767:                    "Evaluating modifier ${%s:%c%s} on value \"%s\"\n",
                   3768:                    expr->name, mod[0], is_single_char ? "" : "...",
                   3769:                    expr->value.str);
                   3770:                return;
                   3771:        }
                   3772:
1.909     rillig   3773:        debug_printf(
                   3774:            "Evaluating modifier ${%s:%c%s} on value \"%s\" (%s, %s)\n",
                   3775:            expr->name, mod[0], is_single_char ? "" : "...", expr->value.str,
1.910     rillig   3776:            VarEvalMode_Name[expr->emode], ExprDefined_Name[expr->defined]);
1.549     rillig   3777: }
                   3778:
                   3779: static void
1.891     rillig   3780: LogAfterApply(const ModChain *ch, const char *p, const char *mod)
1.549     rillig   3781: {
1.891     rillig   3782:        const Expr *expr = ch->expr;
1.823     rillig   3783:        const char *value = expr->value.str;
                   3784:        const char *quot = value == var_Error ? "" : "\"";
1.703     rillig   3785:
1.912     rillig   3786:        if ((expr->emode == VARE_WANTRES || expr->emode == VARE_UNDEFERR) &&
                   3787:            expr->defined == DEF_REGULAR) {
                   3788:
                   3789:                debug_printf("Result of ${%s:%.*s} is %s%s%s\n",
                   3790:                    expr->name, (int)(p - mod), mod,
                   3791:                    quot, value == var_Error ? "error" : value, quot);
                   3792:                return;
                   3793:        }
                   3794:
1.899     rillig   3795:        debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s)\n",
1.898     rillig   3796:            expr->name, (int)(p - mod), mod,
1.823     rillig   3797:            quot, value == var_Error ? "error" : value, quot,
1.906     rillig   3798:            VarEvalMode_Name[expr->emode],
1.825     rillig   3799:            ExprDefined_Name[expr->defined]);
1.549     rillig   3800: }
                   3801:
1.551     rillig   3802: static ApplyModifierResult
1.891     rillig   3803: ApplyModifier(const char **pp, ModChain *ch)
1.551     rillig   3804: {
1.703     rillig   3805:        switch (**pp) {
1.857     rillig   3806:        case '!':
1.891     rillig   3807:                return ApplyModifier_ShellCommand(pp, ch);
1.703     rillig   3808:        case ':':
1.891     rillig   3809:                return ApplyModifier_Assign(pp, ch);
1.857     rillig   3810:        case '?':
1.891     rillig   3811:                return ApplyModifier_IfElse(pp, ch);
1.703     rillig   3812:        case '@':
1.891     rillig   3813:                return ApplyModifier_Loop(pp, ch);
1.857     rillig   3814:        case '[':
1.891     rillig   3815:                return ApplyModifier_Words(pp, ch);
1.703     rillig   3816:        case '_':
1.891     rillig   3817:                return ApplyModifier_Remember(pp, ch);
1.857     rillig   3818: #ifndef NO_REGEX
                   3819:        case 'C':
1.891     rillig   3820:                return ApplyModifier_Regex(pp, ch);
1.857     rillig   3821: #endif
1.703     rillig   3822:        case 'D':
1.891     rillig   3823:                return ApplyModifier_Defined(pp, ch);
1.857     rillig   3824:        case 'E':
1.891     rillig   3825:                return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix);
1.703     rillig   3826:        case 'g':
1.891     rillig   3827:                return ApplyModifier_Gmtime(pp, ch);
1.857     rillig   3828:        case 'H':
1.891     rillig   3829:                return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head);
1.703     rillig   3830:        case 'h':
1.891     rillig   3831:                return ApplyModifier_Hash(pp, ch);
1.857     rillig   3832:        case 'L':
1.891     rillig   3833:                return ApplyModifier_Literal(pp, ch);
1.703     rillig   3834:        case 'l':
1.891     rillig   3835:                return ApplyModifier_Localtime(pp, ch);
1.857     rillig   3836:        case 'M':
1.703     rillig   3837:        case 'N':
1.891     rillig   3838:                return ApplyModifier_Match(pp, ch);
1.857     rillig   3839:        case 'O':
1.891     rillig   3840:                return ApplyModifier_Order(pp, ch);
1.857     rillig   3841:        case 'P':
1.891     rillig   3842:                return ApplyModifier_Path(pp, ch);
1.857     rillig   3843:        case 'Q':
1.703     rillig   3844:        case 'q':
1.891     rillig   3845:                return ApplyModifier_Quote(pp, ch);
1.703     rillig   3846:        case 'R':
1.891     rillig   3847:                return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root);
1.703     rillig   3848:        case 'r':
1.891     rillig   3849:                return ApplyModifier_Range(pp, ch);
1.857     rillig   3850:        case 'S':
1.891     rillig   3851:                return ApplyModifier_Subst(pp, ch);
1.551     rillig   3852: #ifdef SUNSHCMD
1.703     rillig   3853:        case 's':
1.891     rillig   3854:                return ApplyModifier_SunShell(pp, ch);
1.551     rillig   3855: #endif
1.857     rillig   3856:        case 'T':
1.891     rillig   3857:                return ApplyModifier_WordFunc(pp, ch, ModifyWord_Tail);
1.857     rillig   3858:        case 't':
1.891     rillig   3859:                return ApplyModifier_To(pp, ch);
1.857     rillig   3860:        case 'U':
1.891     rillig   3861:                return ApplyModifier_Defined(pp, ch);
1.857     rillig   3862:        case 'u':
1.891     rillig   3863:                return ApplyModifier_Unique(pp, ch);
1.703     rillig   3864:        default:
                   3865:                return AMR_UNKNOWN;
                   3866:        }
1.551     rillig   3867: }
                   3868:
1.823     rillig   3869: static void ApplyModifiers(Expr *, const char **, char, char);
1.641     rillig   3870:
                   3871: typedef enum ApplyModifiersIndirectResult {
1.752     rillig   3872:        /* The indirect modifiers have been applied successfully. */
1.703     rillig   3873:        AMIR_CONTINUE,
1.752     rillig   3874:        /* Fall back to the SysV modifier. */
1.849     rillig   3875:        AMIR_SYSV,
1.752     rillig   3876:        /* Error out. */
1.703     rillig   3877:        AMIR_OUT
1.641     rillig   3878: } ApplyModifiersIndirectResult;
                   3879:
1.752     rillig   3880: /*
                   3881:  * While expanding a variable expression, expand and apply indirect modifiers,
                   3882:  * such as in ${VAR:${M_indirect}}.
                   3883:  *
                   3884:  * All indirect modifiers of a group must come from a single variable
                   3885:  * expression.  ${VAR:${M1}} is valid but ${VAR:${M1}${M2}} is not.
                   3886:  *
                   3887:  * Multiple groups of indirect modifiers can be chained by separating them
                   3888:  * with colons.  ${VAR:${M1}:${M2}} contains 2 indirect modifiers.
                   3889:  *
1.891     rillig   3890:  * If the variable expression is not followed by ch->endc or ':', fall
1.752     rillig   3891:  * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}.
                   3892:  */
1.641     rillig   3893: static ApplyModifiersIndirectResult
1.891     rillig   3894: ApplyModifiersIndirect(ModChain *ch, const char **pp)
1.703     rillig   3895: {
1.891     rillig   3896:        Expr *expr = ch->expr;
1.721     rillig   3897:        const char *p = *pp;
1.743     rillig   3898:        FStr mods;
1.641     rillig   3899:
1.906     rillig   3900:        (void)Var_Parse(&p, expr->scope, expr->emode, &mods);
1.703     rillig   3901:        /* TODO: handle errors */
1.641     rillig   3902:
1.891     rillig   3903:        if (mods.str[0] != '\0' && *p != '\0' && !IsDelimiter(*p, ch)) {
1.743     rillig   3904:                FStr_Done(&mods);
1.849     rillig   3905:                return AMIR_SYSV;
1.703     rillig   3906:        }
                   3907:
1.708     rillig   3908:        DEBUG3(VAR, "Indirect modifier \"%s\" from \"%.*s\"\n",
1.743     rillig   3909:            mods.str, (int)(p - *pp), *pp);
1.703     rillig   3910:
1.743     rillig   3911:        if (mods.str[0] != '\0') {
                   3912:                const char *modsp = mods.str;
1.823     rillig   3913:                ApplyModifiers(expr, &modsp, '\0', '\0');
                   3914:                if (expr->value.str == var_Error || *modsp != '\0') {
1.743     rillig   3915:                        FStr_Done(&mods);
1.721     rillig   3916:                        *pp = p;
1.703     rillig   3917:                        return AMIR_OUT;        /* error already reported */
                   3918:                }
                   3919:        }
1.743     rillig   3920:        FStr_Done(&mods);
1.641     rillig   3921:
1.703     rillig   3922:        if (*p == ':')
                   3923:                p++;
1.891     rillig   3924:        else if (*p == '\0' && ch->endc != '\0') {
1.852     rillig   3925:                Error("Unclosed variable expression after indirect "
                   3926:                      "modifier, expecting '%c' for variable \"%s\"",
1.898     rillig   3927:                    ch->endc, expr->name);
1.721     rillig   3928:                *pp = p;
1.703     rillig   3929:                return AMIR_OUT;
1.641     rillig   3930:        }
                   3931:
1.721     rillig   3932:        *pp = p;
1.703     rillig   3933:        return AMIR_CONTINUE;
1.641     rillig   3934: }
                   3935:
1.750     rillig   3936: static ApplyModifierResult
1.891     rillig   3937: ApplySingleModifier(const char **pp, ModChain *ch)
1.750     rillig   3938: {
                   3939:        ApplyModifierResult res;
1.850     rillig   3940:        const char *mod = *pp;
1.750     rillig   3941:        const char *p = *pp;
                   3942:
                   3943:        if (DEBUG(VAR))
1.891     rillig   3944:                LogBeforeApply(ch, mod);
1.750     rillig   3945:
1.891     rillig   3946:        res = ApplyModifier(&p, ch);
1.750     rillig   3947:
                   3948: #ifdef SYSVVARSUB
                   3949:        if (res == AMR_UNKNOWN) {
                   3950:                assert(p == mod);
1.891     rillig   3951:                res = ApplyModifier_SysV(&p, ch);
1.750     rillig   3952:        }
                   3953: #endif
                   3954:
                   3955:        if (res == AMR_UNKNOWN) {
                   3956:                /*
                   3957:                 * Guess the end of the current modifier.
                   3958:                 * XXX: Skipping the rest of the modifier hides
                   3959:                 * errors and leads to wrong results.
                   3960:                 * Parsing should rather stop here.
                   3961:                 */
1.891     rillig   3962:                for (p++; !IsDelimiter(*p, ch) && *p != '\0'; p++)
1.750     rillig   3963:                        continue;
1.851     rillig   3964:                Parse_Error(PARSE_FATAL, "Unknown modifier \"%.*s\"",
                   3965:                    (int)(p - mod), mod);
1.891     rillig   3966:                Expr_SetValueRefer(ch->expr, var_Error);
1.750     rillig   3967:        }
                   3968:        if (res == AMR_CLEANUP || res == AMR_BAD) {
                   3969:                *pp = p;
                   3970:                return res;
                   3971:        }
                   3972:
                   3973:        if (DEBUG(VAR))
1.891     rillig   3974:                LogAfterApply(ch, p, mod);
1.750     rillig   3975:
1.891     rillig   3976:        if (*p == '\0' && ch->endc != '\0') {
1.750     rillig   3977:                Error(
1.852     rillig   3978:                    "Unclosed variable expression, expecting '%c' for "
                   3979:                    "modifier \"%.*s\" of variable \"%s\" with value \"%s\"",
1.891     rillig   3980:                    ch->endc,
1.852     rillig   3981:                    (int)(p - mod), mod,
1.898     rillig   3982:                    ch->expr->name, ch->expr->value.str);
1.750     rillig   3983:        } else if (*p == ':') {
                   3984:                p++;
1.891     rillig   3985:        } else if (opts.strict && *p != '\0' && *p != ch->endc) {
1.750     rillig   3986:                Parse_Error(PARSE_FATAL,
                   3987:                    "Missing delimiter ':' after modifier \"%.*s\"",
                   3988:                    (int)(p - mod), mod);
                   3989:                /*
                   3990:                 * TODO: propagate parse error to the enclosing
                   3991:                 * expression
                   3992:                 */
                   3993:        }
                   3994:        *pp = p;
                   3995:        return AMR_OK;
                   3996: }
                   3997:
1.897     rillig   3998: #if __STDC_VERSION__ >= 199901L
                   3999: #define ModChain_Literal(expr, startc, endc, sep, oneBigWord) \
                   4000:        (ModChain) { expr, startc, endc, sep, oneBigWord }
                   4001: #else
                   4002: MAKE_INLINE ModChain
                   4003: ModChain_Literal(Expr *expr, char startc, char endc, char sep, bool oneBigWord)
                   4004: {
                   4005:        ModChain ch;
                   4006:        ch.expr = expr;
                   4007:        ch.startc = startc;
                   4008:        ch.endc = endc;
                   4009:        ch.sep = sep;
                   4010:        ch.oneBigWord = oneBigWord;
                   4011:        return ch;
                   4012: }
                   4013: #endif
                   4014:
1.419     rillig   4015: /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
1.823     rillig   4016: static void
1.357     rillig   4017: ApplyModifiers(
1.823     rillig   4018:     Expr *expr,
1.821     rillig   4019:     const char **pp,   /* the parsing position, updated upon return */
                   4020:     char startc,       /* '(' or '{'; or '\0' for indirect modifiers */
1.823     rillig   4021:     char endc          /* ')' or '}'; or '\0' for indirect modifiers */
1.703     rillig   4022: )
                   4023: {
1.897     rillig   4024:        ModChain ch = ModChain_Literal(expr, startc, endc, ' ', false);
1.703     rillig   4025:        const char *p;
                   4026:        const char *mod;
                   4027:
                   4028:        assert(startc == '(' || startc == '{' || startc == '\0');
                   4029:        assert(endc == ')' || endc == '}' || endc == '\0');
1.823     rillig   4030:        assert(expr->value.str != NULL);
1.703     rillig   4031:
                   4032:        p = *pp;
                   4033:
                   4034:        if (*p == '\0' && endc != '\0') {
                   4035:                Error(
                   4036:                    "Unclosed variable expression (expecting '%c') for \"%s\"",
1.898     rillig   4037:                    ch.endc, expr->name);
1.703     rillig   4038:                goto cleanup;
                   4039:        }
                   4040:
                   4041:        while (*p != '\0' && *p != endc) {
1.750     rillig   4042:                ApplyModifierResult res;
1.703     rillig   4043:
                   4044:                if (*p == '$') {
1.849     rillig   4045:                        ApplyModifiersIndirectResult amir =
1.891     rillig   4046:                            ApplyModifiersIndirect(&ch, &p);
1.703     rillig   4047:                        if (amir == AMIR_CONTINUE)
                   4048:                                continue;
                   4049:                        if (amir == AMIR_OUT)
1.752     rillig   4050:                                break;
1.849     rillig   4051:                        /*
                   4052:                         * It's neither '${VAR}:' nor '${VAR}}'.  Try to parse
                   4053:                         * it as a SysV modifier, as that is the only modifier
                   4054:                         * that can start with '$'.
                   4055:                         */
1.703     rillig   4056:                }
1.752     rillig   4057:
1.703     rillig   4058:                mod = p;
1.649     rillig   4059:
1.891     rillig   4060:                res = ApplySingleModifier(&p, &ch);
1.703     rillig   4061:                if (res == AMR_CLEANUP)
                   4062:                        goto cleanup;
                   4063:                if (res == AMR_BAD)
                   4064:                        goto bad_modifier;
1.356     rillig   4065:        }
1.752     rillig   4066:
1.703     rillig   4067:        *pp = p;
1.823     rillig   4068:        assert(expr->value.str != NULL); /* Use var_Error or varUndefined. */
                   4069:        return;
1.25      christos 4070:
1.240     rillig   4071: bad_modifier:
1.703     rillig   4072:        /* XXX: The modifier end is only guessed. */
1.853     rillig   4073:        Error("Bad modifier \":%.*s\" for variable \"%s\"",
1.898     rillig   4074:            (int)strcspn(mod, ":)}"), mod, expr->name);
1.25      christos 4075:
1.240     rillig   4076: cleanup:
1.858     rillig   4077:        /*
                   4078:         * TODO: Use p + strlen(p) instead, to stop parsing immediately.
                   4079:         *
                   4080:         * In the unit tests, this generates a few unterminated strings in the
                   4081:         * shell commands though.  Instead of producing these unfinished
                   4082:         * strings, commands with evaluation errors should not be run at all.
                   4083:         *
                   4084:         * To make that happen, Var_Subst must report the actual errors
                   4085:         * instead of returning VPR_OK unconditionally.
                   4086:         */
1.703     rillig   4087:        *pp = p;
1.823     rillig   4088:        Expr_SetValueRefer(expr, var_Error);
1.108     sjg      4089: }
1.25      christos 4090:
1.778     rillig   4091: /*
1.916     rillig   4092:  * Only 4 of the 7 local variables are treated specially as they are the only
                   4093:  * ones that will be set when dynamic sources are expanded.
1.778     rillig   4094:  */
1.895     rillig   4095: static bool
1.916     rillig   4096: VarnameIsDynamic(Substring varname)
1.335     rillig   4097: {
1.916     rillig   4098:        const char *name;
                   4099:        size_t len;
                   4100:
                   4101:        name = varname.start;
                   4102:        len = Substring_Length(varname);
1.703     rillig   4103:        if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
                   4104:                switch (name[0]) {
                   4105:                case '@':
                   4106:                case '%':
                   4107:                case '*':
                   4108:                case '!':
1.895     rillig   4109:                        return true;
1.703     rillig   4110:                }
1.895     rillig   4111:                return false;
1.335     rillig   4112:        }
                   4113:
1.703     rillig   4114:        if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
1.916     rillig   4115:                return Substring_Equals(varname, ".TARGET") ||
                   4116:                       Substring_Equals(varname, ".ARCHIVE") ||
                   4117:                       Substring_Equals(varname, ".PREFIX") ||
                   4118:                       Substring_Equals(varname, ".MEMBER");
1.703     rillig   4119:        }
1.335     rillig   4120:
1.895     rillig   4121:        return false;
1.335     rillig   4122: }
                   4123:
1.502     rillig   4124: static const char *
1.802     rillig   4125: UndefinedShortVarValue(char varname, const GNode *scope)
1.502     rillig   4126: {
1.802     rillig   4127:        if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) {
1.703     rillig   4128:                /*
1.802     rillig   4129:                 * If substituting a local variable in a non-local scope,
1.703     rillig   4130:                 * assume it's for dynamic source stuff. We have to handle
                   4131:                 * this specially and return the longhand for the variable
                   4132:                 * with the dollar sign escaped so it makes it back to the
                   4133:                 * caller. Only four of the local variables are treated
                   4134:                 * specially as they are the only four that will be set
                   4135:                 * when dynamic sources are expanded.
                   4136:                 */
                   4137:                switch (varname) {
                   4138:                case '@':
                   4139:                        return "$(.TARGET)";
                   4140:                case '%':
                   4141:                        return "$(.MEMBER)";
                   4142:                case '*':
                   4143:                        return "$(.PREFIX)";
                   4144:                case '!':
                   4145:                        return "$(.ARCHIVE)";
                   4146:                }
1.502     rillig   4147:        }
1.769     rillig   4148:        return NULL;
1.502     rillig   4149: }
                   4150:
1.778     rillig   4151: /*
                   4152:  * Parse a variable name, until the end character or a colon, whichever
                   4153:  * comes first.
                   4154:  */
1.916     rillig   4155: static void
1.501     rillig   4156: ParseVarname(const char **pp, char startc, char endc,
1.906     rillig   4157:             GNode *scope, VarEvalMode emode,
1.916     rillig   4158:             LazyBuf *buf)
1.501     rillig   4159: {
1.703     rillig   4160:        const char *p = *pp;
1.854     rillig   4161:        int depth = 0;          /* Track depth so we can spot parse errors. */
1.703     rillig   4162:
1.923     rillig   4163:        LazyBuf_Init(buf, p);
1.703     rillig   4164:
                   4165:        while (*p != '\0') {
1.854     rillig   4166:                if ((*p == endc || *p == ':') && depth == 0)
                   4167:                        break;
1.703     rillig   4168:                if (*p == startc)
                   4169:                        depth++;
1.854     rillig   4170:                if (*p == endc)
                   4171:                        depth--;
1.501     rillig   4172:
1.703     rillig   4173:                /* A variable inside a variable, expand. */
                   4174:                if (*p == '$') {
1.743     rillig   4175:                        FStr nested_val;
1.906     rillig   4176:                        (void)Var_Parse(&p, scope, emode, &nested_val);
1.703     rillig   4177:                        /* TODO: handle errors */
1.916     rillig   4178:                        LazyBuf_AddStr(buf, nested_val.str);
1.743     rillig   4179:                        FStr_Done(&nested_val);
1.703     rillig   4180:                } else {
1.916     rillig   4181:                        LazyBuf_Add(buf, *p);
1.703     rillig   4182:                        p++;
                   4183:                }
1.501     rillig   4184:        }
1.703     rillig   4185:        *pp = p;
1.501     rillig   4186: }
                   4187:
1.652     rillig   4188: static VarParseResult
1.507     rillig   4189: ValidShortVarname(char varname, const char *start)
                   4190: {
1.818     rillig   4191:        if (varname != '$' && varname != ':' && varname != '}' &&
                   4192:            varname != ')' && varname != '\0')
1.703     rillig   4193:                return VPR_OK;
1.507     rillig   4194:
1.771     rillig   4195:        if (!opts.strict)
                   4196:                return VPR_ERR; /* XXX: Missing error message */
1.507     rillig   4197:
1.703     rillig   4198:        if (varname == '$')
                   4199:                Parse_Error(PARSE_FATAL,
1.507     rillig   4200:                    "To escape a dollar, use \\$, not $$, at \"%s\"", start);
1.703     rillig   4201:        else if (varname == '\0')
                   4202:                Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
                   4203:        else
                   4204:                Parse_Error(PARSE_FATAL,
1.507     rillig   4205:                    "Invalid variable name '%c', at \"%s\"", varname, start);
                   4206:
1.767     rillig   4207:        return VPR_ERR;
1.507     rillig   4208: }
                   4209:
1.778     rillig   4210: /*
1.817     rillig   4211:  * Parse a single-character variable name such as in $V or $@.
1.778     rillig   4212:  * Return whether to continue parsing.
                   4213:  */
1.895     rillig   4214: static bool
1.817     rillig   4215: ParseVarnameShort(char varname, const char **pp, GNode *scope,
1.906     rillig   4216:                  VarEvalMode emode,
1.896     rillig   4217:                  VarParseResult *out_false_res, const char **out_false_val,
                   4218:                  Var **out_true_var)
1.667     rillig   4219: {
1.703     rillig   4220:        char name[2];
                   4221:        Var *v;
                   4222:        VarParseResult vpr;
1.622     rillig   4223:
1.817     rillig   4224:        vpr = ValidShortVarname(varname, *pp);
1.703     rillig   4225:        if (vpr != VPR_OK) {
                   4226:                (*pp)++;
1.896     rillig   4227:                *out_false_res = vpr;
                   4228:                *out_false_val = var_Error;
1.895     rillig   4229:                return false;
1.703     rillig   4230:        }
1.622     rillig   4231:
1.817     rillig   4232:        name[0] = varname;
1.703     rillig   4233:        name[1] = '\0';
1.895     rillig   4234:        v = VarFind(name, scope, true);
1.703     rillig   4235:        if (v == NULL) {
1.770     rillig   4236:                const char *val;
1.703     rillig   4237:                *pp += 2;
1.622     rillig   4238:
1.817     rillig   4239:                val = UndefinedShortVarValue(varname, scope);
1.770     rillig   4240:                if (val == NULL)
1.906     rillig   4241:                        val = emode == VARE_UNDEFERR
                   4242:                            ? var_Error : varUndefined;
1.769     rillig   4243:
1.770     rillig   4244:                if (opts.strict && val == var_Error) {
1.703     rillig   4245:                        Parse_Error(PARSE_FATAL,
                   4246:                            "Variable \"%s\" is undefined", name);
1.896     rillig   4247:                        *out_false_res = VPR_ERR;
                   4248:                        *out_false_val = val;
1.895     rillig   4249:                        return false;
1.703     rillig   4250:                }
1.767     rillig   4251:
                   4252:                /*
                   4253:                 * XXX: This looks completely wrong.
                   4254:                 *
                   4255:                 * If undefined expressions are not allowed, this should
                   4256:                 * rather be VPR_ERR instead of VPR_UNDEF, together with an
                   4257:                 * error message.
                   4258:                 *
                   4259:                 * If undefined expressions are allowed, this should rather
                   4260:                 * be VPR_UNDEF instead of VPR_OK.
                   4261:                 */
1.906     rillig   4262:                *out_false_res = emode == VARE_UNDEFERR
                   4263:                    ? VPR_UNDEF : VPR_OK;
1.896     rillig   4264:                *out_false_val = val;
1.895     rillig   4265:                return false;
1.622     rillig   4266:        }
                   4267:
1.896     rillig   4268:        *out_true_var = v;
1.895     rillig   4269:        return true;
1.622     rillig   4270: }
                   4271:
1.662     rillig   4272: /* Find variables like @F or <D. */
                   4273: static Var *
1.916     rillig   4274: FindLocalLegacyVar(Substring varname, GNode *scope,
1.662     rillig   4275:                   const char **out_extraModifiers)
                   4276: {
1.916     rillig   4277:        Var *v;
                   4278:
1.802     rillig   4279:        /* Only resolve these variables if scope is a "real" target. */
                   4280:        if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL)
1.703     rillig   4281:                return NULL;
                   4282:
1.916     rillig   4283:        if (Substring_Length(varname) != 2)
1.703     rillig   4284:                return NULL;
1.916     rillig   4285:        if (varname.start[1] != 'F' && varname.start[1] != 'D')
1.703     rillig   4286:                return NULL;
1.916     rillig   4287:        if (strchr("@%?*!<>", varname.start[0]) == NULL)
1.703     rillig   4288:                return NULL;
                   4289:
1.916     rillig   4290:        v = VarFindSubstring(Substring_Sub(varname, 0, 1), scope, false);
                   4291:        if (v == NULL)
                   4292:                return NULL;
1.897     rillig   4293:
1.916     rillig   4294:        *out_extraModifiers = varname.start[1] == 'D' ? "H:" : "T:";
                   4295:        return v;
1.662     rillig   4296: }
                   4297:
1.663     rillig   4298: static VarParseResult
1.916     rillig   4299: EvalUndefined(bool dynamic, const char *start, const char *p,
                   4300:              Substring varname, VarEvalMode emode, FStr *out_val)
1.667     rillig   4301: {
1.703     rillig   4302:        if (dynamic) {
1.740     rillig   4303:                *out_val = FStr_InitOwn(bmake_strsedup(start, p));
1.703     rillig   4304:                return VPR_OK;
                   4305:        }
                   4306:
1.906     rillig   4307:        if (emode == VARE_UNDEFERR && opts.strict) {
1.703     rillig   4308:                Parse_Error(PARSE_FATAL,
1.916     rillig   4309:                    "Variable \"%.*s\" is undefined",
                   4310:                    (int)Substring_Length(varname), varname.start);
1.740     rillig   4311:                *out_val = FStr_InitRefer(var_Error);
1.767     rillig   4312:                return VPR_ERR;
1.703     rillig   4313:        }
                   4314:
1.906     rillig   4315:        if (emode == VARE_UNDEFERR) {
1.740     rillig   4316:                *out_val = FStr_InitRefer(var_Error);
1.767     rillig   4317:                return VPR_UNDEF;       /* XXX: Should be VPR_ERR instead. */
1.703     rillig   4318:        }
                   4319:
1.740     rillig   4320:        *out_val = FStr_InitRefer(varUndefined);
1.663     rillig   4321:        return VPR_OK;
                   4322: }
                   4323:
1.778     rillig   4324: /*
                   4325:  * Parse a long variable name enclosed in braces or parentheses such as $(VAR)
1.623     rillig   4326:  * or ${VAR}, up to the closing brace or parenthesis, or in the case of
                   4327:  * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
1.778     rillig   4328:  * Return whether to continue parsing.
                   4329:  */
1.895     rillig   4330: static bool
1.623     rillig   4331: ParseVarnameLong(
1.922     rillig   4332:        const char **pp,
1.624     rillig   4333:        char startc,
1.802     rillig   4334:        GNode *scope,
1.906     rillig   4335:        VarEvalMode emode,
1.624     rillig   4336:
1.896     rillig   4337:        const char **out_false_pp,
                   4338:        VarParseResult *out_false_res,
                   4339:        FStr *out_false_val,
                   4340:
                   4341:        char *out_true_endc,
                   4342:        Var **out_true_v,
                   4343:        bool *out_true_haveModifier,
                   4344:        const char **out_true_extraModifiers,
                   4345:        bool *out_true_dynamic,
                   4346:        ExprDefined *out_true_exprDefined
1.703     rillig   4347: )
                   4348: {
1.916     rillig   4349:        LazyBuf varname;
1.703     rillig   4350:        Var *v;
1.895     rillig   4351:        bool haveModifier;
                   4352:        bool dynamic = false;
1.703     rillig   4353:
1.922     rillig   4354:        const char *p = *pp;
1.703     rillig   4355:        const char *const start = p;
                   4356:        char endc = startc == '(' ? ')' : '}';
                   4357:
                   4358:        p += 2;                 /* skip "${" or "$(" or "y(" */
1.916     rillig   4359:        ParseVarname(&p, startc, endc, scope, emode, &varname);
1.703     rillig   4360:
                   4361:        if (*p == ':') {
1.895     rillig   4362:                haveModifier = true;
1.703     rillig   4363:        } else if (*p == endc) {
1.895     rillig   4364:                haveModifier = false;
1.703     rillig   4365:        } else {
1.916     rillig   4366:                Substring name = LazyBuf_Get(&varname);
                   4367:                Parse_Error(PARSE_FATAL, "Unclosed variable \"%.*s\"",
                   4368:                    (int)Substring_Length(name), name.start);
                   4369:                LazyBuf_Done(&varname);
1.896     rillig   4370:                *out_false_pp = p;
                   4371:                *out_false_val = FStr_InitRefer(var_Error);
                   4372:                *out_false_res = VPR_ERR;
1.895     rillig   4373:                return false;
1.703     rillig   4374:        }
1.623     rillig   4375:
1.916     rillig   4376:        v = VarFindSubstring(LazyBuf_Get(&varname), scope, true);
1.623     rillig   4377:
1.703     rillig   4378:        /* At this point, p points just after the variable name,
                   4379:         * either at ':' or at endc. */
1.623     rillig   4380:
1.703     rillig   4381:        if (v == NULL) {
1.916     rillig   4382:                v = FindLocalLegacyVar(LazyBuf_Get(&varname), scope,
1.896     rillig   4383:                    out_true_extraModifiers);
1.703     rillig   4384:        }
1.623     rillig   4385:
1.703     rillig   4386:        if (v == NULL) {
                   4387:                /*
                   4388:                 * Defer expansion of dynamic variables if they appear in
1.802     rillig   4389:                 * non-local scope since they are not defined there.
1.703     rillig   4390:                 */
1.916     rillig   4391:                dynamic = VarnameIsDynamic(LazyBuf_Get(&varname)) &&
1.802     rillig   4392:                          (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL);
1.703     rillig   4393:
                   4394:                if (!haveModifier) {
                   4395:                        p++;    /* skip endc */
1.896     rillig   4396:                        *out_false_pp = p;
                   4397:                        *out_false_res = EvalUndefined(dynamic, start, p,
1.916     rillig   4398:                            LazyBuf_Get(&varname), emode, out_false_val);
1.895     rillig   4399:                        return false;
1.703     rillig   4400:                }
1.623     rillig   4401:
1.703     rillig   4402:                /*
                   4403:                 * The variable expression is based on an undefined variable.
                   4404:                 * Nevertheless it needs a Var, for modifiers that access the
                   4405:                 * variable name, such as :L or :?.
                   4406:                 *
                   4407:                 * Most modifiers leave this expression in the "undefined"
1.821     rillig   4408:                 * state (VES_UNDEF), only a few modifiers like :D, :U, :L,
1.703     rillig   4409:                 * :P turn this undefined expression into a defined
1.821     rillig   4410:                 * expression (VES_DEF).
1.703     rillig   4411:                 *
1.830     rillig   4412:                 * In the end, after applying all modifiers, if the expression
1.703     rillig   4413:                 * is still undefined, Var_Parse will return an empty string
                   4414:                 * instead of the actually computed value.
                   4415:                 */
1.916     rillig   4416:                v = VarNew(LazyBuf_DoneGet(&varname), "", false, false);
1.896     rillig   4417:                *out_true_exprDefined = DEF_UNDEF;
1.703     rillig   4418:        } else
1.916     rillig   4419:                LazyBuf_Done(&varname);
1.623     rillig   4420:
1.922     rillig   4421:        *pp = p;
1.896     rillig   4422:        *out_true_endc = endc;
                   4423:        *out_true_v = v;
                   4424:        *out_true_haveModifier = haveModifier;
                   4425:        *out_true_dynamic = dynamic;
1.895     rillig   4426:        return true;
1.623     rillig   4427: }
                   4428:
1.709     rillig   4429: /* Free the environment variable now since we own it. */
                   4430: static void
1.838     rillig   4431: FreeEnvVar(Var *v, FStr *inout_val)
1.709     rillig   4432: {
1.784     rillig   4433:        char *varValue = Buf_DoneData(&v->val);
1.838     rillig   4434:        if (inout_val->str == varValue)
                   4435:                inout_val->freeIt = varValue;
1.709     rillig   4436:        else
                   4437:                free(varValue);
                   4438:
1.711     rillig   4439:        FStr_Done(&v->name);
1.709     rillig   4440:        free(v);
                   4441: }
                   4442:
1.897     rillig   4443: #if __STDC_VERSION__ >= 199901L
1.917     rillig   4444: #define Expr_Literal(name, value, emode, scope, defined) \
                   4445:        { name, value, emode, scope, defined }
1.897     rillig   4446: #else
                   4447: MAKE_INLINE Expr
1.900     rillig   4448: Expr_Literal(const char *name, FStr value,
1.917     rillig   4449:             VarEvalMode emode, GNode *scope, ExprDefined defined)
1.897     rillig   4450: {
                   4451:        Expr expr;
                   4452:
1.898     rillig   4453:        expr.name = name;
1.897     rillig   4454:        expr.value = value;
1.917     rillig   4455:        expr.emode = emode;
1.897     rillig   4456:        expr.scope = scope;
                   4457:        expr.defined = defined;
                   4458:        return expr;
                   4459: }
                   4460: #endif
                   4461:
1.666     rillig   4462: /*
1.913     rillig   4463:  * Expressions of the form ${:U...} with a trivial value are often generated
                   4464:  * by .for loops and are boring, therefore parse and evaluate them in a fast
                   4465:  * lane without debug logging.
                   4466:  */
                   4467: static bool
                   4468: Var_Parse_FastLane(const char **pp, VarEvalMode emode, FStr *out_value)
                   4469: {
                   4470:        const char *p;
                   4471:
                   4472:        p = *pp;
                   4473:        if (!(p[0] == '$' && p[1] == '{' && p[2] == ':' && p[3] == 'U'))
                   4474:                return false;
                   4475:
                   4476:        p += 4;
1.915     rillig   4477:        while (*p != '$' && *p != '{' && *p != ':' && *p != '\\' &&
                   4478:               *p != '}' && *p != '\0')
1.913     rillig   4479:                p++;
                   4480:        if (*p != '}')
                   4481:                return false;
                   4482:
                   4483:        if (emode == VARE_PARSE_ONLY)
                   4484:                *out_value = FStr_InitRefer("");
                   4485:        else
                   4486:                *out_value = FStr_InitOwn(bmake_strsedup(*pp + 4, p));
                   4487:        *pp = p + 1;
                   4488:        return true;
                   4489: }
                   4490:
                   4491: /*
1.666     rillig   4492:  * Given the start of a variable expression (such as $v, $(VAR),
                   4493:  * ${VAR:Mpattern}), extract the variable name and value, and the modifiers,
                   4494:  * if any.  While doing that, apply the modifiers to the value of the
                   4495:  * expression, forming its final value.  A few of the modifiers such as :!cmd!
                   4496:  * or ::= have side effects.
1.579     rillig   4497:  *
1.108     sjg      4498:  * Input:
1.666     rillig   4499:  *     *pp             The string to parse.
                   4500:  *                     When parsing a condition in ParseEmptyArg, it may also
                   4501:  *                     point to the "y" of "empty(VARNAME:Modifiers)", which
                   4502:  *                     is syntactically the same.
1.802     rillig   4503:  *     scope           The scope for finding variables
1.917     rillig   4504:  *     emode           Controls the exact details of parsing and evaluation
1.666     rillig   4505:  *
                   4506:  * Output:
                   4507:  *     *pp             The position where to continue parsing.
                   4508:  *                     TODO: After a parse error, the value of *pp is
                   4509:  *                     unspecified.  It may not have been updated at all,
                   4510:  *                     point to some random character in the string, to the
                   4511:  *                     location of the parse error, or at the end of the
                   4512:  *                     string.
                   4513:  *     *out_val        The value of the variable expression, never NULL.
                   4514:  *     *out_val        var_Error if there was a parse error.
                   4515:  *     *out_val        var_Error if the base variable of the expression was
1.917     rillig   4516:  *                     undefined, emode is VARE_UNDEFERR, and none of
1.666     rillig   4517:  *                     the modifiers turned the undefined expression into a
                   4518:  *                     defined expression.
                   4519:  *                     XXX: It is not guaranteed that an error message has
                   4520:  *                     been printed.
                   4521:  *     *out_val        varUndefined if the base variable of the expression
1.917     rillig   4522:  *                     was undefined, emode was not VARE_UNDEFERR,
1.666     rillig   4523:  *                     and none of the modifiers turned the undefined
                   4524:  *                     expression into a defined expression.
                   4525:  *                     XXX: It is not guaranteed that an error message has
                   4526:  *                     been printed.
1.108     sjg      4527:  */
1.526     rillig   4528: VarParseResult
1.906     rillig   4529: Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
1.108     sjg      4530: {
1.703     rillig   4531:        const char *p = *pp;
                   4532:        const char *const start = p;
1.895     rillig   4533:        /* true if have modifiers for the variable. */
                   4534:        bool haveModifier;
1.703     rillig   4535:        /* Starting character if variable in parens or braces. */
                   4536:        char startc;
                   4537:        /* Ending character if variable in parens or braces. */
                   4538:        char endc;
                   4539:        /*
1.895     rillig   4540:         * true if the variable is local and we're expanding it in a
1.802     rillig   4541:         * non-local scope. This is done to support dynamic sources.
1.703     rillig   4542:         * The result is just the expression, unaltered.
                   4543:         */
1.895     rillig   4544:        bool dynamic;
1.703     rillig   4545:        const char *extramodifiers;
                   4546:        Var *v;
1.906     rillig   4547:        Expr expr = Expr_Literal(NULL, FStr_InitRefer(NULL), emode,
1.898     rillig   4548:            scope, DEF_REGULAR);
1.703     rillig   4549:
1.913     rillig   4550:        if (Var_Parse_FastLane(pp, emode, out_val))
                   4551:                return VPR_OK;
                   4552:
1.906     rillig   4553:        DEBUG2(VAR, "Var_Parse: %s (%s)\n", start, VarEvalMode_Name[emode]);
1.703     rillig   4554:
1.743     rillig   4555:        *out_val = FStr_InitRefer(NULL);
1.703     rillig   4556:        extramodifiers = NULL;  /* extra modifiers to apply first */
1.895     rillig   4557:        dynamic = false;
1.473     rillig   4558:
1.703     rillig   4559:        /*
                   4560:         * Appease GCC, which thinks that the variable might not be
                   4561:         * initialized.
                   4562:         */
                   4563:        endc = '\0';
1.108     sjg      4564:
1.703     rillig   4565:        startc = p[1];
                   4566:        if (startc != '(' && startc != '{') {
                   4567:                VarParseResult res;
1.906     rillig   4568:                if (!ParseVarnameShort(startc, pp, scope, emode, &res,
1.898     rillig   4569:                    &out_val->str, &v))
1.703     rillig   4570:                        return res;
1.895     rillig   4571:                haveModifier = false;
1.703     rillig   4572:                p++;
                   4573:        } else {
                   4574:                VarParseResult res;
1.922     rillig   4575:                if (!ParseVarnameLong(&p, startc, scope, emode,
1.743     rillig   4576:                    pp, &res, out_val,
1.922     rillig   4577:                    &endc, &v, &haveModifier, &extramodifiers,
1.825     rillig   4578:                    &dynamic, &expr.defined))
1.703     rillig   4579:                        return res;
                   4580:        }
1.401     rillig   4581:
1.898     rillig   4582:        expr.name = v->name.str;
1.902     rillig   4583:        if (v->inUse)
1.711     rillig   4584:                Fatal("Variable %s is recursive.", v->name.str);
1.187     christos 4585:
1.703     rillig   4586:        /*
                   4587:         * XXX: This assignment creates an alias to the current value of the
                   4588:         * variable.  This means that as long as the value of the expression
                   4589:         * stays the same, the value of the variable must not change.
                   4590:         * Using the '::=' modifier, it could be possible to do exactly this.
                   4591:         * At the bottom of this function, the resulting value is compared to
                   4592:         * the then-current value of the variable.  This might also invoke
                   4593:         * undefined behavior.
                   4594:         */
1.823     rillig   4595:        expr.value = FStr_InitRefer(v->val.data);
1.108     sjg      4596:
1.703     rillig   4597:        /*
                   4598:         * Before applying any modifiers, expand any nested expressions from
                   4599:         * the variable value.
                   4600:         */
1.906     rillig   4601:        if (strchr(expr.value.str, '$') != NULL &&
                   4602:            VarEvalMode_ShouldEval(emode)) {
1.743     rillig   4603:                char *expanded;
1.906     rillig   4604:                VarEvalMode nested_emode = emode;
1.764     rillig   4605:                if (opts.strict)
1.906     rillig   4606:                        nested_emode = VarEvalMode_UndefOk(nested_emode);
1.902     rillig   4607:                v->inUse = true;
1.906     rillig   4608:                (void)Var_Subst(expr.value.str, scope, nested_emode,
1.823     rillig   4609:                    &expanded);
1.902     rillig   4610:                v->inUse = false;
1.703     rillig   4611:                /* TODO: handle errors */
1.823     rillig   4612:                Expr_SetValueOwn(&expr, expanded);
1.191     dholland 4613:        }
                   4614:
1.855     rillig   4615:        if (extramodifiers != NULL) {
                   4616:                const char *em = extramodifiers;
                   4617:                ApplyModifiers(&expr, &em, '\0', '\0');
                   4618:        }
1.191     dholland 4619:
1.855     rillig   4620:        if (haveModifier) {
                   4621:                p++;    /* Skip initial colon. */
                   4622:                ApplyModifiers(&expr, &p, startc, endc);
1.191     dholland 4623:        }
1.438     rillig   4624:
1.703     rillig   4625:        if (*p != '\0')         /* Skip past endc if possible. */
                   4626:                p++;
1.519     rillig   4627:
1.703     rillig   4628:        *pp = p;
1.15      christos 4629:
1.902     rillig   4630:        if (v->fromEnv) {
1.838     rillig   4631:                FreeEnvVar(v, &expr.value);
1.703     rillig   4632:
1.825     rillig   4633:        } else if (expr.defined != DEF_REGULAR) {
                   4634:                if (expr.defined == DEF_UNDEF) {
1.703     rillig   4635:                        if (dynamic) {
1.823     rillig   4636:                                Expr_SetValueOwn(&expr,
                   4637:                                    bmake_strsedup(start, p));
1.703     rillig   4638:                        } else {
                   4639:                                /*
                   4640:                                 * The expression is still undefined,
                   4641:                                 * therefore discard the actual value and
                   4642:                                 * return an error marker instead.
                   4643:                                 */
1.823     rillig   4644:                                Expr_SetValueRefer(&expr,
1.906     rillig   4645:                                    emode == VARE_UNDEFERR
1.823     rillig   4646:                                        ? var_Error : varUndefined);
1.703     rillig   4647:                        }
                   4648:                }
1.823     rillig   4649:                /* XXX: This is not standard memory management. */
                   4650:                if (expr.value.str != v->val.data)
1.784     rillig   4651:                        Buf_Done(&v->val);
1.711     rillig   4652:                FStr_Done(&v->name);
1.703     rillig   4653:                free(v);
1.34      christos 4654:        }
1.823     rillig   4655:        *out_val = expr.value;
1.766     rillig   4656:        return VPR_OK;          /* XXX: Is not correct in all cases */
1.1       cgd      4657: }
                   4658:
1.678     rillig   4659: static void
1.906     rillig   4660: VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalMode emode)
1.768     rillig   4661: {
1.830     rillig   4662:        /* A dollar sign may be escaped with another dollar sign. */
1.906     rillig   4663:        if (save_dollars && VarEvalMode_ShouldKeepDollar(emode))
1.768     rillig   4664:                Buf_AddByte(res, '$');
                   4665:        Buf_AddByte(res, '$');
                   4666:        *pp += 2;
                   4667: }
                   4668:
                   4669: static void
1.802     rillig   4670: VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
1.906     rillig   4671:             VarEvalMode emode, bool *inout_errorReported)
1.678     rillig   4672: {
1.703     rillig   4673:        const char *p = *pp;
                   4674:        const char *nested_p = p;
1.743     rillig   4675:        FStr val;
1.703     rillig   4676:
1.906     rillig   4677:        (void)Var_Parse(&nested_p, scope, emode, &val);
1.703     rillig   4678:        /* TODO: handle errors */
1.678     rillig   4679:
1.743     rillig   4680:        if (val.str == var_Error || val.str == varUndefined) {
1.906     rillig   4681:                if (!VarEvalMode_ShouldKeepUndef(emode)) {
1.703     rillig   4682:                        p = nested_p;
1.906     rillig   4683:                } else if (emode == VARE_UNDEFERR || val.str == var_Error) {
1.703     rillig   4684:
                   4685:                        /*
                   4686:                         * XXX: This condition is wrong.  If val == var_Error,
                   4687:                         * this doesn't necessarily mean there was an undefined
                   4688:                         * variable.  It could equally well be a parse error;
                   4689:                         * see unit-tests/varmod-order.exp.
                   4690:                         */
                   4691:
                   4692:                        /*
                   4693:                         * If variable is undefined, complain and skip the
                   4694:                         * variable. The complaint will stop us from doing
                   4695:                         * anything when the file is parsed.
                   4696:                         */
                   4697:                        if (!*inout_errorReported) {
                   4698:                                Parse_Error(PARSE_FATAL,
                   4699:                                    "Undefined variable \"%.*s\"",
                   4700:                                    (int)(size_t)(nested_p - p), p);
                   4701:                        }
                   4702:                        p = nested_p;
1.895     rillig   4703:                        *inout_errorReported = true;
1.703     rillig   4704:                } else {
                   4705:                        /* Copy the initial '$' of the undefined expression,
                   4706:                         * thereby deferring expansion of the expression, but
                   4707:                         * expand nested expressions if already possible.
                   4708:                         * See unit-tests/varparse-undef-partial.mk. */
                   4709:                        Buf_AddByte(buf, *p);
                   4710:                        p++;
                   4711:                }
1.678     rillig   4712:        } else {
1.703     rillig   4713:                p = nested_p;
1.743     rillig   4714:                Buf_AddStr(buf, val.str);
1.678     rillig   4715:        }
                   4716:
1.743     rillig   4717:        FStr_Done(&val);
1.678     rillig   4718:
1.703     rillig   4719:        *pp = p;
1.678     rillig   4720: }
                   4721:
1.768     rillig   4722: /*
                   4723:  * Skip as many characters as possible -- either to the end of the string
                   4724:  * or to the next dollar sign (variable expression).
                   4725:  */
                   4726: static void
                   4727: VarSubstPlain(const char **pp, Buffer *res)
                   4728: {
                   4729:        const char *p = *pp;
                   4730:        const char *start = p;
                   4731:
                   4732:        for (p++; *p != '$' && *p != '\0'; p++)
                   4733:                continue;
                   4734:        Buf_AddBytesBetween(res, start, p);
                   4735:        *pp = p;
                   4736: }
                   4737:
1.778     rillig   4738: /*
                   4739:  * Expand all variable expressions like $V, ${VAR}, $(VAR:Modifiers) in the
1.660     rillig   4740:  * given string.
1.1       cgd      4741:  *
1.70      wiz      4742:  * Input:
1.660     rillig   4743:  *     str             The string in which the variable expressions are
                   4744:  *                     expanded.
1.802     rillig   4745:  *     scope           The scope in which to start searching for
                   4746:  *                     variables.  The other scopes are searched as well.
1.917     rillig   4747:  *     emode           The mode for parsing or evaluating subexpressions.
1.1       cgd      4748:  */
1.533     rillig   4749: VarParseResult
1.906     rillig   4750: Var_Subst(const char *str, GNode *scope, VarEvalMode emode, char **out_res)
1.1       cgd      4751: {
1.703     rillig   4752:        const char *p = str;
                   4753:        Buffer res;
1.1       cgd      4754:
1.703     rillig   4755:        /* Set true if an error has already been reported,
                   4756:         * to prevent a plethora of messages when recursing */
                   4757:        /* XXX: Why is the 'static' necessary here? */
1.895     rillig   4758:        static bool errorReported;
1.703     rillig   4759:
                   4760:        Buf_Init(&res);
1.895     rillig   4761:        errorReported = false;
1.703     rillig   4762:
                   4763:        while (*p != '\0') {
1.768     rillig   4764:                if (p[0] == '$' && p[1] == '$')
1.906     rillig   4765:                        VarSubstDollarDollar(&p, &res, emode);
1.768     rillig   4766:                else if (p[0] == '$')
1.906     rillig   4767:                        VarSubstExpr(&p, &res, scope, emode, &errorReported);
1.768     rillig   4768:                else
                   4769:                        VarSubstPlain(&p, &res);
1.1       cgd      4770:        }
1.15      christos 4771:
1.784     rillig   4772:        *out_res = Buf_DoneDataCompact(&res);
1.703     rillig   4773:        return VPR_OK;
1.1       cgd      4774: }
                   4775:
1.572     rillig   4776: /* Initialize the variables module. */
1.1       cgd      4777: void
1.70      wiz      4778: Var_Init(void)
1.1       cgd      4779: {
1.801     rillig   4780:        SCOPE_INTERNAL = GNode_New("Internal");
                   4781:        SCOPE_GLOBAL = GNode_New("Global");
                   4782:        SCOPE_CMDLINE = GNode_New("Command");
1.6       jtc      4783: }
                   4784:
1.572     rillig   4785: /* Clean up the variables module. */
1.6       jtc      4786: void
1.70      wiz      4787: Var_End(void)
1.6       jtc      4788: {
1.703     rillig   4789:        Var_Stats();
1.286     sjg      4790: }
                   4791:
                   4792: void
                   4793: Var_Stats(void)
                   4794: {
1.802     rillig   4795:        HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables");
1.1       cgd      4796: }
1.15      christos 4797:
1.802     rillig   4798: /* Print all variables in a scope, sorted by name. */
1.5       cgd      4799: void
1.802     rillig   4800: Var_Dump(GNode *scope)
1.1       cgd      4801: {
1.703     rillig   4802:        Vector /* of const char * */ vec;
                   4803:        HashIter hi;
                   4804:        size_t i;
                   4805:        const char **varnames;
                   4806:
                   4807:        Vector_Init(&vec, sizeof(const char *));
                   4808:
1.802     rillig   4809:        HashIter_Init(&hi, &scope->vars);
1.703     rillig   4810:        while (HashIter_Next(&hi) != NULL)
                   4811:                *(const char **)Vector_Push(&vec) = hi.entry->key;
                   4812:        varnames = vec.items;
                   4813:
                   4814:        qsort(varnames, vec.len, sizeof varnames[0], str_cmp_asc);
                   4815:
                   4816:        for (i = 0; i < vec.len; i++) {
                   4817:                const char *varname = varnames[i];
1.802     rillig   4818:                Var *var = HashTable_FindValue(&scope->vars, varname);
1.785     rillig   4819:                debug_printf("%-16s = %s\n", varname, var->val.data);
1.703     rillig   4820:        }
1.573     rillig   4821:
1.703     rillig   4822:        Vector_Done(&vec);
1.1       cgd      4823: }

CVSweb <webmaster@jp.NetBSD.org>