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

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

CVSweb <webmaster@jp.NetBSD.org>