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

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

CVSweb <webmaster@jp.NetBSD.org>