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

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

CVSweb <webmaster@jp.NetBSD.org>