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

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

CVSweb <webmaster@jp.NetBSD.org>