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

1.306   ! rillig      1: /*     $NetBSD: var.c,v 1.305 2020/07/24 08:12:43 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.88      ross       71: #ifndef MAKE_NATIVE
1.306   ! rillig     72: static char rcsid[] = "$NetBSD: var.c,v 1.305 2020/07/24 08:12:43 rillig Exp $";
1.23      lukem      73: #else
1.19      christos   74: #include <sys/cdefs.h>
1.1       cgd        75: #ifndef lint
1.11      christos   76: #if 0
1.15      christos   77: static char sccsid[] = "@(#)var.c      8.3 (Berkeley) 3/19/94";
1.11      christos   78: #else
1.306   ! rillig     79: __RCSID("$NetBSD: var.c,v 1.305 2020/07/24 08:12:43 rillig Exp $");
1.11      christos   80: #endif
1.1       cgd        81: #endif /* not lint */
1.23      lukem      82: #endif
1.1       cgd        83:
                     84: /*-
                     85:  * var.c --
                     86:  *     Variable-handling functions
                     87:  *
                     88:  * Interface:
1.138     dsl        89:  *     Var_Set             Set the value of a variable in the given
                     90:  *                         context. The variable is created if it doesn't
1.292     rillig     91:  *                         yet exist.
1.1       cgd        92:  *
                     93:  *     Var_Append          Append more characters to an existing variable
1.138     dsl        94:  *                         in the given context. The variable needn't
                     95:  *                         exist already -- it will be created if it doesn't.
                     96:  *                         A space is placed between the old value and the
                     97:  *                         new one.
1.1       cgd        98:  *
                     99:  *     Var_Exists          See if a variable exists.
                    100:  *
                    101:  *     Var_Value           Return the value of a variable in a context or
1.138     dsl       102:  *                         NULL if the variable is undefined.
1.1       cgd       103:  *
1.250     rillig    104:  *     Var_Subst           Substitute either a single variable or all
1.292     rillig    105:  *                         variables in a string, using the given context.
1.1       cgd       106:  *
                    107:  *     Var_Parse           Parse a variable expansion from a string and
1.138     dsl       108:  *                         return the result and the number of characters
                    109:  *                         consumed.
1.1       cgd       110:  *
                    111:  *     Var_Delete          Delete a variable in a context.
                    112:  *
                    113:  *     Var_Init            Initialize this module.
                    114:  *
                    115:  * Debugging:
                    116:  *     Var_Dump            Print out all variables defined in the given
1.138     dsl       117:  *                         context.
1.1       cgd       118:  *
                    119:  * XXX: There's a lot of duplication in these functions.
                    120:  */
                    121:
1.157     sjg       122: #include    <sys/stat.h>
1.31      gwr       123: #ifndef NO_REGEX
1.28      wsanchez  124: #include    <sys/types.h>
1.16      christos  125: #include    <regex.h>
1.17      christos  126: #endif
1.70      wiz       127: #include    <ctype.h>
1.163     joerg     128: #include    <inttypes.h>
1.292     rillig    129: #include    <limits.h>
1.17      christos  130: #include    <stdlib.h>
1.166     tsutsui   131: #include    <time.h>
1.70      wiz       132:
1.1       cgd       133: #include    "make.h"
                    134: #include    "buf.h"
1.103     sjg       135: #include    "dir.h"
1.111     rillig    136: #include    "job.h"
1.193     christos  137: #include    "metachar.h"
1.1       cgd       138:
                    139: /*
1.170     sjg       140:  * This lets us tell if we have replaced the original environ
                    141:  * (which we cannot free).
                    142:  */
                    143: char **savedEnv = NULL;
                    144:
                    145: /*
1.1       cgd       146:  * This is a harmless return value for Var_Parse that can be used by Var_Subst
                    147:  * to determine if there was an error in parsing -- easier than returning
                    148:  * a flag, as things outside this module don't give a hoot.
                    149:  */
1.249     rillig    150: char var_Error[] = "";
1.1       cgd       151:
                    152: /*
1.259     rillig    153:  * Similar to var_Error, but returned when the 'VARE_UNDEFERR' flag for
1.292     rillig    154:  * Var_Parse is not set. Why not just use a constant? Well, GCC likes
1.202     christos  155:  * to condense identical string instances...
1.1       cgd       156:  */
1.249     rillig    157: static char varNoError[] = "";
1.1       cgd       158:
                    159: /*
1.205     sjg       160:  * Traditionally we consume $$ during := like any other expansion.
                    161:  * Other make's do not.
                    162:  * This knob allows controlling the behavior.
1.292     rillig    163:  * FALSE to consume $$ during := assignment.
                    164:  * TRUE to preserve $$ during := assignment.
1.205     sjg       165:  */
                    166: #define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
                    167: static Boolean save_dollars = TRUE;
                    168:
                    169: /*
1.1       cgd       170:  * Internally, variables are contained in four different contexts.
1.292     rillig    171:  *     1) the environment. They cannot be changed. If an environment
                    172:  *         variable is appended to, the result is placed in the global
1.1       cgd       173:  *         context.
                    174:  *     2) the global context. Variables set in the Makefile are located in
1.292     rillig    175:  *         the global context.
1.1       cgd       176:  *     3) the command-line context. All variables set on the command line
                    177:  *        are placed in this context. They are UNALTERABLE once placed here.
                    178:  *     4) the local context. Each target has associated with it a context
                    179:  *        list. On this list are located the structures describing such
                    180:  *        local variables as $(@) and $(*)
                    181:  * The four contexts are searched in the reverse order from which they are
1.292     rillig    182:  * listed (but see checkEnvFirst).
1.1       cgd       183:  */
1.240     rillig    184: GNode          *VAR_INTERNAL;  /* variables from make itself */
                    185: GNode          *VAR_GLOBAL;    /* variables from the makefile */
                    186: GNode          *VAR_CMD;       /* variables defined on the command-line */
                    187:
1.260     rillig    188: typedef enum {
                    189:     FIND_CMD           = 0x01, /* look in VAR_CMD when searching */
                    190:     FIND_GLOBAL                = 0x02, /* look in VAR_GLOBAL as well */
                    191:     FIND_ENV           = 0x04  /* look in the environment also */
                    192: } VarFindFlags;
1.1       cgd       193:
1.228     rillig    194: typedef enum {
1.292     rillig    195:     VAR_IN_USE         = 0x01, /* Variable's value is currently being used
                    196:                                 * by Var_Parse or Var_Subst.
1.228     rillig    197:                                 * Used to avoid endless recursion */
1.240     rillig    198:     VAR_FROM_ENV       = 0x02, /* Variable comes from the environment */
                    199:     VAR_JUNK           = 0x04, /* Variable is a junk variable that
1.228     rillig    200:                                 * should be destroyed when done with
                    201:                                 * it. Used by Var_Parse for undefined,
                    202:                                 * modified variables */
1.240     rillig    203:     VAR_KEEP           = 0x08, /* Variable is VAR_JUNK, but we found
1.228     rillig    204:                                 * a use for it in some modifier and
                    205:                                 * the value is therefore valid */
1.240     rillig    206:     VAR_EXPORTED       = 0x10, /* Variable is exported */
                    207:     VAR_REEXPORT       = 0x20, /* Indicate if var needs re-export.
1.228     rillig    208:                                 * This would be true if it contains $'s */
1.240     rillig    209:     VAR_FROM_CMD       = 0x40  /* Variable came from command line */
1.228     rillig    210: } Var_Flags;
                    211:
1.1       cgd       212: typedef struct Var {
                    213:     char          *name;       /* the variable's name */
1.138     dsl       214:     Buffer       val;          /* its value */
1.228     rillig    215:     Var_Flags    flags;        /* miscellaneous status flags */
1.1       cgd       216: }  Var;
                    217:
1.118     sjg       218: /*
                    219:  * Exporting vars is expensive so skip it if we can
                    220:  */
1.292     rillig    221: typedef enum {
                    222:     VAR_EXPORTED_NONE,
                    223:     VAR_EXPORTED_YES,
                    224:     VAR_EXPORTED_ALL
                    225: } VarExportedMode;
                    226: static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
                    227:
                    228: typedef enum {
                    229:     /*
                    230:      * We pass this to Var_Export when doing the initial export
                    231:      * or after updating an exported var.
                    232:      */
                    233:     VAR_EXPORT_PARENT  = 0x01,
                    234:     /*
                    235:      * We pass this to Var_Export1 to tell it to leave the value alone.
                    236:      */
                    237:     VAR_EXPORT_LITERAL = 0x02
                    238: } VarExportFlags;
1.16      christos  239:
1.261     rillig    240: /* Flags for pattern matching in the :S and :C modifiers */
1.229     rillig    241: typedef enum {
1.261     rillig    242:     VARP_SUB_GLOBAL    = 0x01, /* Apply substitution globally */
                    243:     VARP_SUB_ONE       = 0x02, /* Apply substitution to one word */
                    244:     VARP_SUB_MATCHED   = 0x04, /* There was a match */
1.288     rillig    245:     VARP_ANCHOR_START  = 0x08, /* Match at start of word */
                    246:     VARP_ANCHOR_END    = 0x10  /* Match at end of word */
1.261     rillig    247: } VarPatternFlags;
1.16      christos  248:
1.230     rillig    249: typedef enum {
1.292     rillig    250:     VAR_NO_EXPORT      = 0x01  /* do not export */
1.230     rillig    251: } VarSet_Flags;
1.65      sjg       252:
1.100     christos  253: #define BROPEN '{'
                    254: #define BRCLOSE        '}'
                    255: #define PROPEN '('
                    256: #define PRCLOSE        ')'
                    257:
1.1       cgd       258: /*-
                    259:  *-----------------------------------------------------------------------
                    260:  * VarFind --
                    261:  *     Find the given variable in the given context and any other contexts
                    262:  *     indicated.
                    263:  *
1.70      wiz       264:  * Input:
                    265:  *     name            name to find
                    266:  *     ctxt            context in which to find it
1.260     rillig    267:  *     flags           FIND_GLOBAL     look in VAR_GLOBAL as well
                    268:  *                     FIND_CMD        look in VAR_CMD as well
                    269:  *                     FIND_ENV        look in the environment as well
1.70      wiz       270:  *
1.1       cgd       271:  * Results:
                    272:  *     A pointer to the structure describing the desired variable or
1.136     dsl       273:  *     NULL if the variable does not exist.
1.1       cgd       274:  *
                    275:  * Side Effects:
                    276:  *     None
                    277:  *-----------------------------------------------------------------------
                    278:  */
                    279: static Var *
1.260     rillig    280: VarFind(const char *name, GNode *ctxt, VarFindFlags flags)
1.1       cgd       281: {
1.36      mycroft   282:     Hash_Entry                 *var;
1.138     dsl       283:     Var                        *v;
1.1       cgd       284:
1.242     rillig    285:     /*
                    286:      * If the variable name begins with a '.', it could very well be one of
                    287:      * the local ones.  We check the name against all the local variables
                    288:      * and substitute the short version in for 'name' if it matches one of
                    289:      * them.
                    290:      */
                    291:     if (*name == '.' && isupper((unsigned char) name[1])) {
                    292:        switch (name[1]) {
                    293:        case 'A':
1.257     rillig    294:            if (strcmp(name, ".ALLSRC") == 0)
1.242     rillig    295:                name = ALLSRC;
1.257     rillig    296:            if (strcmp(name, ".ARCHIVE") == 0)
1.242     rillig    297:                name = ARCHIVE;
                    298:            break;
                    299:        case 'I':
1.257     rillig    300:            if (strcmp(name, ".IMPSRC") == 0)
1.242     rillig    301:                name = IMPSRC;
                    302:            break;
                    303:        case 'M':
1.257     rillig    304:            if (strcmp(name, ".MEMBER") == 0)
1.242     rillig    305:                name = MEMBER;
                    306:            break;
                    307:        case 'O':
1.257     rillig    308:            if (strcmp(name, ".OODATE") == 0)
1.242     rillig    309:                name = OODATE;
                    310:            break;
                    311:        case 'P':
1.257     rillig    312:            if (strcmp(name, ".PREFIX") == 0)
1.242     rillig    313:                name = PREFIX;
                    314:            break;
                    315:        case 'T':
1.257     rillig    316:            if (strcmp(name, ".TARGET") == 0)
1.242     rillig    317:                name = TARGET;
                    318:            break;
                    319:        }
                    320:     }
                    321:
1.160     christos  322: #ifdef notyet
                    323:     /* for compatibility with gmake */
                    324:     if (name[0] == '^' && name[1] == '\0')
1.242     rillig    325:        name = ALLSRC;
1.160     christos  326: #endif
                    327:
1.1       cgd       328:     /*
                    329:      * First look for the variable in the given context. If it's not there,
                    330:      * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
                    331:      * depending on the FIND_* flags in 'flags'
                    332:      */
1.92      christos  333:     var = Hash_FindEntry(&ctxt->context, name);
1.1       cgd       334:
1.231     rillig    335:     if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) {
1.92      christos  336:        var = Hash_FindEntry(&VAR_CMD->context, name);
1.1       cgd       337:     }
1.231     rillig    338:     if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) &&
                    339:        ctxt != VAR_GLOBAL)
1.1       cgd       340:     {
1.92      christos  341:        var = Hash_FindEntry(&VAR_GLOBAL->context, name);
1.231     rillig    342:        if (var == NULL && ctxt != VAR_INTERNAL) {
1.184     sjg       343:            /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
                    344:            var = Hash_FindEntry(&VAR_INTERNAL->context, name);
                    345:        }
1.1       cgd       346:     }
1.231     rillig    347:     if (var == NULL && (flags & FIND_ENV)) {
1.1       cgd       348:        char *env;
                    349:
1.97      christos  350:        if ((env = getenv(name)) != NULL) {
1.257     rillig    351:            int len;
1.15      christos  352:
1.134     joerg     353:            v = bmake_malloc(sizeof(Var));
                    354:            v->name = bmake_strdup(name);
1.1       cgd       355:
                    356:            len = strlen(env);
1.15      christos  357:
1.146     dsl       358:            Buf_Init(&v->val, len + 1);
                    359:            Buf_AddBytes(&v->val, len, env);
1.15      christos  360:
1.1       cgd       361:            v->flags = VAR_FROM_ENV;
1.231     rillig    362:            return v;
1.1       cgd       363:        } else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
1.231     rillig    364:                   ctxt != VAR_GLOBAL)
1.1       cgd       365:        {
1.92      christos  366:            var = Hash_FindEntry(&VAR_GLOBAL->context, name);
1.231     rillig    367:            if (var == NULL && ctxt != VAR_INTERNAL) {
1.184     sjg       368:                var = Hash_FindEntry(&VAR_INTERNAL->context, name);
                    369:            }
1.36      mycroft   370:            if (var == NULL) {
1.136     dsl       371:                return NULL;
1.1       cgd       372:            } else {
1.231     rillig    373:                return (Var *)Hash_GetValue(var);
1.1       cgd       374:            }
                    375:        } else {
1.136     dsl       376:            return NULL;
1.1       cgd       377:        }
1.36      mycroft   378:     } else if (var == NULL) {
1.136     dsl       379:        return NULL;
1.1       cgd       380:     } else {
1.231     rillig    381:        return (Var *)Hash_GetValue(var);
1.1       cgd       382:     }
                    383: }
                    384:
                    385: /*-
                    386:  *-----------------------------------------------------------------------
1.105     christos  387:  * VarFreeEnv  --
                    388:  *     If the variable is an environment variable, free it
                    389:  *
                    390:  * Input:
                    391:  *     v               the variable
                    392:  *     destroy         true if the value buffer should be destroyed.
                    393:  *
                    394:  * Results:
                    395:  *     1 if it is an environment variable 0 ow.
                    396:  *
                    397:  * Side Effects:
                    398:  *     The variable is free'ed if it is an environent variable.
                    399:  *-----------------------------------------------------------------------
                    400:  */
                    401: static Boolean
                    402: VarFreeEnv(Var *v, Boolean destroy)
                    403: {
1.257     rillig    404:     if (!(v->flags & VAR_FROM_ENV))
1.105     christos  405:        return FALSE;
                    406:     free(v->name);
1.146     dsl       407:     Buf_Destroy(&v->val, destroy);
1.105     christos  408:     free(v);
                    409:     return TRUE;
                    410: }
                    411:
                    412: /*-
                    413:  *-----------------------------------------------------------------------
1.1       cgd       414:  * VarAdd  --
                    415:  *     Add a new variable of name name and value val to the given context
                    416:  *
1.70      wiz       417:  * Input:
                    418:  *     name            name of variable to add
                    419:  *     val             value to set it to
                    420:  *     ctxt            context in which to set it
                    421:  *
1.1       cgd       422:  * Side Effects:
                    423:  *     The new variable is placed at the front of the given context
                    424:  *     The name and val arguments are duplicated so they may
                    425:  *     safely be freed.
                    426:  *-----------------------------------------------------------------------
                    427:  */
1.5       cgd       428: static void
1.73      christos  429: VarAdd(const char *name, const char *val, GNode *ctxt)
1.1       cgd       430: {
1.70      wiz       431:     Var          *v;
1.138     dsl       432:     int                  len;
1.70      wiz       433:     Hash_Entry    *h;
1.1       cgd       434:
1.134     joerg     435:     v = bmake_malloc(sizeof(Var));
1.1       cgd       436:
1.257     rillig    437:     len = val != NULL ? strlen(val) : 0;
1.242     rillig    438:     Buf_Init(&v->val, len + 1);
1.146     dsl       439:     Buf_AddBytes(&v->val, len, val);
1.1       cgd       440:
                    441:     v->flags = 0;
                    442:
1.92      christos  443:     h = Hash_CreateEntry(&ctxt->context, name, NULL);
1.36      mycroft   444:     Hash_SetValue(h, v);
1.37      sommerfe  445:     v->name = h->name;
1.257     rillig    446:     if (DEBUG(VAR) && !(ctxt->flags & INTERNAL)) {
1.114     dsl       447:        fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
1.1       cgd       448:     }
                    449: }
                    450:
                    451: /*-
                    452:  *-----------------------------------------------------------------------
                    453:  * Var_Delete --
                    454:  *     Remove a variable from a context.
                    455:  *
                    456:  * Side Effects:
                    457:  *     The Var structure is removed and freed.
                    458:  *
                    459:  *-----------------------------------------------------------------------
                    460:  */
                    461: void
1.73      christos  462: Var_Delete(const char *name, GNode *ctxt)
1.1       cgd       463: {
1.36      mycroft   464:     Hash_Entry           *ln;
1.174     sjg       465:     char *cp;
1.231     rillig    466:
1.257     rillig    467:     if (strchr(name, '$') != NULL) {
1.259     rillig    468:        cp = Var_Subst(NULL, name, VAR_GLOBAL, VARE_WANTRES);
1.174     sjg       469:     } else {
1.257     rillig    470:        cp = UNCONST(name);
1.174     sjg       471:     }
                    472:     ln = Hash_FindEntry(&ctxt->context, cp);
1.1       cgd       473:     if (DEBUG(VAR)) {
1.117     dsl       474:        fprintf(debug_file, "%s:delete %s%s\n",
1.174     sjg       475:            ctxt->name, cp, ln ? "" : " (not found)");
                    476:     }
1.257     rillig    477:     if (cp != name)
1.174     sjg       478:        free(cp);
1.36      mycroft   479:     if (ln != NULL) {
1.257     rillig    480:        Var *v = (Var *)Hash_GetValue(ln);
1.292     rillig    481:        if (v->flags & VAR_EXPORTED)
1.118     sjg       482:            unsetenv(v->name);
1.292     rillig    483:        if (strcmp(MAKE_EXPORTED, v->name) == 0)
1.155     sjg       484:            var_exportedVars = VAR_EXPORTED_NONE;
1.37      sommerfe  485:        if (v->name != ln->name)
1.242     rillig    486:            free(v->name);
1.36      mycroft   487:        Hash_DeleteEntry(&ctxt->context, ln);
1.146     dsl       488:        Buf_Destroy(&v->val, TRUE);
1.98      christos  489:        free(v);
1.1       cgd       490:     }
                    491: }
                    492:
1.118     sjg       493:
                    494: /*
                    495:  * Export a var.
                    496:  * We ignore make internal variables (those which start with '.')
                    497:  * Also we jump through some hoops to avoid calling setenv
                    498:  * more than necessary since it can leak.
1.152     sjg       499:  * We only manipulate flags of vars if 'parent' is set.
1.118     sjg       500:  */
                    501: static int
1.292     rillig    502: Var_Export1(const char *name, VarExportFlags flags)
1.118     sjg       503: {
                    504:     char tmp[BUFSIZ];
                    505:     Var *v;
                    506:     char *val = NULL;
                    507:     int n;
1.292     rillig    508:     VarExportFlags parent = flags & VAR_EXPORT_PARENT;
1.118     sjg       509:
                    510:     if (*name == '.')
1.240     rillig    511:        return 0;               /* skip internals */
1.118     sjg       512:     if (!name[1]) {
                    513:        /*
                    514:         * A single char.
                    515:         * If it is one of the vars that should only appear in
                    516:         * local context, skip it, else we can get Var_Subst
                    517:         * into a loop.
                    518:         */
                    519:        switch (name[0]) {
                    520:        case '@':
                    521:        case '%':
                    522:        case '*':
                    523:        case '!':
                    524:            return 0;
                    525:        }
                    526:     }
                    527:     v = VarFind(name, VAR_GLOBAL, 0);
1.257     rillig    528:     if (v == NULL)
1.118     sjg       529:        return 0;
1.152     sjg       530:     if (!parent &&
1.292     rillig    531:        (v->flags & (VAR_EXPORTED | VAR_REEXPORT)) == VAR_EXPORTED) {
1.118     sjg       532:        return 0;                       /* nothing to do */
                    533:     }
1.146     dsl       534:     val = Buf_GetAll(&v->val, NULL);
1.203     sjg       535:     if ((flags & VAR_EXPORT_LITERAL) == 0 && strchr(val, '$')) {
1.152     sjg       536:        if (parent) {
1.118     sjg       537:            /*
1.152     sjg       538:             * Flag this as something we need to re-export.
1.118     sjg       539:             * No point actually exporting it now though,
                    540:             * the child can do it at the last minute.
                    541:             */
1.292     rillig    542:            v->flags |= (VAR_EXPORTED | VAR_REEXPORT);
1.118     sjg       543:            return 1;
                    544:        }
1.158     sjg       545:        if (v->flags & VAR_IN_USE) {
                    546:            /*
                    547:             * We recursed while exporting in a child.
                    548:             * This isn't going to end well, just skip it.
                    549:             */
                    550:            return 0;
                    551:        }
1.118     sjg       552:        n = snprintf(tmp, sizeof(tmp), "${%s}", name);
1.147     lukem     553:        if (n < (int)sizeof(tmp)) {
1.259     rillig    554:            val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARE_WANTRES);
1.118     sjg       555:            setenv(name, val, 1);
                    556:            free(val);
                    557:        }
                    558:     } else {
1.292     rillig    559:        if (parent)
1.152     sjg       560:            v->flags &= ~VAR_REEXPORT;  /* once will do */
1.292     rillig    561:        if (parent || !(v->flags & VAR_EXPORTED))
1.118     sjg       562:            setenv(name, val, 1);
                    563:     }
                    564:     /*
                    565:      * This is so Var_Set knows to call Var_Export again...
                    566:      */
1.152     sjg       567:     if (parent) {
                    568:        v->flags |= VAR_EXPORTED;
                    569:     }
1.118     sjg       570:     return 1;
                    571: }
                    572:
1.241     rillig    573: static void
                    574: Var_ExportVars_callback(void *entry, void *unused MAKE_ATTR_UNUSED)
                    575: {
1.242     rillig    576:     Var *var = entry;
                    577:     Var_Export1(var->name, 0);
1.241     rillig    578: }
                    579:
1.118     sjg       580: /*
                    581:  * This gets called from our children.
                    582:  */
                    583: void
                    584: Var_ExportVars(void)
                    585: {
                    586:     char tmp[BUFSIZ];
                    587:     char *val;
                    588:     int n;
                    589:
1.182     christos  590:     /*
                    591:      * Several make's support this sort of mechanism for tracking
                    592:      * recursion - but each uses a different name.
                    593:      * We allow the makefiles to update MAKELEVEL and ensure
                    594:      * children see a correctly incremented value.
                    595:      */
                    596:     snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
                    597:     setenv(MAKE_LEVEL_ENV, tmp, 1);
                    598:
1.118     sjg       599:     if (VAR_EXPORTED_NONE == var_exportedVars)
                    600:        return;
                    601:
                    602:     if (VAR_EXPORTED_ALL == var_exportedVars) {
1.241     rillig    603:        /* Ouch! This is crazy... */
                    604:        Hash_ForEach(&VAR_GLOBAL->context, Var_ExportVars_callback, NULL);
1.118     sjg       605:        return;
                    606:     }
                    607:     /*
                    608:      * We have a number of exported vars,
                    609:      */
                    610:     n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
1.147     lukem     611:     if (n < (int)sizeof(tmp)) {
1.118     sjg       612:        char **av;
                    613:        char *as;
1.127     christos  614:        int ac;
1.118     sjg       615:        int i;
1.142     dsl       616:
1.259     rillig    617:        val = Var_Subst(NULL, tmp, VAR_GLOBAL, VARE_WANTRES);
1.200     sjg       618:        if (*val) {
                    619:            av = brk_string(val, &ac, FALSE, &as);
1.257     rillig    620:            for (i = 0; i < ac; i++)
1.200     sjg       621:                Var_Export1(av[i], 0);
                    622:            free(as);
                    623:            free(av);
1.118     sjg       624:        }
                    625:        free(val);
                    626:     }
                    627: }
                    628:
                    629: /*
                    630:  * This is called when .export is seen or
                    631:  * .MAKE.EXPORTED is modified.
                    632:  * It is also called when any exported var is modified.
                    633:  */
                    634: void
                    635: Var_Export(char *str, int isExport)
                    636: {
                    637:     char **av;
                    638:     char *as;
1.302     rillig    639:     VarExportFlags flags;
1.127     christos  640:     int ac;
1.118     sjg       641:     int i;
                    642:
                    643:     if (isExport && (!str || !str[0])) {
                    644:        var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
                    645:        return;
                    646:     }
                    647:
1.203     sjg       648:     flags = 0;
1.159     sjg       649:     if (strncmp(str, "-env", 4) == 0) {
                    650:        str += 4;
1.203     sjg       651:     } else if (strncmp(str, "-literal", 8) == 0) {
                    652:        str += 8;
                    653:        flags |= VAR_EXPORT_LITERAL;
1.159     sjg       654:     } else {
1.203     sjg       655:        flags |= VAR_EXPORT_PARENT;
1.159     sjg       656:     }
1.302     rillig    657:
                    658:     char *val = Var_Subst(NULL, str, VAR_GLOBAL, VARE_WANTRES);
1.200     sjg       659:     if (*val) {
                    660:        av = brk_string(val, &ac, FALSE, &as);
                    661:        for (i = 0; i < ac; i++) {
1.302     rillig    662:            const char *name = av[i];
1.200     sjg       663:            if (!name[1]) {
                    664:                /*
                    665:                 * A single char.
                    666:                 * If it is one of the vars that should only appear in
                    667:                 * local context, skip it, else we can get Var_Subst
                    668:                 * into a loop.
                    669:                 */
                    670:                switch (name[0]) {
                    671:                case '@':
                    672:                case '%':
                    673:                case '*':
                    674:                case '!':
                    675:                    continue;
                    676:                }
1.118     sjg       677:            }
1.203     sjg       678:            if (Var_Export1(name, flags)) {
1.200     sjg       679:                if (VAR_EXPORTED_ALL != var_exportedVars)
                    680:                    var_exportedVars = VAR_EXPORTED_YES;
1.203     sjg       681:                if (isExport && (flags & VAR_EXPORT_PARENT)) {
1.200     sjg       682:                    Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
                    683:                }
1.118     sjg       684:            }
                    685:        }
1.200     sjg       686:        free(as);
                    687:        free(av);
1.118     sjg       688:     }
                    689:     free(val);
                    690: }
                    691:
1.155     sjg       692:
1.257     rillig    693: extern char **environ;
                    694:
1.155     sjg       695: /*
                    696:  * This is called when .unexport[-env] is seen.
                    697:  */
                    698: void
                    699: Var_UnExport(char *str)
                    700: {
                    701:     char tmp[BUFSIZ];
                    702:     char *vlist;
                    703:     char *cp;
                    704:     Boolean unexport_env;
                    705:     int n;
                    706:
1.257     rillig    707:     if (str == NULL || str[0] == '\0')
1.242     rillig    708:        return;                 /* assert? */
1.155     sjg       709:
                    710:     vlist = NULL;
                    711:
                    712:     str += 8;
                    713:     unexport_env = (strncmp(str, "-env", 4) == 0);
                    714:     if (unexport_env) {
                    715:        char **newenv;
                    716:
1.179     sjg       717:        cp = getenv(MAKE_LEVEL_ENV);    /* we should preserve this */
1.170     sjg       718:        if (environ == savedEnv) {
1.155     sjg       719:            /* we have been here before! */
                    720:            newenv = bmake_realloc(environ, 2 * sizeof(char *));
                    721:        } else {
1.170     sjg       722:            if (savedEnv) {
                    723:                free(savedEnv);
                    724:                savedEnv = NULL;
1.155     sjg       725:            }
                    726:            newenv = bmake_malloc(2 * sizeof(char *));
                    727:        }
                    728:        if (!newenv)
                    729:            return;
                    730:        /* Note: we cannot safely free() the original environ. */
1.170     sjg       731:        environ = savedEnv = newenv;
1.155     sjg       732:        newenv[0] = NULL;
                    733:        newenv[1] = NULL;
1.221     sjg       734:        if (cp && *cp)
                    735:            setenv(MAKE_LEVEL_ENV, cp, 1);
1.155     sjg       736:     } else {
                    737:        for (; *str != '\n' && isspace((unsigned char) *str); str++)
                    738:            continue;
                    739:        if (str[0] && str[0] != '\n') {
                    740:            vlist = str;
                    741:        }
                    742:     }
                    743:
                    744:     if (!vlist) {
                    745:        /* Using .MAKE.EXPORTED */
1.257     rillig    746:        vlist = Var_Subst(NULL, "${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL,
1.259     rillig    747:                          VARE_WANTRES);
1.155     sjg       748:     }
                    749:     if (vlist) {
                    750:        Var *v;
                    751:        char **av;
                    752:        char *as;
                    753:        int ac;
                    754:        int i;
                    755:
                    756:        av = brk_string(vlist, &ac, FALSE, &as);
                    757:        for (i = 0; i < ac; i++) {
                    758:            v = VarFind(av[i], VAR_GLOBAL, 0);
                    759:            if (!v)
                    760:                continue;
                    761:            if (!unexport_env &&
1.292     rillig    762:                (v->flags & (VAR_EXPORTED | VAR_REEXPORT)) == VAR_EXPORTED)
1.155     sjg       763:                unsetenv(v->name);
1.292     rillig    764:            v->flags &= ~(VAR_EXPORTED | VAR_REEXPORT);
1.155     sjg       765:            /*
                    766:             * If we are unexporting a list,
                    767:             * remove each one from .MAKE.EXPORTED.
                    768:             * If we are removing them all,
                    769:             * just delete .MAKE.EXPORTED below.
                    770:             */
                    771:            if (vlist == str) {
                    772:                n = snprintf(tmp, sizeof(tmp),
                    773:                             "${" MAKE_EXPORTED ":N%s}", v->name);
                    774:                if (n < (int)sizeof(tmp)) {
1.259     rillig    775:                    cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARE_WANTRES);
1.230     rillig    776:                    Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL);
1.155     sjg       777:                    free(cp);
                    778:                }
                    779:            }
                    780:        }
                    781:        free(as);
                    782:        free(av);
                    783:        if (vlist != str) {
                    784:            Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
                    785:            free(vlist);
                    786:        }
                    787:     }
                    788: }
                    789:
1.230     rillig    790: static void
1.242     rillig    791: Var_Set_with_flags(const char *name, const char *val, GNode *ctxt,
                    792:                   VarSet_Flags flags)
1.1       cgd       793: {
1.249     rillig    794:     Var *v;
1.139     dsl       795:     char *expanded_name = NULL;
1.142     dsl       796:
1.1       cgd       797:     /*
                    798:      * We only look for a variable in the given context since anything set
                    799:      * here will override anything in a lower context, so there's not much
                    800:      * point in searching them all just to save a bit of memory...
                    801:      */
1.139     dsl       802:     if (strchr(name, '$') != NULL) {
1.259     rillig    803:        expanded_name = Var_Subst(NULL, name, ctxt, VARE_WANTRES);
1.257     rillig    804:        if (expanded_name[0] == '\0') {
1.139     dsl       805:            if (DEBUG(VAR)) {
                    806:                fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
                    807:                        "name expands to empty string - ignored\n",
                    808:                        name, val);
                    809:            }
                    810:            free(expanded_name);
                    811:            return;
                    812:        }
                    813:        name = expanded_name;
                    814:     }
1.129     sjg       815:     if (ctxt == VAR_GLOBAL) {
                    816:        v = VarFind(name, VAR_CMD, 0);
1.136     dsl       817:        if (v != NULL) {
1.131     sjg       818:            if ((v->flags & VAR_FROM_CMD)) {
                    819:                if (DEBUG(VAR)) {
                    820:                    fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val);
                    821:                }
                    822:                goto out;
                    823:            }
                    824:            VarFreeEnv(v, TRUE);
1.129     sjg       825:        }
                    826:     }
1.92      christos  827:     v = VarFind(name, ctxt, 0);
1.136     dsl       828:     if (v == NULL) {
1.183     sjg       829:        if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
                    830:            /*
                    831:             * This var would normally prevent the same name being added
                    832:             * to VAR_GLOBAL, so delete it from there if needed.
                    833:             * Otherwise -V name may show the wrong value.
                    834:             */
                    835:            Var_Delete(name, VAR_GLOBAL);
                    836:        }
1.92      christos  837:        VarAdd(name, val, ctxt);
1.1       cgd       838:     } else {
1.146     dsl       839:        Buf_Empty(&v->val);
1.218     sjg       840:        if (val)
                    841:            Buf_AddBytes(&v->val, strlen(val), val);
1.1       cgd       842:
                    843:        if (DEBUG(VAR)) {
1.114     dsl       844:            fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
1.1       cgd       845:        }
1.118     sjg       846:        if ((v->flags & VAR_EXPORTED)) {
1.152     sjg       847:            Var_Export1(name, VAR_EXPORT_PARENT);
1.118     sjg       848:        }
1.1       cgd       849:     }
                    850:     /*
                    851:      * Any variables given on the command line are automatically exported
                    852:      * to the environment (as per POSIX standard)
                    853:      */
1.65      sjg       854:     if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
1.136     dsl       855:        if (v == NULL) {
1.131     sjg       856:            /* we just added it */
                    857:            v = VarFind(name, ctxt, 0);
                    858:        }
1.151     christos  859:        if (v != NULL)
1.150     christos  860:            v->flags |= VAR_FROM_CMD;
1.71      thorpej   861:        /*
                    862:         * If requested, don't export these in the environment
                    863:         * individually.  We still put them in MAKEOVERRIDES so
                    864:         * that the command-line settings continue to override
                    865:         * Makefile settings.
                    866:         */
                    867:        if (varNoExportEnv != TRUE)
1.218     sjg       868:            setenv(name, val ? val : "", 1);
1.62      sjg       869:
1.64      sjg       870:        Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
1.1       cgd       871:     }
1.292     rillig    872:     if (name[0] == '.' && strcmp(name, SAVE_DOLLARS) == 0)
                    873:        save_dollars = s2Boolean(val, save_dollars);
1.205     sjg       874:
1.242     rillig    875: out:
1.196     christos  876:     free(expanded_name);
1.136     dsl       877:     if (v != NULL)
1.107     christos  878:        VarFreeEnv(v, TRUE);
1.1       cgd       879: }
                    880:
                    881: /*-
                    882:  *-----------------------------------------------------------------------
1.230     rillig    883:  * Var_Set --
                    884:  *     Set the variable name to the value val in the given context.
                    885:  *
                    886:  * Input:
                    887:  *     name            name of variable to set
                    888:  *     val             value to give to the variable
                    889:  *     ctxt            context in which to set it
                    890:  *
                    891:  * Side Effects:
                    892:  *     If the variable doesn't yet exist, a new record is created for it.
                    893:  *     Else the old value is freed and the new one stuck in its place
                    894:  *
                    895:  * Notes:
                    896:  *     The variable is searched for only in its context before being
                    897:  *     created in that context. I.e. if the context is VAR_GLOBAL,
                    898:  *     only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
                    899:  *     VAR_CMD->context is searched. This is done to avoid the literally
                    900:  *     thousands of unnecessary strcmp's that used to be done to
                    901:  *     set, say, $(@) or $(<).
                    902:  *     If the context is VAR_GLOBAL though, we check if the variable
                    903:  *     was set in VAR_CMD from the command line and skip it if so.
                    904:  *-----------------------------------------------------------------------
                    905:  */
                    906: void
                    907: Var_Set(const char *name, const char *val, GNode *ctxt)
                    908: {
1.242     rillig    909:     Var_Set_with_flags(name, val, ctxt, 0);
1.230     rillig    910: }
                    911:
                    912: /*-
                    913:  *-----------------------------------------------------------------------
1.1       cgd       914:  * Var_Append --
                    915:  *     The variable of the given name has the given value appended to it in
                    916:  *     the given context.
                    917:  *
1.70      wiz       918:  * Input:
                    919:  *     name            name of variable to modify
                    920:  *     val             String to append to it
                    921:  *     ctxt            Context in which this should occur
                    922:  *
1.1       cgd       923:  * Side Effects:
                    924:  *     If the variable doesn't exist, it is created. Else the strings
                    925:  *     are concatenated (with a space in between).
                    926:  *
                    927:  * Notes:
                    928:  *     Only if the variable is being sought in the global context is the
                    929:  *     environment searched.
                    930:  *     XXX: Knows its calling circumstances in that if called with ctxt
                    931:  *     an actual target, it will only search that context since only
                    932:  *     a local variable could be being appended to. This is actually
                    933:  *     a big win and must be tolerated.
                    934:  *-----------------------------------------------------------------------
                    935:  */
                    936: void
1.73      christos  937: Var_Append(const char *name, const char *val, GNode *ctxt)
1.1       cgd       938: {
1.249     rillig    939:     Var *v;
                    940:     Hash_Entry *h;
1.139     dsl       941:     char *expanded_name = NULL;
1.1       cgd       942:
1.139     dsl       943:     if (strchr(name, '$') != NULL) {
1.259     rillig    944:        expanded_name = Var_Subst(NULL, name, ctxt, VARE_WANTRES);
1.257     rillig    945:        if (expanded_name[0] == '\0') {
1.139     dsl       946:            if (DEBUG(VAR)) {
                    947:                fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
                    948:                        "name expands to empty string - ignored\n",
                    949:                        name, val);
                    950:            }
                    951:            free(expanded_name);
                    952:            return;
                    953:        }
                    954:        name = expanded_name;
                    955:     }
1.142     dsl       956:
1.260     rillig    957:     v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD | FIND_ENV) : 0);
1.1       cgd       958:
1.136     dsl       959:     if (v == NULL) {
1.230     rillig    960:        Var_Set(name, val, ctxt);
1.217     sjg       961:     } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) {
1.146     dsl       962:        Buf_AddByte(&v->val, ' ');
                    963:        Buf_AddBytes(&v->val, strlen(val), val);
1.1       cgd       964:
                    965:        if (DEBUG(VAR)) {
1.114     dsl       966:            fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name,
1.242     rillig    967:                    Buf_GetAll(&v->val, NULL));
1.1       cgd       968:        }
                    969:
                    970:        if (v->flags & VAR_FROM_ENV) {
                    971:            /*
                    972:             * If the original variable came from the environment, we
                    973:             * have to install it in the global context (we could place
                    974:             * it in the environment, but then we should provide a way to
                    975:             * export other variables...)
                    976:             */
                    977:            v->flags &= ~VAR_FROM_ENV;
1.92      christos  978:            h = Hash_CreateEntry(&ctxt->context, name, NULL);
1.36      mycroft   979:            Hash_SetValue(h, v);
1.1       cgd       980:        }
                    981:     }
1.196     christos  982:     free(expanded_name);
1.1       cgd       983: }
                    984:
                    985: /*-
                    986:  *-----------------------------------------------------------------------
                    987:  * Var_Exists --
                    988:  *     See if the given variable exists.
                    989:  *
1.70      wiz       990:  * Input:
                    991:  *     name            Variable to find
                    992:  *     ctxt            Context in which to start search
                    993:  *
1.1       cgd       994:  * Results:
                    995:  *     TRUE if it does, FALSE if it doesn't
                    996:  *
                    997:  * Side Effects:
                    998:  *     None.
                    999:  *
                   1000:  *-----------------------------------------------------------------------
                   1001:  */
                   1002: Boolean
1.73      christos 1003: Var_Exists(const char *name, GNode *ctxt)
1.1       cgd      1004: {
1.138     dsl      1005:     Var                  *v;
1.128     sjg      1006:     char          *cp;
1.1       cgd      1007:
1.257     rillig   1008:     if ((cp = strchr(name, '$')) != NULL)
1.259     rillig   1009:        cp = Var_Subst(NULL, name, ctxt, VARE_WANTRES);
1.260     rillig   1010:     v = VarFind(cp ? cp : name, ctxt, FIND_CMD | FIND_GLOBAL | FIND_ENV);
1.196     christos 1011:     free(cp);
1.257     rillig   1012:     if (v == NULL)
1.231     rillig   1013:        return FALSE;
                   1014:
                   1015:     (void)VarFreeEnv(v, TRUE);
                   1016:     return TRUE;
1.1       cgd      1017: }
                   1018:
                   1019: /*-
                   1020:  *-----------------------------------------------------------------------
                   1021:  * Var_Value --
                   1022:  *     Return the value of the named variable in the given context
                   1023:  *
1.70      wiz      1024:  * Input:
                   1025:  *     name            name to find
                   1026:  *     ctxt            context in which to search for it
                   1027:  *
1.1       cgd      1028:  * Results:
                   1029:  *     The value if the variable exists, NULL if it doesn't
                   1030:  *
                   1031:  * Side Effects:
                   1032:  *     None
                   1033:  *-----------------------------------------------------------------------
                   1034:  */
                   1035: char *
1.73      christos 1036: Var_Value(const char *name, GNode *ctxt, char **frp)
1.1       cgd      1037: {
1.257     rillig   1038:     Var *v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1.6       jtc      1039:     *frp = NULL;
1.231     rillig   1040:     if (v == NULL)
1.136     dsl      1041:        return NULL;
1.231     rillig   1042:
1.257     rillig   1043:     char *p = Buf_GetAll(&v->val, NULL);
1.231     rillig   1044:     if (VarFreeEnv(v, FALSE))
                   1045:        *frp = p;
                   1046:     return p;
1.1       cgd      1047: }
                   1048:
1.244     rillig   1049:
1.278     rillig   1050: /* SepBuf is a string being built from "words", interleaved with separators. */
                   1051: typedef struct {
                   1052:     Buffer buf;
                   1053:     Boolean needSep;
                   1054:     char sep;
                   1055: } SepBuf;
                   1056:
                   1057: static void
                   1058: SepBuf_Init(SepBuf *buf, char sep)
                   1059: {
                   1060:     Buf_Init(&buf->buf, 32 /* bytes */);
                   1061:     buf->needSep = FALSE;
                   1062:     buf->sep = sep;
                   1063: }
                   1064:
                   1065: static void
                   1066: SepBuf_Sep(SepBuf *buf)
                   1067: {
                   1068:     buf->needSep = TRUE;
                   1069: }
                   1070:
                   1071: static void
                   1072: SepBuf_AddBytes(SepBuf *buf, const void *mem, size_t mem_size)
                   1073: {
                   1074:     if (mem_size == 0)
                   1075:        return;
                   1076:     if (buf->needSep && buf->sep != '\0') {
                   1077:        Buf_AddByte(&buf->buf, buf->sep);
                   1078:        buf->needSep = FALSE;
                   1079:     }
                   1080:     Buf_AddBytes(&buf->buf, mem_size, mem);
                   1081: }
                   1082:
                   1083: static char *
                   1084: SepBuf_Destroy(SepBuf *buf, Boolean free_buf)
                   1085: {
                   1086:     return Buf_Destroy(&buf->buf, free_buf);
                   1087: }
                   1088:
                   1089:
1.291     rillig   1090: /* This callback for ModifyWords gets a single word from an expression and
1.244     rillig   1091:  * typically adds a modification of this word to the buffer. It may also do
1.278     rillig   1092:  * nothing or add several words. */
1.295     rillig   1093: typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data);
1.244     rillig   1094:
                   1095:
1.291     rillig   1096: /* Callback for ModifyWords to implement the :H modifier.
1.244     rillig   1097:  * Add the dirname of the given word to the buffer. */
1.278     rillig   1098: static void
1.295     rillig   1099: ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1100: {
1.238     rillig   1101:     const char *slash = strrchr(word, '/');
                   1102:     if (slash != NULL)
1.278     rillig   1103:        SepBuf_AddBytes(buf, word, slash - word);
1.238     rillig   1104:     else
1.278     rillig   1105:        SepBuf_AddBytes(buf, ".", 1);
1.1       cgd      1106: }
                   1107:
1.291     rillig   1108: /* Callback for ModifyWords to implement the :T modifier.
1.244     rillig   1109:  * Add the basename of the given word to the buffer. */
1.278     rillig   1110: static void
1.295     rillig   1111: ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1112: {
1.238     rillig   1113:     const char *slash = strrchr(word, '/');
                   1114:     const char *base = slash != NULL ? slash + 1 : word;
1.278     rillig   1115:     SepBuf_AddBytes(buf, base, strlen(base));
1.1       cgd      1116: }
                   1117:
1.291     rillig   1118: /* Callback for ModifyWords to implement the :E modifier.
1.244     rillig   1119:  * Add the filename suffix of the given word to the buffer, if it exists. */
1.278     rillig   1120: static void
1.295     rillig   1121: ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1122: {
1.239     rillig   1123:     const char *dot = strrchr(word, '.');
1.278     rillig   1124:     if (dot != NULL)
                   1125:        SepBuf_AddBytes(buf, dot + 1, strlen(dot + 1));
1.1       cgd      1126: }
                   1127:
1.291     rillig   1128: /* Callback for ModifyWords to implement the :R modifier.
                   1129:  * Add the basename of the given word to the buffer. */
1.278     rillig   1130: static void
1.295     rillig   1131: ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd      1132: {
1.239     rillig   1133:     char *dot = strrchr(word, '.');
1.247     lukem    1134:     size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1.278     rillig   1135:     SepBuf_AddBytes(buf, word, len);
1.1       cgd      1136: }
                   1137:
1.291     rillig   1138: /* Callback for ModifyWords to implement the :M modifier.
1.244     rillig   1139:  * Place the word in the buffer if it matches the given pattern. */
1.278     rillig   1140: static void
1.295     rillig   1141: ModifyWord_Match(const char *word, SepBuf *buf, void *data)
1.1       cgd      1142: {
1.244     rillig   1143:     const char *pattern = data;
1.137     christos 1144:     if (DEBUG(VAR))
1.244     rillig   1145:        fprintf(debug_file, "VarMatch [%s] [%s]\n", word, pattern);
1.278     rillig   1146:     if (Str_Match(word, pattern))
                   1147:        SepBuf_AddBytes(buf, word, strlen(word));
1.1       cgd      1148: }
                   1149:
1.291     rillig   1150: /* Callback for ModifyWords to implement the :N modifier.
                   1151:  * Place the word in the buffer if it doesn't match the given pattern. */
                   1152: static void
1.295     rillig   1153: ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
1.291     rillig   1154: {
                   1155:     const char *pattern = data;
                   1156:     if (!Str_Match(word, pattern))
                   1157:        SepBuf_AddBytes(buf, word, strlen(word));
                   1158: }
                   1159:
1.13      christos 1160: #ifdef SYSVVARSUB
1.256     rillig   1161: /*-
                   1162:  *-----------------------------------------------------------------------
                   1163:  * Str_SYSVMatch --
                   1164:  *     Check word against pattern for a match (% is wild),
                   1165:  *
                   1166:  * Input:
                   1167:  *     word            Word to examine
                   1168:  *     pattern         Pattern to examine against
                   1169:  *     len             Number of characters to substitute
                   1170:  *
                   1171:  * Results:
                   1172:  *     Returns the beginning position of a match or null. The number
                   1173:  *     of characters matched is returned in len.
                   1174:  *-----------------------------------------------------------------------
                   1175:  */
1.277     rillig   1176: static const char *
1.256     rillig   1177: Str_SYSVMatch(const char *word, const char *pattern, size_t *len,
                   1178:     Boolean *hasPercent)
                   1179: {
                   1180:     const char *p = pattern;
                   1181:     const char *w = word;
                   1182:     const char *m;
                   1183:
                   1184:     *hasPercent = FALSE;
                   1185:     if (*p == '\0') {
                   1186:        /* Null pattern is the whole string */
                   1187:        *len = strlen(w);
1.277     rillig   1188:        return w;
1.256     rillig   1189:     }
                   1190:
                   1191:     if ((m = strchr(p, '%')) != NULL) {
                   1192:        *hasPercent = TRUE;
                   1193:        if (*w == '\0') {
                   1194:                /* empty word does not match pattern */
                   1195:                return NULL;
                   1196:        }
                   1197:        /* check that the prefix matches */
                   1198:        for (; p != m && *w && *w == *p; w++, p++)
                   1199:             continue;
                   1200:
                   1201:        if (p != m)
                   1202:            return NULL;        /* No match */
                   1203:
                   1204:        if (*++p == '\0') {
                   1205:            /* No more pattern, return the rest of the string */
                   1206:            *len = strlen(w);
1.277     rillig   1207:            return w;
1.256     rillig   1208:        }
                   1209:     }
                   1210:
                   1211:     m = w;
                   1212:
                   1213:     /* Find a matching tail */
1.277     rillig   1214:     do {
1.256     rillig   1215:        if (strcmp(p, w) == 0) {
                   1216:            *len = w - m;
1.277     rillig   1217:            return m;
1.256     rillig   1218:        }
1.277     rillig   1219:     } while (*w++ != '\0');
1.256     rillig   1220:
                   1221:     return NULL;
                   1222: }
                   1223:
                   1224:
                   1225: /*-
                   1226:  *-----------------------------------------------------------------------
                   1227:  * Str_SYSVSubst --
                   1228:  *     Substitute '%' on the pattern with len characters from src.
                   1229:  *     If the pattern does not contain a '%' prepend len characters
                   1230:  *     from src.
                   1231:  *
                   1232:  * Side Effects:
                   1233:  *     Places result on buf
                   1234:  *-----------------------------------------------------------------------
                   1235:  */
                   1236: static void
1.278     rillig   1237: Str_SYSVSubst(SepBuf *buf, const char *pat, const char *src, size_t len,
                   1238:              Boolean lhsHasPercent)
1.256     rillig   1239: {
                   1240:     const char *m;
                   1241:
                   1242:     if ((m = strchr(pat, '%')) != NULL && lhsHasPercent) {
                   1243:        /* Copy the prefix */
1.278     rillig   1244:        SepBuf_AddBytes(buf, pat, m - pat);
1.256     rillig   1245:        /* skip the % */
                   1246:        pat = m + 1;
                   1247:     }
                   1248:     if (m != NULL || !lhsHasPercent) {
                   1249:        /* Copy the pattern */
1.278     rillig   1250:        SepBuf_AddBytes(buf, src, len);
1.256     rillig   1251:     }
                   1252:
                   1253:     /* append the rest */
1.278     rillig   1254:     SepBuf_AddBytes(buf, pat, strlen(pat));
1.256     rillig   1255: }
                   1256:
                   1257:
1.276     rillig   1258: typedef struct {
1.295     rillig   1259:     GNode *ctx;
1.276     rillig   1260:     const char *lhs;
                   1261:     const char *rhs;
1.291     rillig   1262: } ModifyWord_SYSVSubstArgs;
1.276     rillig   1263:
1.291     rillig   1264: /* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1.278     rillig   1265: static void
1.295     rillig   1266: ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
1.5       cgd      1267: {
1.291     rillig   1268:     const ModifyWord_SYSVSubstArgs *args = data;
1.5       cgd      1269:
1.276     rillig   1270:     size_t len;
                   1271:     Boolean hasPercent;
                   1272:     const char *ptr = Str_SYSVMatch(word, args->lhs, &len, &hasPercent);
                   1273:     if (ptr != NULL) {
1.295     rillig   1274:        char *varexp = Var_Subst(NULL, args->rhs, args->ctx, VARE_WANTRES);
1.223     christos 1275:        Str_SYSVSubst(buf, varexp, ptr, len, hasPercent);
1.61      explorer 1276:        free(varexp);
                   1277:     } else {
1.278     rillig   1278:        SepBuf_AddBytes(buf, word, strlen(word));
1.61      explorer 1279:     }
1.5       cgd      1280: }
1.13      christos 1281: #endif
1.5       cgd      1282:
1.1       cgd      1283:
1.291     rillig   1284: typedef struct {
                   1285:     const char *lhs;
                   1286:     size_t     lhsLen;
                   1287:     const char *rhs;
                   1288:     size_t     rhsLen;
                   1289:     VarPatternFlags pflags;
                   1290: } ModifyWord_SubstArgs;
                   1291:
                   1292: /* Callback for ModifyWords to implement the :S,from,to, modifier.
1.244     rillig   1293:  * Perform a string substitution on the given word. */
1.278     rillig   1294: static void
1.295     rillig   1295: ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
1.1       cgd      1296: {
1.279     rillig   1297:     size_t wordLen = strlen(word);
1.291     rillig   1298:     ModifyWord_SubstArgs *args = data;
1.281     rillig   1299:     const VarPatternFlags pflags = args->pflags;
1.1       cgd      1300:
1.279     rillig   1301:     if ((pflags & (VARP_SUB_ONE | VARP_SUB_MATCHED)) ==
                   1302:        (VARP_SUB_ONE | VARP_SUB_MATCHED))
                   1303:        goto nosub;
                   1304:
1.288     rillig   1305:     if (args->pflags & VARP_ANCHOR_START) {
1.282     rillig   1306:        if (wordLen < args->lhsLen ||
                   1307:            memcmp(word, args->lhs, args->lhsLen) != 0)
1.1       cgd      1308:            goto nosub;
1.279     rillig   1309:
1.288     rillig   1310:        if (args->pflags & VARP_ANCHOR_END) {
1.281     rillig   1311:            if (wordLen != args->lhsLen)
1.1       cgd      1312:                goto nosub;
1.279     rillig   1313:
1.281     rillig   1314:            SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
                   1315:            args->pflags |= VARP_SUB_MATCHED;
1.1       cgd      1316:        } else {
1.281     rillig   1317:            SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
                   1318:            SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen);
                   1319:            args->pflags |= VARP_SUB_MATCHED;
1.1       cgd      1320:        }
1.278     rillig   1321:        return;
1.1       cgd      1322:     }
1.279     rillig   1323:
1.288     rillig   1324:     if (args->pflags & VARP_ANCHOR_END) {
1.281     rillig   1325:        if (wordLen < args->lhsLen)
1.280     rillig   1326:            goto nosub;
1.281     rillig   1327:        const char *start = word + (wordLen - args->lhsLen);
                   1328:        if (memcmp(start, args->lhs, args->lhsLen) != 0)
1.279     rillig   1329:            goto nosub;
                   1330:
1.280     rillig   1331:        SepBuf_AddBytes(buf, word, start - word);
1.281     rillig   1332:        SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
                   1333:        args->pflags |= VARP_SUB_MATCHED;
1.279     rillig   1334:        return;
                   1335:     }
                   1336:
                   1337:     /* unanchored */
                   1338:     const char *cp;
1.281     rillig   1339:     while ((cp = Str_FindSubstring(word, args->lhs)) != NULL) {
1.279     rillig   1340:        SepBuf_AddBytes(buf, word, cp - word);
1.281     rillig   1341:        SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
                   1342:        wordLen -= (cp - word) + args->lhsLen;
                   1343:        word = cp + args->lhsLen;
                   1344:        if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL))
1.279     rillig   1345:            break;
1.281     rillig   1346:        args->pflags |= VARP_SUB_MATCHED;
1.279     rillig   1347:     }
1.242     rillig   1348: nosub:
1.278     rillig   1349:     SepBuf_AddBytes(buf, word, wordLen);
1.1       cgd      1350: }
                   1351:
1.31      gwr      1352: #ifndef NO_REGEX
1.16      christos 1353: /*-
                   1354:  *-----------------------------------------------------------------------
                   1355:  * VarREError --
                   1356:  *     Print the error caused by a regcomp or regexec call.
                   1357:  *
                   1358:  * Side Effects:
                   1359:  *     An error gets printed.
                   1360:  *
                   1361:  *-----------------------------------------------------------------------
                   1362:  */
                   1363: static void
1.202     christos 1364: VarREError(int reerr, regex_t *pat, const char *str)
1.16      christos 1365: {
                   1366:     char *errbuf;
1.127     christos 1367:     int errlen;
1.16      christos 1368:
1.202     christos 1369:     errlen = regerror(reerr, pat, 0, 0);
1.134     joerg    1370:     errbuf = bmake_malloc(errlen);
1.202     christos 1371:     regerror(reerr, pat, errbuf, errlen);
1.16      christos 1372:     Error("%s: %s", str, errbuf);
                   1373:     free(errbuf);
                   1374: }
                   1375:
1.291     rillig   1376: typedef struct {
                   1377:     regex_t       re;
                   1378:     int                   nsub;
                   1379:     char         *replace;
                   1380:     VarPatternFlags pflags;
                   1381: } ModifyWord_SubstRegexArgs;
                   1382:
                   1383: /* Callback for ModifyWords to implement the :C/from/to/ modifier.
1.244     rillig   1384:  * Perform a regex substitution on the given word. */
1.278     rillig   1385: static void
1.295     rillig   1386: ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data)
1.16      christos 1387: {
1.304     rillig   1388:     ModifyWord_SubstRegexArgs *args = data;
1.16      christos 1389:     int xrv;
1.253     rillig   1390:     const char *wp = word;
1.16      christos 1391:     char *rp;
1.20      christos 1392:     int flags = 0;
1.305     rillig   1393:     regmatch_t m[10];
1.16      christos 1394:
1.306   ! rillig   1395:     if ((args->pflags & VARP_SUB_ONE) && (args->pflags & VARP_SUB_MATCHED))
1.16      christos 1396:        xrv = REG_NOMATCH;
                   1397:     else {
                   1398:     tryagain:
1.305     rillig   1399:        xrv = regexec(&args->re, wp, args->nsub, m, flags);
1.16      christos 1400:     }
                   1401:
                   1402:     switch (xrv) {
                   1403:     case 0:
1.304     rillig   1404:        args->pflags |= VARP_SUB_MATCHED;
1.305     rillig   1405:        SepBuf_AddBytes(buf, wp, m[0].rm_so);
1.16      christos 1406:
1.304     rillig   1407:        for (rp = args->replace; *rp; rp++) {
1.278     rillig   1408:            if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) {
                   1409:                SepBuf_AddBytes(buf, rp + 1, 1);
1.16      christos 1410:                rp++;
1.278     rillig   1411:            } else if (*rp == '&' ||
                   1412:                (*rp == '\\' && isdigit((unsigned char)rp[1]))) {
1.16      christos 1413:                int n;
                   1414:                char errstr[3];
                   1415:
                   1416:                if (*rp == '&') {
                   1417:                    n = 0;
                   1418:                    errstr[0] = '&';
                   1419:                    errstr[1] = '\0';
                   1420:                } else {
                   1421:                    n = rp[1] - '0';
                   1422:                    errstr[0] = '\\';
                   1423:                    errstr[1] = rp[1];
                   1424:                    errstr[2] = '\0';
                   1425:                    rp++;
                   1426:                }
                   1427:
1.304     rillig   1428:                if (n >= args->nsub) {
1.294     rillig   1429:                    Error("No subexpression %s", errstr);
1.305     rillig   1430:                } else if (m[n].rm_so == -1 && m[n].rm_eo == -1) {
1.294     rillig   1431:                    Error("No match for subexpression %s", errstr);
1.242     rillig   1432:                } else {
1.305     rillig   1433:                    SepBuf_AddBytes(buf, wp + m[n].rm_so,
                   1434:                                    m[n].rm_eo - m[n].rm_so);
1.16      christos 1435:                }
                   1436:
                   1437:            } else {
1.278     rillig   1438:                SepBuf_AddBytes(buf, rp, 1);
1.16      christos 1439:            }
                   1440:        }
1.305     rillig   1441:        wp += m[0].rm_eo;
1.304     rillig   1442:        if (args->pflags & VARP_SUB_GLOBAL) {
1.20      christos 1443:            flags |= REG_NOTBOL;
1.305     rillig   1444:            if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1.278     rillig   1445:                SepBuf_AddBytes(buf, wp, 1);
1.20      christos 1446:                wp++;
                   1447:            }
                   1448:            if (*wp)
                   1449:                goto tryagain;
                   1450:        }
1.16      christos 1451:        if (*wp) {
1.278     rillig   1452:            SepBuf_AddBytes(buf, wp, strlen(wp));
1.16      christos 1453:        }
                   1454:        break;
                   1455:     default:
1.304     rillig   1456:        VarREError(xrv, &args->re, "Unexpected regex error");
1.242     rillig   1457:        /* fall through */
1.16      christos 1458:     case REG_NOMATCH:
1.278     rillig   1459:        SepBuf_AddBytes(buf, wp, strlen(wp));
1.16      christos 1460:        break;
                   1461:     }
                   1462: }
1.17      christos 1463: #endif
1.16      christos 1464:
                   1465:
1.291     rillig   1466: typedef struct {
1.295     rillig   1467:     GNode      *ctx;
1.291     rillig   1468:     char       *tvar;          /* name of temporary variable */
                   1469:     char       *str;           /* string to expand */
                   1470:     VarEvalFlags eflags;
                   1471: } ModifyWord_LoopArgs;
                   1472:
                   1473: /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */
1.278     rillig   1474: static void
1.295     rillig   1475: ModifyWord_Loop(const char *word, SepBuf *buf, void *data)
1.40      sjg      1476: {
1.278     rillig   1477:     if (word[0] == '\0')
                   1478:        return;
                   1479:
1.295     rillig   1480:     const ModifyWord_LoopArgs *args = data;
                   1481:     Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT);
                   1482:     char *s = Var_Subst(NULL, args->str, args->ctx, args->eflags);
1.278     rillig   1483:     if (DEBUG(VAR)) {
                   1484:        fprintf(debug_file,
1.291     rillig   1485:                "ModifyWord_Loop: in \"%s\", replace \"%s\" with \"%s\" "
1.278     rillig   1486:                "to \"%s\"\n",
1.295     rillig   1487:                word, args->tvar, args->str, s ? s : "(null)");
1.278     rillig   1488:     }
1.64      sjg      1489:
1.278     rillig   1490:     if (s != NULL && s[0] != '\0') {
                   1491:        if (s[0] == '\n' || (buf->buf.count > 0 &&
                   1492:            buf->buf.buffer[buf->buf.count - 1] == '\n'))
                   1493:            buf->needSep = FALSE;
                   1494:        SepBuf_AddBytes(buf, s, strlen(s));
1.40      sjg      1495:     }
1.278     rillig   1496:     free(s);
1.40      sjg      1497: }
                   1498:
1.81      sjg      1499:
                   1500: /*-
1.291     rillig   1501:  * Implements the :[first..last] modifier.
1.292     rillig   1502:  * This is a special case of ModifyWords since we want to be able
1.291     rillig   1503:  * to scan the list backwards if first > last.
1.81      sjg      1504:  */
                   1505: static char *
1.301     rillig   1506: VarSelectWords(Byte sep, Boolean oneBigWord, const char *str, int first,
                   1507:               int last)
1.81      sjg      1508: {
1.278     rillig   1509:     SepBuf buf;
1.240     rillig   1510:     char **av;                 /* word list */
                   1511:     char *as;                  /* word list memory */
1.127     christos 1512:     int ac, i;
1.81      sjg      1513:     int start, end, step;
1.142     dsl      1514:
1.301     rillig   1515:     SepBuf_Init(&buf, sep);
1.81      sjg      1516:
1.301     rillig   1517:     if (oneBigWord) {
1.81      sjg      1518:        /* fake what brk_string() would do if there were only one word */
                   1519:        ac = 1;
1.242     rillig   1520:        av = bmake_malloc((ac + 1) * sizeof(char *));
1.134     joerg    1521:        as = bmake_strdup(str);
1.81      sjg      1522:        av[0] = as;
                   1523:        av[1] = NULL;
                   1524:     } else {
                   1525:        av = brk_string(str, &ac, FALSE, &as);
                   1526:     }
                   1527:
                   1528:     /*
                   1529:      * Now sanitize seldata.
                   1530:      * If seldata->start or seldata->end are negative, convert them to
                   1531:      * the positive equivalents (-1 gets converted to argc, -2 gets
                   1532:      * converted to (argc-1), etc.).
                   1533:      */
1.290     rillig   1534:     if (first < 0)
                   1535:        first += ac + 1;
                   1536:     if (last < 0)
                   1537:        last += ac + 1;
1.81      sjg      1538:
                   1539:     /*
                   1540:      * We avoid scanning more of the list than we need to.
                   1541:      */
1.290     rillig   1542:     if (first > last) {
                   1543:        start = MIN(ac, first) - 1;
                   1544:        end = MAX(0, last - 1);
1.81      sjg      1545:        step = -1;
                   1546:     } else {
1.290     rillig   1547:        start = MAX(0, first - 1);
                   1548:        end = MIN(ac, last);
1.81      sjg      1549:        step = 1;
                   1550:     }
                   1551:
1.296     rillig   1552:     for (i = start; (step < 0) == (i >= end); i += step) {
1.278     rillig   1553:        if (av[i][0] != '\0') {
                   1554:            SepBuf_AddBytes(&buf, av[i], strlen(av[i]));
                   1555:            SepBuf_Sep(&buf);
1.81      sjg      1556:        }
                   1557:     }
                   1558:
                   1559:     free(as);
                   1560:     free(av);
                   1561:
1.278     rillig   1562:     return SepBuf_Destroy(&buf, FALSE);
1.81      sjg      1563: }
                   1564:
1.156     sjg      1565:
1.291     rillig   1566: /* Callback for ModifyWords to implement the :tA modifier.
1.244     rillig   1567:  * Replace each word with the result of realpath() if successful. */
1.278     rillig   1568: static void
1.295     rillig   1569: ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.156     sjg      1570: {
1.242     rillig   1571:     struct stat st;
                   1572:     char rbuf[MAXPATHLEN];
1.231     rillig   1573:
1.278     rillig   1574:     char *rp = cached_realpath(word, rbuf);
1.257     rillig   1575:     if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1.242     rillig   1576:        word = rp;
1.231     rillig   1577:
1.278     rillig   1578:     SepBuf_AddBytes(buf, word, strlen(word));
1.156     sjg      1579: }
                   1580:
1.1       cgd      1581: /*-
                   1582:  *-----------------------------------------------------------------------
1.244     rillig   1583:  * Modify each of the words of the passed string using the given function.
1.1       cgd      1584:  *
1.70      wiz      1585:  * Input:
1.278     rillig   1586:  *     str             String whose words should be modified
1.291     rillig   1587:  *     modifyWord      Function that modifies a single word
                   1588:  *     data            Custom data for modifyWord
1.70      wiz      1589:  *
1.1       cgd      1590:  * Results:
                   1591:  *     A string of all the words modified appropriately.
                   1592:  *-----------------------------------------------------------------------
                   1593:  */
                   1594: static char *
1.301     rillig   1595: ModifyWords(GNode *ctx, Byte sep, Boolean oneBigWord,
1.291     rillig   1596:            const char *str, ModifyWordsCallback modifyWord, void *data)
1.1       cgd      1597: {
1.278     rillig   1598:     SepBuf result;
1.240     rillig   1599:     char **av;                 /* word list */
                   1600:     char *as;                  /* word list memory */
1.127     christos 1601:     int ac, i;
1.7       jtc      1602:
1.301     rillig   1603:     SepBuf_Init(&result, sep);
1.1       cgd      1604:
1.301     rillig   1605:     if (oneBigWord) {
1.81      sjg      1606:        /* fake what brk_string() would do if there were only one word */
                   1607:        ac = 1;
1.242     rillig   1608:        av = bmake_malloc((ac + 1) * sizeof(char *));
1.134     joerg    1609:        as = bmake_strdup(str);
1.81      sjg      1610:        av[0] = as;
                   1611:        av[1] = NULL;
                   1612:     } else {
                   1613:        av = brk_string(str, &ac, FALSE, &as);
                   1614:     }
1.1       cgd      1615:
1.255     rillig   1616:     if (DEBUG(VAR)) {
1.292     rillig   1617:        fprintf(debug_file, "ModifyWords: split \"%s\" into %d words\n",
1.255     rillig   1618:                str, ac);
                   1619:     }
                   1620:
1.278     rillig   1621:     for (i = 0; i < ac; i++) {
                   1622:        size_t orig_count = result.buf.count;
1.295     rillig   1623:        modifyWord(av[i], &result, data);
1.278     rillig   1624:        size_t count = result.buf.count;
                   1625:        if (count != orig_count)
                   1626:            SepBuf_Sep(&result);
                   1627:     }
1.24      christos 1628:
                   1629:     free(as);
                   1630:     free(av);
1.15      christos 1631:
1.278     rillig   1632:     return SepBuf_Destroy(&result, FALSE);
1.1       cgd      1633: }
                   1634:
1.35      christos 1635:
                   1636: static int
1.70      wiz      1637: VarWordCompare(const void *a, const void *b)
1.35      christos 1638: {
1.242     rillig   1639:     int r = strcmp(*(const char * const *)a, *(const char * const *)b);
                   1640:     return r;
1.35      christos 1641: }
                   1642:
1.224     sjg      1643: static int
                   1644: VarWordCompareReverse(const void *a, const void *b)
                   1645: {
1.242     rillig   1646:     int r = strcmp(*(const char * const *)b, *(const char * const *)a);
                   1647:     return r;
1.224     sjg      1648: }
                   1649:
1.35      christos 1650: /*-
                   1651:  *-----------------------------------------------------------------------
1.93      sjg      1652:  * VarOrder --
                   1653:  *     Order the words in the string.
1.35      christos 1654:  *
1.70      wiz      1655:  * Input:
1.93      sjg      1656:  *     str             String whose words should be sorted.
                   1657:  *     otype           How to order: s - sort, x - random.
1.70      wiz      1658:  *
1.35      christos 1659:  * Results:
1.93      sjg      1660:  *     A string containing the words ordered.
1.35      christos 1661:  *
                   1662:  * Side Effects:
                   1663:  *     None.
                   1664:  *
                   1665:  *-----------------------------------------------------------------------
                   1666:  */
                   1667: static char *
1.93      sjg      1668: VarOrder(const char *str, const char otype)
1.35      christos 1669: {
1.240     rillig   1670:     Buffer buf;                        /* Buffer for the new string */
                   1671:     char **av;                 /* word list [first word does not count] */
                   1672:     char *as;                  /* word list memory */
1.127     christos 1673:     int ac, i;
1.35      christos 1674:
1.146     dsl      1675:     Buf_Init(&buf, 0);
1.35      christos 1676:
                   1677:     av = brk_string(str, &ac, FALSE, &as);
                   1678:
1.240     rillig   1679:     if (ac > 0) {
1.93      sjg      1680:        switch (otype) {
1.240     rillig   1681:        case 'r':               /* reverse sort alphabetically */
1.224     sjg      1682:            qsort(av, ac, sizeof(char *), VarWordCompareReverse);
                   1683:            break;
1.240     rillig   1684:        case 's':               /* sort alphabetically */
1.93      sjg      1685:            qsort(av, ac, sizeof(char *), VarWordCompare);
                   1686:            break;
1.240     rillig   1687:        case 'x':               /* randomize */
                   1688:            {
                   1689:                /*
                   1690:                 * We will use [ac..2] range for mod factors. This will produce
                   1691:                 * random numbers in [(ac-1)..0] interval, and minimal
                   1692:                 * reasonable value for mod factor is 2 (the mod 1 will produce
                   1693:                 * 0 with probability 1).
                   1694:                 */
                   1695:                for (i = ac - 1; i > 0; i--) {
                   1696:                    int rndidx = random() % (i + 1);
                   1697:                    char *t = av[i];
1.93      sjg      1698:                    av[i] = av[rndidx];
                   1699:                    av[rndidx] = t;
                   1700:                }
                   1701:            }
                   1702:        }
1.240     rillig   1703:     }
1.35      christos 1704:
                   1705:     for (i = 0; i < ac; i++) {
1.146     dsl      1706:        Buf_AddBytes(&buf, strlen(av[i]), av[i]);
1.35      christos 1707:        if (i != ac - 1)
1.146     dsl      1708:            Buf_AddByte(&buf, ' ');
1.35      christos 1709:     }
                   1710:
                   1711:     free(as);
                   1712:     free(av);
                   1713:
1.146     dsl      1714:     return Buf_Destroy(&buf, FALSE);
1.35      christos 1715: }
                   1716:
                   1717:
1.1       cgd      1718: /*-
                   1719:  *-----------------------------------------------------------------------
1.55      christos 1720:  * VarUniq --
                   1721:  *     Remove adjacent duplicate words.
                   1722:  *
1.70      wiz      1723:  * Input:
                   1724:  *     str             String whose words should be sorted
                   1725:  *
1.55      christos 1726:  * Results:
                   1727:  *     A string containing the resulting words.
                   1728:  *
                   1729:  * Side Effects:
                   1730:  *     None.
                   1731:  *
                   1732:  *-----------------------------------------------------------------------
                   1733:  */
                   1734: static char *
1.73      christos 1735: VarUniq(const char *str)
1.55      christos 1736: {
1.240     rillig   1737:     Buffer       buf;          /* Buffer for new string */
                   1738:     char       **av;           /* List of words to affect */
                   1739:     char        *as;           /* Word list memory */
1.127     christos 1740:     int          ac, i, j;
1.55      christos 1741:
1.146     dsl      1742:     Buf_Init(&buf, 0);
1.55      christos 1743:     av = brk_string(str, &ac, FALSE, &as);
                   1744:
                   1745:     if (ac > 1) {
                   1746:        for (j = 0, i = 1; i < ac; i++)
                   1747:            if (strcmp(av[i], av[j]) != 0 && (++j != i))
                   1748:                av[j] = av[i];
                   1749:        ac = j + 1;
                   1750:     }
                   1751:
                   1752:     for (i = 0; i < ac; i++) {
1.146     dsl      1753:        Buf_AddBytes(&buf, strlen(av[i]), av[i]);
1.55      christos 1754:        if (i != ac - 1)
1.146     dsl      1755:            Buf_AddByte(&buf, ' ');
1.55      christos 1756:     }
                   1757:
                   1758:     free(as);
                   1759:     free(av);
                   1760:
1.146     dsl      1761:     return Buf_Destroy(&buf, FALSE);
1.55      christos 1762: }
                   1763:
1.210     sjg      1764: /*-
                   1765:  *-----------------------------------------------------------------------
                   1766:  * VarRange --
                   1767:  *     Return an integer sequence
                   1768:  *
                   1769:  * Input:
                   1770:  *     str             String whose words provide default range
                   1771:  *     ac              range length, if 0 use str words
                   1772:  *
                   1773:  * Side Effects:
                   1774:  *     None.
                   1775:  *
                   1776:  *-----------------------------------------------------------------------
                   1777:  */
                   1778: static char *
                   1779: VarRange(const char *str, int ac)
                   1780: {
1.240     rillig   1781:     Buffer       buf;          /* Buffer for new string */
                   1782:     char         tmp[32];      /* each element */
                   1783:     char       **av;           /* List of words to affect */
                   1784:     char        *as;           /* Word list memory */
1.210     sjg      1785:     int          i, n;
                   1786:
                   1787:     Buf_Init(&buf, 0);
                   1788:     if (ac > 0) {
                   1789:        as = NULL;
                   1790:        av = NULL;
                   1791:     } else {
                   1792:        av = brk_string(str, &ac, FALSE, &as);
                   1793:     }
                   1794:     for (i = 0; i < ac; i++) {
                   1795:        n = snprintf(tmp, sizeof(tmp), "%d", 1 + i);
                   1796:        if (n >= (int)sizeof(tmp))
                   1797:            break;
                   1798:        Buf_AddBytes(&buf, n, tmp);
                   1799:        if (i != ac - 1)
                   1800:            Buf_AddByte(&buf, ' ');
                   1801:     }
                   1802:
                   1803:     free(as);
                   1804:     free(av);
                   1805:
                   1806:     return Buf_Destroy(&buf, FALSE);
                   1807: }
                   1808:
1.55      christos 1809:
                   1810: /*-
1.265     rillig   1811:  * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/
                   1812:  * or the :@ modifier. Nested variables in the text are expanded unless
1.287     rillig   1813:  * VARE_NOSUBST is set.
1.265     rillig   1814:  *
                   1815:  * The text part is parsed until the next delimiter.  To escape the delimiter,
                   1816:  * a backslash or a dollar, put a backslash before it.
                   1817:  *
                   1818:  * Return the expanded string or NULL if the delimiter was missing.
                   1819:  * If pattern is specified, handle escaped ampersands and replace unescaped
                   1820:  * ampersands with the lhs of the pattern (for the :S and :C modifiers).
                   1821:  *
                   1822:  * If length is specified, return the string length of the buffer.
                   1823:  * If mpflags is specified and the last character of the pattern is a $,
1.288     rillig   1824:  * set the VARP_ANCHOR_END bit of mpflags.
1.16      christos 1825:  */
                   1826: static char *
1.266     rillig   1827: ParseModifierPart(GNode *ctxt, const char **tstr, int delim,
                   1828:                  VarEvalFlags eflags, VarPatternFlags *mpflags,
1.291     rillig   1829:                  size_t *length, ModifyWord_SubstArgs *subst)
1.16      christos 1830: {
1.73      christos 1831:     const char *cp;
1.146     dsl      1832:     char *rstr;
                   1833:     Buffer buf;
1.281     rillig   1834:     size_t junk;
1.261     rillig   1835:     VarEvalFlags errnum = eflags & VARE_UNDEFERR;
1.146     dsl      1836:
                   1837:     Buf_Init(&buf, 0);
1.16      christos 1838:     if (length == NULL)
                   1839:        length = &junk;
                   1840:
                   1841:     /*
                   1842:      * Skim through until the matching delimiter is found;
                   1843:      * pick up variable substitutions on the way. Also allow
                   1844:      * backslashes to quote the delimiter, $, and \, but don't
                   1845:      * touch other backslashes.
                   1846:      */
1.278     rillig   1847:     for (cp = *tstr; *cp != '\0' && *cp != delim; cp++) {
1.263     rillig   1848:        Boolean is_escaped = cp[0] == '\\' && (cp[1] == delim ||
1.281     rillig   1849:            cp[1] == '\\' || cp[1] == '$' || (subst != NULL && cp[1] == '&'));
1.263     rillig   1850:        if (is_escaped) {
1.146     dsl      1851:            Buf_AddByte(&buf, cp[1]);
1.16      christos 1852:            cp++;
                   1853:        } else if (*cp == '$') {
1.288     rillig   1854:            if (cp[1] == delim) {       /* Unescaped $ at end of pattern */
1.261     rillig   1855:                if (mpflags == NULL)
1.146     dsl      1856:                    Buf_AddByte(&buf, *cp);
1.16      christos 1857:                else
1.288     rillig   1858:                    *mpflags |= VARP_ANCHOR_END;
1.40      sjg      1859:            } else {
1.287     rillig   1860:                if (!(eflags & VARE_NOSUBST)) {
1.40      sjg      1861:                    char   *cp2;
1.127     christos 1862:                    int     len;
1.104     christos 1863:                    void   *freeIt;
1.40      sjg      1864:
                   1865:                    /*
                   1866:                     * If unescaped dollar sign not before the
                   1867:                     * delimiter, assume it's a variable
                   1868:                     * substitution and recurse.
                   1869:                     */
1.261     rillig   1870:                    cp2 = Var_Parse(cp, ctxt, errnum | (eflags & VARE_WANTRES),
1.249     rillig   1871:                                    &len, &freeIt);
1.146     dsl      1872:                    Buf_AddBytes(&buf, strlen(cp2), cp2);
1.196     christos 1873:                    free(freeIt);
1.40      sjg      1874:                    cp += len - 1;
                   1875:                } else {
1.73      christos 1876:                    const char *cp2 = &cp[1];
1.16      christos 1877:
1.100     christos 1878:                    if (*cp2 == PROPEN || *cp2 == BROPEN) {
1.40      sjg      1879:                        /*
                   1880:                         * Find the end of this variable reference
                   1881:                         * and suck it in without further ado.
1.232     rillig   1882:                         * It will be interpreted later.
1.40      sjg      1883:                         */
                   1884:                        int have = *cp2;
1.100     christos 1885:                        int want = (*cp2 == PROPEN) ? PRCLOSE : BRCLOSE;
1.40      sjg      1886:                        int depth = 1;
                   1887:
                   1888:                        for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
                   1889:                            if (cp2[-1] != '\\') {
                   1890:                                if (*cp2 == have)
                   1891:                                    ++depth;
                   1892:                                if (*cp2 == want)
                   1893:                                    --depth;
                   1894:                            }
                   1895:                        }
1.146     dsl      1896:                        Buf_AddBytes(&buf, cp2 - cp, cp);
1.40      sjg      1897:                        cp = --cp2;
                   1898:                    } else
1.146     dsl      1899:                        Buf_AddByte(&buf, *cp);
1.40      sjg      1900:                }
1.16      christos 1901:            }
1.281     rillig   1902:        } else if (subst != NULL && *cp == '&')
                   1903:            Buf_AddBytes(&buf, subst->lhsLen, subst->lhs);
1.16      christos 1904:        else
1.146     dsl      1905:            Buf_AddByte(&buf, *cp);
1.16      christos 1906:     }
                   1907:
                   1908:     if (*cp != delim) {
                   1909:        *tstr = cp;
                   1910:        *length = 0;
                   1911:        return NULL;
                   1912:     }
1.146     dsl      1913:
                   1914:     *tstr = ++cp;
                   1915:     *length = Buf_Size(&buf);
                   1916:     rstr = Buf_Destroy(&buf, FALSE);
                   1917:     if (DEBUG(VAR))
1.278     rillig   1918:        fprintf(debug_file, "Modifier part: \"%s\"\n", rstr);
1.146     dsl      1919:     return rstr;
1.16      christos 1920: }
                   1921:
                   1922: /*-
                   1923:  *-----------------------------------------------------------------------
                   1924:  * VarQuote --
1.194     mlelstv  1925:  *     Quote shell meta-characters and space characters in the string
1.220     christos 1926:  *     if quoteDollar is set, also quote and double any '$' characters.
1.16      christos 1927:  *
                   1928:  * Results:
                   1929:  *     The quoted string
                   1930:  *
                   1931:  * Side Effects:
                   1932:  *     None.
                   1933:  *
                   1934:  *-----------------------------------------------------------------------
                   1935:  */
                   1936: static char *
1.220     christos 1937: VarQuote(char *str, Boolean quoteDollar)
1.16      christos 1938: {
1.293     rillig   1939:     Buffer buf;
1.146     dsl      1940:     Buf_Init(&buf, 0);
1.193     christos 1941:
                   1942:     for (; *str != '\0'; str++) {
                   1943:        if (*str == '\n') {
1.293     rillig   1944:            const char *newline = Shell_GetNewline();
                   1945:            if (newline == NULL)
                   1946:                newline = "\\\n";
                   1947:            Buf_AddBytes(&buf, strlen(newline), newline);
1.193     christos 1948:            continue;
                   1949:        }
1.195     christos 1950:        if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
1.146     dsl      1951:            Buf_AddByte(&buf, '\\');
1.193     christos 1952:        Buf_AddByte(&buf, *str);
1.220     christos 1953:        if (quoteDollar && *str == '$')
1.219     christos 1954:            Buf_AddBytes(&buf, 2, "\\$");
1.16      christos 1955:     }
1.193     christos 1956:
1.146     dsl      1957:     str = Buf_Destroy(&buf, FALSE);
1.137     christos 1958:     if (DEBUG(VAR))
                   1959:        fprintf(debug_file, "QuoteMeta: [%s]\n", str);
1.16      christos 1960:     return str;
                   1961: }
                   1962:
1.68      pk       1963: /*-
                   1964:  *-----------------------------------------------------------------------
1.163     joerg    1965:  * VarHash --
                   1966:  *      Hash the string using the MurmurHash3 algorithm.
                   1967:  *      Output is computed using 32bit Little Endian arithmetic.
                   1968:  *
                   1969:  * Input:
                   1970:  *     str             String to modify
                   1971:  *
                   1972:  * Results:
                   1973:  *      Hash value of str, encoded as 8 hex digits.
                   1974:  *
                   1975:  * Side Effects:
                   1976:  *      None.
                   1977:  *
                   1978:  *-----------------------------------------------------------------------
                   1979:  */
                   1980: static char *
1.252     rillig   1981: VarHash(const char *str)
1.163     joerg    1982: {
                   1983:     static const char    hexdigits[16] = "0123456789abcdef";
                   1984:     Buffer         buf;
                   1985:     size_t         len, len2;
1.252     rillig   1986:     const unsigned char *ustr = (const unsigned char *)str;
1.163     joerg    1987:     uint32_t       h, k, c1, c2;
                   1988:
                   1989:     h  = 0x971e137bU;
                   1990:     c1 = 0x95543787U;
                   1991:     c2 = 0x2ad7eb25U;
                   1992:     len2 = strlen(str);
                   1993:
                   1994:     for (len = len2; len; ) {
                   1995:        k = 0;
                   1996:        switch (len) {
                   1997:        default:
1.252     rillig   1998:            k = ((uint32_t)ustr[3] << 24) |
                   1999:                ((uint32_t)ustr[2] << 16) |
                   2000:                ((uint32_t)ustr[1] << 8) |
                   2001:                (uint32_t)ustr[0];
1.163     joerg    2002:            len -= 4;
                   2003:            ustr += 4;
                   2004:            break;
                   2005:        case 3:
1.252     rillig   2006:            k |= (uint32_t)ustr[2] << 16;
1.222     mrg      2007:            /* FALLTHROUGH */
1.163     joerg    2008:        case 2:
1.252     rillig   2009:            k |= (uint32_t)ustr[1] << 8;
1.222     mrg      2010:            /* FALLTHROUGH */
1.163     joerg    2011:        case 1:
1.252     rillig   2012:            k |= (uint32_t)ustr[0];
1.163     joerg    2013:            len = 0;
                   2014:        }
                   2015:        c1 = c1 * 5 + 0x7b7d159cU;
                   2016:        c2 = c2 * 5 + 0x6bce6396U;
                   2017:        k *= c1;
                   2018:        k = (k << 11) ^ (k >> 21);
                   2019:        k *= c2;
                   2020:        h = (h << 13) ^ (h >> 19);
                   2021:        h = h * 5 + 0x52dce729U;
                   2022:        h ^= k;
1.242     rillig   2023:     }
                   2024:     h ^= len2;
                   2025:     h *= 0x85ebca6b;
                   2026:     h ^= h >> 13;
                   2027:     h *= 0xc2b2ae35;
                   2028:     h ^= h >> 16;
                   2029:
                   2030:     Buf_Init(&buf, 0);
                   2031:     for (len = 0; len < 8; ++len) {
                   2032:        Buf_AddByte(&buf, hexdigits[h & 15]);
                   2033:        h >>= 4;
1.249     rillig   2034:     }
1.163     joerg    2035:
1.249     rillig   2036:     return Buf_Destroy(&buf, FALSE);
1.163     joerg    2037: }
                   2038:
1.164     sjg      2039: static char *
1.209     sjg      2040: VarStrftime(const char *fmt, int zulu, time_t utc)
1.164     sjg      2041: {
                   2042:     char buf[BUFSIZ];
                   2043:
1.209     sjg      2044:     if (!utc)
                   2045:        time(&utc);
1.164     sjg      2046:     if (!*fmt)
                   2047:        fmt = "%c";
                   2048:     strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&utc) : localtime(&utc));
1.235     rillig   2049:
1.164     sjg      2050:     buf[sizeof(buf) - 1] = '\0';
                   2051:     return bmake_strdup(buf);
                   2052: }
                   2053:
1.236     rillig   2054: typedef struct {
                   2055:     /* const parameters */
1.267     rillig   2056:     int startc;                        /* '\0' or '{' or '(' */
1.236     rillig   2057:     int endc;
1.242     rillig   2058:     Var *v;
1.236     rillig   2059:     GNode *ctxt;
1.268     rillig   2060:     VarEvalFlags eflags;
1.242     rillig   2061:     int *lengthPtr;
                   2062:     void **freePtr;
1.236     rillig   2063:
                   2064:     /* read-write */
                   2065:     char *nstr;
                   2066:     const char *start;
1.300     rillig   2067:     const char *cp;            /* The position where parsing continues
                   2068:                                 * after the current modifier. */
1.236     rillig   2069:     char termc;                        /* Character which terminated scan */
1.298     rillig   2070:     char missing_delim;                /* For error reporting */
1.236     rillig   2071:     int modifier;              /* that we are processing */
1.301     rillig   2072:
                   2073:     Byte       sep;            /* Word separator in expansions */
                   2074:     Boolean    oneBigWord;     /* TRUE if we will treat the variable as a
                   2075:                                 * single big word, even if it contains
                   2076:                                 * embedded spaces (as opposed to the
                   2077:                                 * usual behaviour of treating it as
                   2078:                                 * several space-separated words). */
1.236     rillig   2079:
                   2080:     /* result */
                   2081:     char *newStr;              /* New value to return */
                   2082: } ApplyModifiersState;
                   2083:
                   2084: /* we now have some modifiers with long names */
                   2085: #define STRMOD_MATCH(s, want, n) \
                   2086:     (strncmp(s, want, n) == 0 && (s[n] == st->endc || s[n] == ':'))
                   2087: #define STRMOD_MATCHX(s, want, n) \
1.246     rillig   2088:     (strncmp(s, want, n) == 0 && \
                   2089:      (s[n] == st->endc || s[n] == ':' || s[n] == '='))
1.236     rillig   2090: #define CHARMOD_MATCH(c) (c == st->endc || c == ':')
                   2091:
                   2092: /* :@var@...${var}...@ */
                   2093: static Boolean
1.299     rillig   2094: ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) {
1.291     rillig   2095:     ModifyWord_LoopArgs args;
1.236     rillig   2096:
1.295     rillig   2097:     args.ctx = st->ctxt;
1.299     rillig   2098:     st->cp = mod + 1;
1.298     rillig   2099:     char delim = '@';
                   2100:     args.tvar = ParseModifierPart(st->ctxt, &st->cp, delim,
1.288     rillig   2101:                                  st->eflags | VARE_NOSUBST,
                   2102:                                  NULL, NULL, NULL);
1.298     rillig   2103:     if (args.tvar == NULL) {
                   2104:        st->missing_delim = delim;
1.236     rillig   2105:        return FALSE;
1.298     rillig   2106:     }
1.236     rillig   2107:
1.298     rillig   2108:     args.str = ParseModifierPart(st->ctxt, &st->cp, delim,
1.288     rillig   2109:                                 st->eflags | VARE_NOSUBST,
                   2110:                                 NULL, NULL, NULL);
1.298     rillig   2111:     if (args.str == NULL) {
                   2112:        st->missing_delim = delim;
1.236     rillig   2113:        return FALSE;
1.298     rillig   2114:     }
1.236     rillig   2115:
                   2116:     st->termc = *st->cp;
                   2117:
1.291     rillig   2118:     args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
1.301     rillig   2119:     int prev_sep = st->sep;
                   2120:     st->sep = ' ';             /* XXX: this is inconsistent */
                   2121:     st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
1.291     rillig   2122:                             ModifyWord_Loop, &args);
1.301     rillig   2123:     st->sep = prev_sep;
1.291     rillig   2124:     Var_Delete(args.tvar, st->ctxt);
                   2125:     free(args.tvar);
                   2126:     free(args.str);
1.236     rillig   2127:     return TRUE;
                   2128: }
                   2129:
                   2130: /* :Ddefined or :Uundefined */
                   2131: static void
1.299     rillig   2132: ApplyModifier_Defined(const char *mod, ApplyModifiersState *st)
1.236     rillig   2133: {
1.242     rillig   2134:     Buffer buf;                        /* Buffer for patterns */
1.268     rillig   2135:     VarEvalFlags neflags;
1.236     rillig   2136:
1.268     rillig   2137:     if (st->eflags & VARE_WANTRES) {
                   2138:        Boolean wantres;
1.299     rillig   2139:        if (*mod == 'U')
1.236     rillig   2140:            wantres = ((st->v->flags & VAR_JUNK) != 0);
                   2141:        else
                   2142:            wantres = ((st->v->flags & VAR_JUNK) == 0);
1.268     rillig   2143:        neflags = st->eflags & ~VARE_WANTRES;
1.236     rillig   2144:        if (wantres)
1.268     rillig   2145:            neflags |= VARE_WANTRES;
1.236     rillig   2146:     } else
1.268     rillig   2147:        neflags = st->eflags;
1.236     rillig   2148:
                   2149:     /*
1.302     rillig   2150:      * Pass through mod looking for 1) escaped delimiters,
1.236     rillig   2151:      * '$'s and backslashes (place the escaped character in
                   2152:      * uninterpreted) and 2) unescaped $'s that aren't before
                   2153:      * the delimiter (expand the variable substitution).
                   2154:      * The result is left in the Buffer buf.
                   2155:      */
                   2156:     Buf_Init(&buf, 0);
1.299     rillig   2157:     for (st->cp = mod + 1;
1.236     rillig   2158:         *st->cp != st->endc && *st->cp != ':' && *st->cp != '\0';
                   2159:         st->cp++) {
                   2160:        if (*st->cp == '\\' &&
                   2161:            (st->cp[1] == ':' || st->cp[1] == '$' || st->cp[1] == st->endc ||
                   2162:             st->cp[1] == '\\')) {
                   2163:            Buf_AddByte(&buf, st->cp[1]);
                   2164:            st->cp++;
                   2165:        } else if (*st->cp == '$') {
                   2166:            /*
                   2167:             * If unescaped dollar sign, assume it's a
                   2168:             * variable substitution and recurse.
                   2169:             */
                   2170:            char    *cp2;
                   2171:            int     len;
                   2172:            void    *freeIt;
                   2173:
1.268     rillig   2174:            cp2 = Var_Parse(st->cp, st->ctxt, neflags, &len, &freeIt);
1.236     rillig   2175:            Buf_AddBytes(&buf, strlen(cp2), cp2);
                   2176:            free(freeIt);
                   2177:            st->cp += len - 1;
                   2178:        } else {
                   2179:            Buf_AddByte(&buf, *st->cp);
                   2180:        }
                   2181:     }
                   2182:
                   2183:     st->termc = *st->cp;
                   2184:
1.257     rillig   2185:     if (st->v->flags & VAR_JUNK)
1.236     rillig   2186:        st->v->flags |= VAR_KEEP;
1.268     rillig   2187:     if (neflags & VARE_WANTRES) {
1.236     rillig   2188:        st->newStr = Buf_Destroy(&buf, FALSE);
                   2189:     } else {
                   2190:        st->newStr = st->nstr;
                   2191:        Buf_Destroy(&buf, TRUE);
                   2192:     }
                   2193: }
                   2194:
                   2195: /* :gmtime */
                   2196: static Boolean
1.299     rillig   2197: ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st)
1.236     rillig   2198: {
                   2199:     time_t utc;
                   2200:     char *ep;
                   2201:
1.299     rillig   2202:     st->cp = mod + 1;          /* make sure it is set */
                   2203:     if (!STRMOD_MATCHX(mod, "gmtime", 6))
1.236     rillig   2204:        return FALSE;
1.299     rillig   2205:     if (mod[6] == '=') {
                   2206:        utc = strtoul(mod + 7, &ep, 10);
1.236     rillig   2207:        st->cp = ep;
                   2208:     } else {
                   2209:        utc = 0;
1.299     rillig   2210:        st->cp = mod + 6;
1.236     rillig   2211:     }
                   2212:     st->newStr = VarStrftime(st->nstr, 1, utc);
                   2213:     st->termc = *st->cp;
                   2214:     return TRUE;
                   2215: }
                   2216:
                   2217: /* :localtime */
                   2218: static Boolean
1.299     rillig   2219: ApplyModifier_Localtime(const char *mod, ApplyModifiersState *st)
1.236     rillig   2220: {
                   2221:     time_t utc;
                   2222:     char *ep;
                   2223:
1.299     rillig   2224:     st->cp = mod + 1;  /* make sure it is set */
                   2225:     if (!STRMOD_MATCHX(mod, "localtime", 9))
1.236     rillig   2226:        return FALSE;
                   2227:
1.299     rillig   2228:     if (mod[9] == '=') {
                   2229:        utc = strtoul(mod + 10, &ep, 10);
1.236     rillig   2230:        st->cp = ep;
                   2231:     } else {
                   2232:        utc = 0;
1.299     rillig   2233:        st->cp = mod + 9;
1.236     rillig   2234:     }
                   2235:     st->newStr = VarStrftime(st->nstr, 0, utc);
                   2236:     st->termc = *st->cp;
                   2237:     return TRUE;
                   2238: }
                   2239:
                   2240: /* :hash */
                   2241: static Boolean
1.299     rillig   2242: ApplyModifier_Hash(const char *mod, ApplyModifiersState *st)
1.236     rillig   2243: {
1.299     rillig   2244:     st->cp = mod + 1;  /* make sure it is set */
                   2245:     if (!STRMOD_MATCH(mod, "hash", 4))
1.236     rillig   2246:        return FALSE;
                   2247:     st->newStr = VarHash(st->nstr);
1.299     rillig   2248:     st->cp = mod + 4;
1.236     rillig   2249:     st->termc = *st->cp;
                   2250:     return TRUE;
                   2251: }
                   2252:
                   2253: /* :P */
                   2254: static void
1.299     rillig   2255: ApplyModifier_Path(const char *mod, ApplyModifiersState *st)
1.236     rillig   2256: {
                   2257:     if ((st->v->flags & VAR_JUNK) != 0)
                   2258:        st->v->flags |= VAR_KEEP;
1.299     rillig   2259:     GNode *gn = Targ_FindNode(st->v->name, TARG_NOCREATE);
1.236     rillig   2260:     if (gn == NULL || gn->type & OP_NOPATH) {
                   2261:        st->newStr = NULL;
                   2262:     } else if (gn->path) {
                   2263:        st->newStr = bmake_strdup(gn->path);
                   2264:     } else {
                   2265:        st->newStr = Dir_FindFile(st->v->name, Suff_FindPath(gn));
                   2266:     }
                   2267:     if (!st->newStr)
                   2268:        st->newStr = bmake_strdup(st->v->name);
1.299     rillig   2269:     st->cp = mod + 1;
                   2270:     st->termc = *st->cp;
1.236     rillig   2271: }
                   2272:
                   2273: /* :!cmd! */
                   2274: static Boolean
1.299     rillig   2275: ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st)
1.236     rillig   2276: {
1.299     rillig   2277:     st->cp = mod + 1;
1.298     rillig   2278:     char delim = '!';
                   2279:     char *cmd = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.274     rillig   2280:                                  NULL, NULL, NULL);
1.298     rillig   2281:     if (cmd == NULL) {
                   2282:        st->missing_delim = delim;
1.236     rillig   2283:        return FALSE;
1.298     rillig   2284:     }
1.274     rillig   2285:
                   2286:     const char *emsg = NULL;
1.268     rillig   2287:     if (st->eflags & VARE_WANTRES)
1.274     rillig   2288:        st->newStr = Cmd_Exec(cmd, &emsg);
1.236     rillig   2289:     else
                   2290:        st->newStr = varNoError;
1.274     rillig   2291:     free(cmd);
                   2292:
1.236     rillig   2293:     if (emsg)
                   2294:        Error(emsg, st->nstr);
1.274     rillig   2295:
1.236     rillig   2296:     st->termc = *st->cp;
                   2297:     if (st->v->flags & VAR_JUNK)
                   2298:        st->v->flags |= VAR_KEEP;
                   2299:     return TRUE;
                   2300: }
                   2301:
                   2302: /* :range */
                   2303: static Boolean
1.299     rillig   2304: ApplyModifier_Range(const char *mod, ApplyModifiersState *st)
1.236     rillig   2305: {
                   2306:     int n;
                   2307:     char *ep;
                   2308:
1.299     rillig   2309:     st->cp = mod + 1;  /* make sure it is set */
                   2310:     if (!STRMOD_MATCHX(mod, "range", 5))
1.236     rillig   2311:        return FALSE;
                   2312:
1.299     rillig   2313:     if (mod[5] == '=') {
                   2314:        n = strtoul(mod + 6, &ep, 10);
1.236     rillig   2315:        st->cp = ep;
                   2316:     } else {
                   2317:        n = 0;
1.299     rillig   2318:        st->cp = mod + 5;
1.236     rillig   2319:     }
                   2320:     st->newStr = VarRange(st->nstr, n);
                   2321:     st->termc = *st->cp;
                   2322:     return TRUE;
                   2323: }
                   2324:
                   2325: /* :Mpattern or :Npattern */
                   2326: static void
1.299     rillig   2327: ApplyModifier_Match(const char *mod, ApplyModifiersState *st)
1.236     rillig   2328: {
1.288     rillig   2329:     Boolean copy = FALSE;      /* pattern should be, or has been, copied */
                   2330:     Boolean needSubst = FALSE;
1.236     rillig   2331:     /*
1.288     rillig   2332:      * In the loop below, ignore ':' unless we are at (or back to) the
                   2333:      * original brace level.
                   2334:      * XXX This will likely not work right if $() and ${} are intermixed.
1.236     rillig   2335:      */
1.288     rillig   2336:     int nest = 1;
1.299     rillig   2337:     for (st->cp = mod + 1;
1.236     rillig   2338:         *st->cp != '\0' && !(*st->cp == ':' && nest == 1);
                   2339:         st->cp++) {
                   2340:        if (*st->cp == '\\' &&
                   2341:            (st->cp[1] == ':' || st->cp[1] == st->endc ||
                   2342:             st->cp[1] == st->startc)) {
                   2343:            if (!needSubst)
                   2344:                copy = TRUE;
                   2345:            st->cp++;
                   2346:            continue;
                   2347:        }
                   2348:        if (*st->cp == '$')
                   2349:            needSubst = TRUE;
                   2350:        if (*st->cp == '(' || *st->cp == '{')
                   2351:            ++nest;
                   2352:        if (*st->cp == ')' || *st->cp == '}') {
                   2353:            --nest;
                   2354:            if (nest == 0)
                   2355:                break;
                   2356:        }
                   2357:     }
                   2358:     st->termc = *st->cp;
1.288     rillig   2359:     const char *endpat = st->cp;
                   2360:
                   2361:     char *pattern = NULL;
1.236     rillig   2362:     if (copy) {
                   2363:        /*
                   2364:         * Need to compress the \:'s out of the pattern, so
                   2365:         * allocate enough room to hold the uncompressed
1.299     rillig   2366:         * pattern (note that st->cp started at mod+1, so
                   2367:         * st->cp - mod takes the null byte into account) and
1.236     rillig   2368:         * compress the pattern into the space.
                   2369:         */
1.299     rillig   2370:        pattern = bmake_malloc(st->cp - mod);
1.288     rillig   2371:        char *cp2;
1.299     rillig   2372:        for (cp2 = pattern, st->cp = mod + 1;
1.236     rillig   2373:             st->cp < endpat;
                   2374:             st->cp++, cp2++) {
                   2375:            if ((*st->cp == '\\') && (st->cp+1 < endpat) &&
                   2376:                (st->cp[1] == ':' || st->cp[1] == st->endc))
                   2377:                st->cp++;
                   2378:            *cp2 = *st->cp;
                   2379:        }
                   2380:        *cp2 = '\0';
                   2381:        endpat = cp2;
                   2382:     } else {
                   2383:        /*
1.292     rillig   2384:         * Either Var_Subst or ModifyWords will need a
1.236     rillig   2385:         * nul-terminated string soon, so construct one now.
                   2386:         */
1.299     rillig   2387:        pattern = bmake_strndup(mod + 1, endpat - (mod + 1));
1.236     rillig   2388:     }
                   2389:     if (needSubst) {
                   2390:        /* pattern contains embedded '$', so use Var_Subst to expand it. */
1.288     rillig   2391:        char *old_pattern = pattern;
                   2392:        pattern = Var_Subst(NULL, pattern, st->ctxt, st->eflags);
                   2393:        free(old_pattern);
1.236     rillig   2394:     }
                   2395:     if (DEBUG(VAR))
                   2396:        fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
                   2397:            st->v->name, st->nstr, pattern);
1.299     rillig   2398:     ModifyWordsCallback callback = mod[0] == 'M'
1.291     rillig   2399:        ? ModifyWord_Match : ModifyWord_NoMatch;
1.301     rillig   2400:     st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
1.291     rillig   2401:                             callback, pattern);
1.236     rillig   2402:     free(pattern);
                   2403: }
                   2404:
                   2405: /* :S,from,to, */
                   2406: static Boolean
1.299     rillig   2407: ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st)
1.236     rillig   2408: {
1.291     rillig   2409:     ModifyWord_SubstArgs args;
1.301     rillig   2410:     Boolean oneBigWord = st->oneBigWord;
1.299     rillig   2411:     char delim = mod[1];
                   2412:
                   2413:     st->cp = mod + 2;
1.236     rillig   2414:
                   2415:     /*
                   2416:      * If pattern begins with '^', it is anchored to the
                   2417:      * start of the word -- skip over it and flag pattern.
                   2418:      */
1.281     rillig   2419:     args.pflags = 0;
1.299     rillig   2420:     if (*st->cp == '^') {
1.288     rillig   2421:        args.pflags |= VARP_ANCHOR_START;
1.299     rillig   2422:        st->cp++;
1.236     rillig   2423:     }
                   2424:
1.298     rillig   2425:     char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.281     rillig   2426:                                  &args.pflags, &args.lhsLen, NULL);
1.298     rillig   2427:     if (lhs == NULL) {
                   2428:        st->missing_delim = delim;
1.236     rillig   2429:        return FALSE;
1.298     rillig   2430:     }
1.281     rillig   2431:     args.lhs = lhs;
1.236     rillig   2432:
1.298     rillig   2433:     char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.281     rillig   2434:                                  NULL, &args.rhsLen, &args);
1.298     rillig   2435:     if (rhs == NULL) {
                   2436:        st->missing_delim = delim;
1.236     rillig   2437:        return FALSE;
1.298     rillig   2438:     }
1.281     rillig   2439:     args.rhs = rhs;
1.236     rillig   2440:
                   2441:     /*
                   2442:      * Check for global substitution. If 'g' after the final
                   2443:      * delimiter, substitution is global and is marked that
                   2444:      * way.
                   2445:      */
                   2446:     for (;; st->cp++) {
                   2447:        switch (*st->cp) {
                   2448:        case 'g':
1.281     rillig   2449:            args.pflags |= VARP_SUB_GLOBAL;
1.236     rillig   2450:            continue;
                   2451:        case '1':
1.281     rillig   2452:            args.pflags |= VARP_SUB_ONE;
1.236     rillig   2453:            continue;
                   2454:        case 'W':
1.301     rillig   2455:            oneBigWord = TRUE;
1.236     rillig   2456:            continue;
                   2457:        }
                   2458:        break;
                   2459:     }
                   2460:
                   2461:     st->termc = *st->cp;
1.301     rillig   2462:     st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr,
1.291     rillig   2463:                             ModifyWord_Subst, &args);
1.236     rillig   2464:
1.281     rillig   2465:     free(lhs);
                   2466:     free(rhs);
1.236     rillig   2467:     return TRUE;
                   2468: }
                   2469:
                   2470: #ifndef NO_REGEX
1.291     rillig   2471:
1.236     rillig   2472: /* :C,from,to, */
                   2473: static Boolean
1.299     rillig   2474: ApplyModifier_Regex(const char *mod, ApplyModifiersState *st)
1.236     rillig   2475: {
1.291     rillig   2476:     ModifyWord_SubstRegexArgs args;
1.236     rillig   2477:
1.291     rillig   2478:     args.pflags = 0;
1.301     rillig   2479:     Boolean oneBigWord = st->oneBigWord;
1.299     rillig   2480:     char delim = mod[1];
1.236     rillig   2481:
1.299     rillig   2482:     st->cp = mod + 2;
1.236     rillig   2483:
1.297     rillig   2484:     char *re = ParseModifierPart(st->ctxt, &st->cp, delim,
1.291     rillig   2485:                                 st->eflags, NULL, NULL, NULL);
1.297     rillig   2486:     if (re == NULL) {
1.298     rillig   2487:        st->missing_delim = delim;
1.236     rillig   2488:        return FALSE;
1.297     rillig   2489:     }
1.236     rillig   2490:
1.297     rillig   2491:     args.replace = ParseModifierPart(st->ctxt, &st->cp, delim,
1.291     rillig   2492:                                     st->eflags, NULL, NULL, NULL);
                   2493:     if (args.replace == NULL) {
1.236     rillig   2494:        free(re);
1.298     rillig   2495:        st->missing_delim = delim;
1.236     rillig   2496:        return FALSE;
                   2497:     }
                   2498:
                   2499:     for (;; st->cp++) {
                   2500:        switch (*st->cp) {
                   2501:        case 'g':
1.291     rillig   2502:            args.pflags |= VARP_SUB_GLOBAL;
1.236     rillig   2503:            continue;
                   2504:        case '1':
1.291     rillig   2505:            args.pflags |= VARP_SUB_ONE;
1.236     rillig   2506:            continue;
                   2507:        case 'W':
1.301     rillig   2508:            oneBigWord = TRUE;
1.236     rillig   2509:            continue;
                   2510:        }
                   2511:        break;
                   2512:     }
                   2513:
                   2514:     st->termc = *st->cp;
                   2515:
1.291     rillig   2516:     int error = regcomp(&args.re, re, REG_EXTENDED);
1.236     rillig   2517:     free(re);
1.242     rillig   2518:     if (error) {
1.236     rillig   2519:        *st->lengthPtr = st->cp - st->start + 1;
1.291     rillig   2520:        VarREError(error, &args.re, "RE substitution error");
                   2521:        free(args.replace);
1.236     rillig   2522:        return FALSE;
                   2523:     }
                   2524:
1.291     rillig   2525:     args.nsub = args.re.re_nsub + 1;
                   2526:     if (args.nsub < 1)
                   2527:        args.nsub = 1;
                   2528:     if (args.nsub > 10)
                   2529:        args.nsub = 10;
1.301     rillig   2530:     st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr,
1.291     rillig   2531:                             ModifyWord_SubstRegex, &args);
                   2532:     regfree(&args.re);
                   2533:     free(args.replace);
1.236     rillig   2534:     return TRUE;
                   2535: }
                   2536: #endif
                   2537:
1.278     rillig   2538: static void
1.295     rillig   2539: ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1.278     rillig   2540: {
                   2541:     SepBuf_AddBytes(buf, word, strlen(word));
1.275     rillig   2542: }
                   2543:
1.289     rillig   2544: /* :ts<separator> */
                   2545: static Boolean
1.299     rillig   2546: ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
1.289     rillig   2547: {
                   2548:     if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
                   2549:        /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */
1.301     rillig   2550:        st->sep = sep[0];
1.289     rillig   2551:        st->cp = sep + 1;
                   2552:     } else if (sep[0] == st->endc || sep[0] == ':') {
                   2553:        /* ":ts<endc>" or ":ts:" */
1.301     rillig   2554:        st->sep = '\0';         /* no separator */
1.289     rillig   2555:        st->cp = sep;
                   2556:     } else if (sep[0] == '\\') {
                   2557:        const char *xp = sep + 1;
                   2558:        int base = 8;           /* assume octal */
                   2559:
                   2560:        switch (sep[1]) {
                   2561:        case 'n':
1.301     rillig   2562:            st->sep = '\n';
1.289     rillig   2563:            st->cp = sep + 2;
                   2564:            break;
                   2565:        case 't':
1.301     rillig   2566:            st->sep = '\t';
1.289     rillig   2567:            st->cp = sep + 2;
                   2568:            break;
                   2569:        case 'x':
                   2570:            base = 16;
                   2571:            xp++;
                   2572:            goto get_numeric;
                   2573:        case '0':
                   2574:            base = 0;
                   2575:            goto get_numeric;
                   2576:        default:
                   2577:            if (!isdigit((unsigned char)sep[1]))
                   2578:                return FALSE;   /* ":ts<backslash><unrecognised>". */
                   2579:
                   2580:            char *end;
                   2581:        get_numeric:
1.301     rillig   2582:            st->sep = strtoul(sep + 1 + (sep[1] == 'x'), &end, base);
1.289     rillig   2583:            if (*end != ':' && *end != st->endc)
                   2584:                return FALSE;
                   2585:            st->cp = end;
                   2586:            break;
                   2587:        }
                   2588:     } else {
                   2589:        return FALSE;           /* Found ":ts<unrecognised><unrecognised>". */
                   2590:     }
                   2591:
                   2592:     st->termc = *st->cp;
1.301     rillig   2593:     st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
1.292     rillig   2594:                             ModifyWord_Copy, NULL);
1.289     rillig   2595:     return TRUE;
                   2596: }
                   2597:
                   2598: /* :tA, :tu, :tl, :ts<separator>, etc. */
1.236     rillig   2599: static Boolean
1.299     rillig   2600: ApplyModifier_To(const char *mod, ApplyModifiersState *st)
1.236     rillig   2601: {
1.299     rillig   2602:     st->cp = mod + 1;  /* make sure it is set */
                   2603:     if (mod[1] == st->endc || mod[1] == ':')
1.289     rillig   2604:        return FALSE;           /* Found ":t<endc>" or ":t:". */
                   2605:
1.299     rillig   2606:     if (mod[1] == 's')
                   2607:        return ApplyModifier_ToSep(mod + 2, st);
1.289     rillig   2608:
1.299     rillig   2609:     if (mod[2] != st->endc && mod[2] != ':')
1.289     rillig   2610:        return FALSE;           /* Found ":t<unrecognised><unrecognised>". */
1.236     rillig   2611:
1.289     rillig   2612:     /* Check for two-character options: ":tu", ":tl" */
1.299     rillig   2613:     if (mod[1] == 'A') {       /* absolute path */
1.301     rillig   2614:        st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
1.291     rillig   2615:                                 ModifyWord_Realpath, NULL);
1.299     rillig   2616:        st->cp = mod + 2;
1.289     rillig   2617:        st->termc = *st->cp;
1.299     rillig   2618:     } else if (mod[1] == 'u') {
1.289     rillig   2619:        char *dp = bmake_strdup(st->nstr);
                   2620:        for (st->newStr = dp; *dp; dp++)
                   2621:            *dp = toupper((unsigned char)*dp);
1.299     rillig   2622:        st->cp = mod + 2;
1.289     rillig   2623:        st->termc = *st->cp;
1.299     rillig   2624:     } else if (mod[1] == 'l') {
1.289     rillig   2625:        char *dp = bmake_strdup(st->nstr);
                   2626:        for (st->newStr = dp; *dp; dp++)
                   2627:            *dp = tolower((unsigned char)*dp);
1.299     rillig   2628:        st->cp = mod + 2;
1.289     rillig   2629:        st->termc = *st->cp;
1.299     rillig   2630:     } else if (mod[1] == 'W' || mod[1] == 'w') {
1.301     rillig   2631:        st->oneBigWord = mod[1] == 'W';
1.289     rillig   2632:        st->newStr = st->nstr;
1.299     rillig   2633:        st->cp = mod + 2;
1.289     rillig   2634:        st->termc = *st->cp;
1.236     rillig   2635:     } else {
1.289     rillig   2636:        /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
1.236     rillig   2637:        return FALSE;
                   2638:     }
                   2639:     return TRUE;
                   2640: }
                   2641:
                   2642: /* :[#], :[1], etc. */
                   2643: static int
1.299     rillig   2644: ApplyModifier_Words(const char *mod, ApplyModifiersState *st)
1.236     rillig   2645: {
1.299     rillig   2646:     st->cp = mod + 1;  /* point to char after '[' */
1.298     rillig   2647:     char delim = ']';          /* look for closing ']' */
                   2648:     char *estr = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.266     rillig   2649:                                   NULL, NULL, NULL);
1.298     rillig   2650:     if (estr == NULL) {
                   2651:        st->missing_delim = delim;
                   2652:        return 'c';
                   2653:     }
1.288     rillig   2654:
1.236     rillig   2655:     /* now st->cp points just after the closing ']' */
1.288     rillig   2656:     if (st->cp[0] != ':' && st->cp[0] != st->endc)
                   2657:        goto bad_modifier;      /* Found junk after ']' */
                   2658:
                   2659:     if (estr[0] == '\0')
                   2660:        goto bad_modifier;      /* empty square brackets in ":[]". */
1.236     rillig   2661:
1.288     rillig   2662:     if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
1.236     rillig   2663:        /*
1.288     rillig   2664:         * We will need enough space for the decimal representation of an int.
                   2665:         * We calculate the space needed for the octal representation, and add
                   2666:         * enough slop to cope with a '-' sign (which should never be needed)
                   2667:         * and a '\0' string terminator.
1.236     rillig   2668:         */
                   2669:        int newStrSize = (sizeof(int) * CHAR_BIT + 2) / 3 + 2;
                   2670:
                   2671:        st->newStr = bmake_malloc(newStrSize);
1.301     rillig   2672:        if (st->oneBigWord) {
1.236     rillig   2673:            strncpy(st->newStr, "1", newStrSize);
                   2674:        } else {
                   2675:            /* XXX: brk_string() is a rather expensive
                   2676:             * way of counting words. */
                   2677:            char **av;
                   2678:            char *as;
                   2679:            int ac;
                   2680:
                   2681:            av = brk_string(st->nstr, &ac, FALSE, &as);
1.242     rillig   2682:            snprintf(st->newStr, newStrSize, "%d", ac);
1.236     rillig   2683:            free(as);
                   2684:            free(av);
                   2685:        }
1.288     rillig   2686:        goto ok;
                   2687:     }
                   2688:
                   2689:     if (estr[0] == '*' && estr[1] == '\0') {
1.236     rillig   2690:        /* Found ":[*]" */
1.301     rillig   2691:        st->oneBigWord = TRUE;
1.236     rillig   2692:        st->newStr = st->nstr;
1.288     rillig   2693:        goto ok;
                   2694:     }
                   2695:
                   2696:     if (estr[0] == '@' && estr[1] == '\0') {
1.236     rillig   2697:        /* Found ":[@]" */
1.301     rillig   2698:        st->oneBigWord = FALSE;
1.236     rillig   2699:        st->newStr = st->nstr;
1.288     rillig   2700:        goto ok;
                   2701:     }
                   2702:
                   2703:     /*
                   2704:      * We expect estr to contain a single integer for :[N], or two integers
                   2705:      * separated by ".." for :[start..end].
                   2706:      */
                   2707:     char *ep;
1.290     rillig   2708:     int first = strtol(estr, &ep, 0);
                   2709:     int last;
1.288     rillig   2710:     if (ep == estr)            /* Found junk instead of a number */
                   2711:        goto bad_modifier;
                   2712:
                   2713:     if (ep[0] == '\0') {       /* Found only one integer in :[N] */
1.290     rillig   2714:        last = first;
1.288     rillig   2715:     } else if (ep[0] == '.' && ep[1] == '.' && ep[2] != '\0') {
                   2716:        /* Expecting another integer after ".." */
                   2717:        ep += 2;
1.290     rillig   2718:        last = strtol(ep, &ep, 0);
1.288     rillig   2719:        if (ep[0] != '\0')      /* Found junk after ".." */
                   2720:            goto bad_modifier;
                   2721:     } else
                   2722:        goto bad_modifier;      /* Found junk instead of ".." */
1.236     rillig   2723:
1.288     rillig   2724:     /*
                   2725:      * Now seldata is properly filled in, but we still have to check for 0 as
                   2726:      * a special case.
                   2727:      */
1.290     rillig   2728:     if (first == 0 && last == 0) {
1.288     rillig   2729:        /* ":[0]" or perhaps ":[0..0]" */
1.301     rillig   2730:        st->oneBigWord = TRUE;
1.288     rillig   2731:        st->newStr = st->nstr;
                   2732:        goto ok;
1.236     rillig   2733:     }
1.288     rillig   2734:
                   2735:     /* ":[0..N]" or ":[N..0]" */
1.290     rillig   2736:     if (first == 0 || last == 0)
1.288     rillig   2737:        goto bad_modifier;
                   2738:
                   2739:     /* Normal case: select the words described by seldata. */
1.301     rillig   2740:     st->newStr = VarSelectWords(st->sep, st->oneBigWord, st->nstr, first, last);
1.288     rillig   2741:
                   2742: ok:
                   2743:     st->termc = *st->cp;
                   2744:     free(estr);
                   2745:     return 0;
                   2746:
                   2747: bad_modifier:
                   2748:     free(estr);
                   2749:     return 'b';
1.236     rillig   2750: }
                   2751:
                   2752: /* :O or :Ox */
                   2753: static Boolean
1.299     rillig   2754: ApplyModifier_Order(const char *mod, ApplyModifiersState *st)
1.236     rillig   2755: {
                   2756:     char otype;
                   2757:
1.299     rillig   2758:     st->cp = mod + 1;  /* skip to the rest in any case */
                   2759:     if (mod[1] == st->endc || mod[1] == ':') {
1.236     rillig   2760:        otype = 's';
                   2761:        st->termc = *st->cp;
1.299     rillig   2762:     } else if ((mod[1] == 'r' || mod[1] == 'x') &&
                   2763:               (mod[2] == st->endc || mod[2] == ':')) {
                   2764:        otype = mod[1];
                   2765:        st->cp = mod + 2;
1.236     rillig   2766:        st->termc = *st->cp;
                   2767:     } else {
                   2768:        return FALSE;
                   2769:     }
                   2770:     st->newStr = VarOrder(st->nstr, otype);
                   2771:     return TRUE;
                   2772: }
                   2773:
                   2774: /* :? then : else */
                   2775: static Boolean
1.299     rillig   2776: ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st)
1.236     rillig   2777: {
1.285     rillig   2778:     Boolean value = FALSE;
                   2779:     int cond_rc = 0;
                   2780:     VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES;
                   2781:     VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES;
1.236     rillig   2782:
1.268     rillig   2783:     if (st->eflags & VARE_WANTRES) {
1.236     rillig   2784:        cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE);
1.285     rillig   2785:        if (cond_rc != COND_INVALID && value)
                   2786:            then_eflags |= VARE_WANTRES;
                   2787:        if (cond_rc != COND_INVALID && !value)
                   2788:            else_eflags |= VARE_WANTRES;
1.236     rillig   2789:     }
                   2790:
1.299     rillig   2791:     st->cp = mod + 1;
1.298     rillig   2792:     char delim = ':';
1.265     rillig   2793:     char *then_expr = ParseModifierPart(
1.298     rillig   2794:        st->ctxt, &st->cp, delim, then_eflags, NULL, NULL, NULL);
                   2795:     if (then_expr == NULL) {
                   2796:        st->missing_delim = delim;
1.236     rillig   2797:        return FALSE;
1.298     rillig   2798:     }
1.236     rillig   2799:
1.298     rillig   2800:     delim = st->endc;          /* BRCLOSE or PRCLOSE */
1.265     rillig   2801:     char *else_expr = ParseModifierPart(
1.298     rillig   2802:        st->ctxt, &st->cp, delim, else_eflags, NULL, NULL, NULL);
                   2803:     if (else_expr == NULL) {
                   2804:        st->missing_delim = delim;
1.236     rillig   2805:        return FALSE;
1.298     rillig   2806:     }
1.236     rillig   2807:
                   2808:     st->termc = *--st->cp;
                   2809:     if (cond_rc == COND_INVALID) {
                   2810:        Error("Bad conditional expression `%s' in %s?%s:%s",
1.258     rillig   2811:            st->v->name, st->v->name, then_expr, else_expr);
1.236     rillig   2812:        return FALSE;
                   2813:     }
                   2814:
                   2815:     if (value) {
1.258     rillig   2816:        st->newStr = then_expr;
                   2817:        free(else_expr);
1.236     rillig   2818:     } else {
1.258     rillig   2819:        st->newStr = else_expr;
1.270     rillig   2820:        free(then_expr);
1.236     rillig   2821:     }
                   2822:     if (st->v->flags & VAR_JUNK)
                   2823:        st->v->flags |= VAR_KEEP;
                   2824:     return TRUE;
                   2825: }
                   2826:
1.283     rillig   2827: /*
                   2828:  * The ::= modifiers actually assign a value to the variable.
                   2829:  * Their main purpose is in supporting modifiers of .for loop
                   2830:  * iterators and other obscure uses.  They always expand to
                   2831:  * nothing.  In a target rule that would otherwise expand to an
                   2832:  * empty line they can be preceded with @: to keep make happy.
                   2833:  * Eg.
                   2834:  *
                   2835:  * foo:        .USE
                   2836:  * .for i in ${.TARGET} ${.TARGET:R}.gz
                   2837:  *     @: ${t::=$i}
                   2838:  *     @echo blah ${t:T}
                   2839:  * .endfor
                   2840:  *
                   2841:  *       ::=<str>      Assigns <str> as the new value of variable.
                   2842:  *       ::?=<str>     Assigns <str> as value of variable if
                   2843:  *                     it was not already set.
                   2844:  *       ::+=<str>     Appends <str> to variable.
                   2845:  *       ::!=<cmd>     Assigns output of <cmd> as the new value of
                   2846:  *                     variable.
                   2847:  */
1.236     rillig   2848: static int
1.299     rillig   2849: ApplyModifier_Assign(const char *mod, ApplyModifiersState *st)
1.236     rillig   2850: {
1.299     rillig   2851:     const char *op = mod + 1;
1.272     rillig   2852:     if (!(op[0] == '=' ||
                   2853:        (op[1] == '=' &&
                   2854:         (op[0] == '!' || op[0] == '+' || op[0] == '?'))))
                   2855:        return 'd';             /* "::<unrecognised>" */
1.236     rillig   2856:
1.272     rillig   2857:     GNode *v_ctxt;             /* context where v belongs */
                   2858:
                   2859:     if (st->v->name[0] == 0)
                   2860:        return 'b';
                   2861:
                   2862:     v_ctxt = st->ctxt;
1.273     rillig   2863:     char *sv_name = NULL;
1.272     rillig   2864:     if (st->v->flags & VAR_JUNK) {
                   2865:        /*
                   2866:         * We need to bmake_strdup() it incase ParseModifierPart() recurses.
                   2867:         */
                   2868:        sv_name = st->v->name;
                   2869:        st->v->name = bmake_strdup(st->v->name);
                   2870:     } else if (st->ctxt != VAR_GLOBAL) {
                   2871:        Var *gv = VarFind(st->v->name, st->ctxt, 0);
                   2872:        if (gv == NULL)
                   2873:            v_ctxt = VAR_GLOBAL;
                   2874:        else
                   2875:            VarFreeEnv(gv, TRUE);
                   2876:     }
                   2877:
1.273     rillig   2878:     switch (op[0]) {
1.272     rillig   2879:     case '+':
                   2880:     case '?':
                   2881:     case '!':
1.299     rillig   2882:        st->cp = mod + 3;
1.272     rillig   2883:        break;
                   2884:     default:
1.299     rillig   2885:        st->cp = mod + 2;
1.272     rillig   2886:        break;
                   2887:     }
                   2888:
1.298     rillig   2889:     char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE;
1.287     rillig   2890:     VarEvalFlags eflags = (st->eflags & VARE_WANTRES) ? 0 : VARE_NOSUBST;
1.298     rillig   2891:     char *val = ParseModifierPart(st->ctxt, &st->cp, delim,
1.287     rillig   2892:                                  st->eflags | eflags, NULL, NULL, NULL);
1.272     rillig   2893:     if (st->v->flags & VAR_JUNK) {
                   2894:        /* restore original name */
                   2895:        free(st->v->name);
                   2896:        st->v->name = sv_name;
                   2897:     }
1.298     rillig   2898:     if (val == NULL) {
                   2899:        st->missing_delim = delim;
1.272     rillig   2900:        return 'c';
1.298     rillig   2901:     }
1.236     rillig   2902:
1.272     rillig   2903:     st->termc = *--st->cp;
1.236     rillig   2904:
1.272     rillig   2905:     if (st->eflags & VARE_WANTRES) {
1.273     rillig   2906:        switch (op[0]) {
1.236     rillig   2907:        case '+':
1.273     rillig   2908:            Var_Append(st->v->name, val, v_ctxt);
1.272     rillig   2909:            break;
1.273     rillig   2910:        case '!': {
                   2911:            const char *emsg;
                   2912:            st->newStr = Cmd_Exec(val, &emsg);
1.272     rillig   2913:            if (emsg)
                   2914:                Error(emsg, st->nstr);
                   2915:            else
                   2916:                Var_Set(st->v->name, st->newStr, v_ctxt);
                   2917:            free(st->newStr);
1.236     rillig   2918:            break;
1.273     rillig   2919:        }
1.272     rillig   2920:        case '?':
                   2921:            if ((st->v->flags & VAR_JUNK) == 0)
                   2922:                break;
                   2923:            /* FALLTHROUGH */
1.236     rillig   2924:        default:
1.273     rillig   2925:            Var_Set(st->v->name, val, v_ctxt);
1.236     rillig   2926:            break;
                   2927:        }
                   2928:     }
1.273     rillig   2929:     free(val);
1.272     rillig   2930:     st->newStr = varNoError;
                   2931:     return 0;
1.236     rillig   2932: }
                   2933:
                   2934: /* remember current value */
                   2935: static Boolean
1.299     rillig   2936: ApplyModifier_Remember(const char *mod, ApplyModifiersState *st)
1.236     rillig   2937: {
1.299     rillig   2938:     st->cp = mod + 1;  /* make sure it is set */
                   2939:     if (!STRMOD_MATCHX(mod, "_", 1))
1.236     rillig   2940:        return FALSE;
                   2941:
1.299     rillig   2942:     if (mod[1] == '=') {
1.236     rillig   2943:        char *np;
                   2944:        int n;
                   2945:
                   2946:        st->cp++;
                   2947:        n = strcspn(st->cp, ":)}");
1.249     rillig   2948:        np = bmake_strndup(st->cp, n + 1);
1.236     rillig   2949:        np[n] = '\0';
1.299     rillig   2950:        st->cp = mod + 2 + n;
1.236     rillig   2951:        Var_Set(np, st->nstr, st->ctxt);
                   2952:        free(np);
                   2953:     } else {
                   2954:        Var_Set("_", st->nstr, st->ctxt);
                   2955:     }
                   2956:     st->newStr = st->nstr;
                   2957:     st->termc = *st->cp;
                   2958:     return TRUE;
                   2959: }
                   2960:
                   2961: #ifdef SYSVVARSUB
                   2962: /* :from=to */
                   2963: static int
1.299     rillig   2964: ApplyModifier_SysV(const char *mod, ApplyModifiersState *st)
1.236     rillig   2965: {
1.276     rillig   2966:     Boolean eqFound = FALSE;
1.245     rillig   2967:
1.236     rillig   2968:     /*
                   2969:      * First we make a pass through the string trying
                   2970:      * to verify it is a SYSV-make-style translation:
                   2971:      * it must be: <string1>=<string2>)
                   2972:      */
1.299     rillig   2973:     st->cp = mod;
1.262     rillig   2974:     int nest = 1;
                   2975:     while (*st->cp != '\0' && nest > 0) {
1.236     rillig   2976:        if (*st->cp == '=') {
                   2977:            eqFound = TRUE;
                   2978:            /* continue looking for st->endc */
1.242     rillig   2979:        } else if (*st->cp == st->endc)
1.262     rillig   2980:            nest--;
1.236     rillig   2981:        else if (*st->cp == st->startc)
1.262     rillig   2982:            nest++;
                   2983:        if (nest > 0)
1.236     rillig   2984:            st->cp++;
                   2985:     }
1.245     rillig   2986:     if (*st->cp != st->endc || !eqFound)
                   2987:        return 0;
1.236     rillig   2988:
1.298     rillig   2989:     char delim = '=';
1.299     rillig   2990:     st->cp = mod;
1.298     rillig   2991:     char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.284     rillig   2992:                                  NULL, NULL, NULL);
1.298     rillig   2993:     if (lhs == NULL) {
                   2994:        st->missing_delim = delim;
1.245     rillig   2995:        return 'c';
1.298     rillig   2996:     }
1.245     rillig   2997:
1.298     rillig   2998:     delim = st->endc;
                   2999:     char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags,
1.276     rillig   3000:                                  NULL, NULL, NULL);
1.298     rillig   3001:     if (rhs == NULL) {
                   3002:        st->missing_delim = delim;
1.245     rillig   3003:        return 'c';
1.298     rillig   3004:     }
1.236     rillig   3005:
1.245     rillig   3006:     /*
                   3007:      * SYSV modifications happen through the whole
                   3008:      * string. Note the pattern is anchored at the end.
                   3009:      */
                   3010:     st->termc = *--st->cp;
1.276     rillig   3011:     if (lhs[0] == '\0' && *st->nstr == '\0') {
1.245     rillig   3012:        st->newStr = st->nstr;  /* special case */
                   3013:     } else {
1.295     rillig   3014:        ModifyWord_SYSVSubstArgs args = { st->ctxt, lhs, rhs };
1.301     rillig   3015:        st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
1.291     rillig   3016:                                 ModifyWord_SYSVSubst, &args);
1.245     rillig   3017:     }
1.276     rillig   3018:     free(lhs);
                   3019:     free(rhs);
1.245     rillig   3020:     return '=';
1.236     rillig   3021: }
                   3022: #endif
                   3023:
1.108     sjg      3024: /*
                   3025:  * Now we need to apply any modifiers the user wants applied.
                   3026:  * These are:
                   3027:  *       :M<pattern>   words which match the given <pattern>.
1.138     dsl      3028:  *                     <pattern> is of the standard file
                   3029:  *                     wildcarding form.
1.108     sjg      3030:  *       :N<pattern>   words which do not match the given <pattern>.
                   3031:  *       :S<d><pat1><d><pat2><d>[1gW]
1.138     dsl      3032:  *                     Substitute <pat2> for <pat1> in the value
1.108     sjg      3033:  *       :C<d><pat1><d><pat2><d>[1gW]
1.138     dsl      3034:  *                     Substitute <pat2> for regex <pat1> in the value
                   3035:  *       :H            Substitute the head of each word
                   3036:  *       :T            Substitute the tail of each word
                   3037:  *       :E            Substitute the extension (minus '.') of
                   3038:  *                     each word
                   3039:  *       :R            Substitute the root of each word
                   3040:  *                     (pathname minus the suffix).
                   3041:  *       :O            ("Order") Alphabeticaly sort words in variable.
                   3042:  *       :Ox           ("intermiX") Randomize words in variable.
                   3043:  *       :u            ("uniq") Remove adjacent duplicate words.
                   3044:  *       :tu           Converts the variable contents to uppercase.
                   3045:  *       :tl           Converts the variable contents to lowercase.
                   3046:  *       :ts[c]        Sets varSpace - the char used to
                   3047:  *                     separate words to 'c'. If 'c' is
                   3048:  *                     omitted then no separation is used.
                   3049:  *       :tW           Treat the variable contents as a single
                   3050:  *                     word, even if it contains spaces.
                   3051:  *                     (Mnemonic: one big 'W'ord.)
                   3052:  *       :tw           Treat the variable contents as multiple
                   3053:  *                     space-separated words.
                   3054:  *                     (Mnemonic: many small 'w'ords.)
                   3055:  *       :[index]      Select a single word from the value.
                   3056:  *       :[start..end] Select multiple words from the value.
                   3057:  *       :[*] or :[0]  Select the entire value, as a single
                   3058:  *                     word.  Equivalent to :tW.
                   3059:  *       :[@]          Select the entire value, as multiple
                   3060:  *                     words.  Undoes the effect of :[*].
                   3061:  *                     Equivalent to :tw.
                   3062:  *       :[#]          Returns the number of words in the value.
                   3063:  *
                   3064:  *       :?<true-value>:<false-value>
                   3065:  *                     If the variable evaluates to true, return
                   3066:  *                     true value, else return the second value.
                   3067:  *       :lhs=rhs      Like :S, but the rhs goes to the end of
                   3068:  *                     the invocation.
                   3069:  *       :sh           Treat the current value as a command
                   3070:  *                     to be run, new value is its output.
1.108     sjg      3071:  * The following added so we can handle ODE makefiles.
1.138     dsl      3072:  *       :@<tmpvar>@<newval>@
                   3073:  *                     Assign a temporary local variable <tmpvar>
                   3074:  *                     to the current value of each word in turn
                   3075:  *                     and replace each word with the result of
                   3076:  *                     evaluating <newval>
                   3077:  *       :D<newval>    Use <newval> as value if variable defined
                   3078:  *       :U<newval>    Use <newval> as value if variable undefined
                   3079:  *       :L            Use the name of the variable as the value.
                   3080:  *       :P            Use the path of the node that has the same
                   3081:  *                     name as the variable as the value.  This
                   3082:  *                     basically includes an implied :L so that
                   3083:  *                     the common method of refering to the path
                   3084:  *                     of your dependent 'x' in a rule is to use
                   3085:  *                     the form '${x:P}'.
                   3086:  *       :!<cmd>!      Run cmd much the same as :sh run's the
                   3087:  *                     current value of the variable.
1.283     rillig   3088:  * Assignment operators (see ApplyModifier_Assign).
1.1       cgd      3089:  */
1.108     sjg      3090: static char *
                   3091: ApplyModifiers(char *nstr, const char *tstr,
1.236     rillig   3092:               int const startc, int const endc,
1.268     rillig   3093:               Var * const v, GNode * const ctxt, VarEvalFlags const eflags,
1.236     rillig   3094:               int * const lengthPtr, void ** const freePtr)
                   3095: {
                   3096:     ApplyModifiersState st = {
1.268     rillig   3097:        startc, endc, v, ctxt, eflags, lengthPtr, freePtr,
1.299     rillig   3098:        nstr, tstr, tstr,
1.301     rillig   3099:        '\0', '\0', 0, ' ', FALSE, NULL
1.236     rillig   3100:     };
1.15      christos 3101:
1.299     rillig   3102:     const char *p = tstr;
                   3103:     while (*p != '\0' && *p != endc) {
1.142     dsl      3104:
1.299     rillig   3105:        if (*p == '$') {
1.142     dsl      3106:            /*
1.167     sjg      3107:             * We may have some complex modifiers in a variable.
1.1       cgd      3108:             */
1.108     sjg      3109:            void *freeIt;
                   3110:            char *rval;
1.127     christos 3111:            int rlen;
1.167     sjg      3112:            int c;
1.22      christos 3113:
1.299     rillig   3114:            rval = Var_Parse(p, st.ctxt, st.eflags, &rlen, &freeIt);
1.1       cgd      3115:
1.167     sjg      3116:            /*
1.236     rillig   3117:             * If we have not parsed up to st.endc or ':',
1.167     sjg      3118:             * we are not interested.
                   3119:             */
                   3120:            if (rval != NULL && *rval &&
1.299     rillig   3121:                (c = p[rlen]) != '\0' &&
1.167     sjg      3122:                c != ':' &&
1.236     rillig   3123:                c != st.endc) {
1.196     christos 3124:                free(freeIt);
1.167     sjg      3125:                goto apply_mods;
                   3126:            }
                   3127:
1.108     sjg      3128:            if (DEBUG(VAR)) {
1.114     dsl      3129:                fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
1.299     rillig   3130:                       rval, rlen, p, rlen, p + rlen);
1.22      christos 3131:            }
1.1       cgd      3132:
1.299     rillig   3133:            p += rlen;
1.15      christos 3134:
1.108     sjg      3135:            if (rval != NULL && *rval) {
1.127     christos 3136:                int used;
1.15      christos 3137:
1.236     rillig   3138:                st.nstr = ApplyModifiers(st.nstr, rval, 0, 0, st.v,
1.268     rillig   3139:                                      st.ctxt, st.eflags, &used, st.freePtr);
1.236     rillig   3140:                if (st.nstr == var_Error
1.268     rillig   3141:                    || (st.nstr == varNoError && (st.eflags & VARE_UNDEFERR) == 0)
1.111     rillig   3142:                    || strlen(rval) != (size_t) used) {
1.196     christos 3143:                    free(freeIt);
1.240     rillig   3144:                    goto out;   /* error already reported */
1.1       cgd      3145:                }
                   3146:            }
1.196     christos 3147:            free(freeIt);
1.299     rillig   3148:            if (*p == ':')
                   3149:                p++;
                   3150:            else if (*p == '\0' && endc != '\0') {
1.246     rillig   3151:                Error("Unclosed variable specification after complex "
                   3152:                    "modifier (expecting '%c') for %s", st.endc, st.v->name);
1.119     sjg      3153:                goto out;
                   3154:            }
1.108     sjg      3155:            continue;
                   3156:        }
1.167     sjg      3157:     apply_mods:
1.108     sjg      3158:        if (DEBUG(VAR)) {
1.236     rillig   3159:            fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", st.v->name,
1.299     rillig   3160:                *p, st.nstr);
1.1       cgd      3161:        }
1.236     rillig   3162:        st.newStr = var_Error;
1.299     rillig   3163:        switch ((st.modifier = *p)) {
1.108     sjg      3164:        case ':':
1.1       cgd      3165:            {
1.299     rillig   3166:                int res = ApplyModifier_Assign(p, &st);
1.236     rillig   3167:                if (res == 'b')
                   3168:                    goto bad_modifier;
                   3169:                if (res == 'c')
1.108     sjg      3170:                    goto cleanup;
1.236     rillig   3171:                if (res == 'd')
                   3172:                    goto default_case;
1.108     sjg      3173:                break;
                   3174:            }
1.236     rillig   3175:        case '@':
1.299     rillig   3176:            ApplyModifier_Loop(p, &st);
1.236     rillig   3177:            break;
                   3178:        case '_':
1.299     rillig   3179:            if (!ApplyModifier_Remember(p, &st))
1.236     rillig   3180:                goto default_case;
                   3181:            break;
1.108     sjg      3182:        case 'D':
                   3183:        case 'U':
1.299     rillig   3184:            ApplyModifier_Defined(p, &st);
1.236     rillig   3185:            break;
1.108     sjg      3186:        case 'L':
                   3187:            {
1.236     rillig   3188:                if ((st.v->flags & VAR_JUNK) != 0)
                   3189:                    st.v->flags |= VAR_KEEP;
                   3190:                st.newStr = bmake_strdup(st.v->name);
1.299     rillig   3191:                st.cp = p + 1;
                   3192:                st.termc = *st.cp;
1.108     sjg      3193:                break;
                   3194:            }
                   3195:        case 'P':
1.299     rillig   3196:            ApplyModifier_Path(p, &st);
1.236     rillig   3197:            break;
1.108     sjg      3198:        case '!':
1.299     rillig   3199:            if (!ApplyModifier_Exclam(p, &st))
1.236     rillig   3200:                goto cleanup;
                   3201:            break;
                   3202:        case '[':
1.108     sjg      3203:            {
1.299     rillig   3204:                int res = ApplyModifier_Words(p, &st);
1.236     rillig   3205:                if (res == 'b')
                   3206:                    goto bad_modifier;
                   3207:                if (res == 'c')
1.108     sjg      3208:                    goto cleanup;
                   3209:                break;
                   3210:            }
1.164     sjg      3211:        case 'g':
1.299     rillig   3212:            if (!ApplyModifier_Gmtime(p, &st))
1.165     sjg      3213:                goto default_case;
1.164     sjg      3214:            break;
1.163     joerg    3215:        case 'h':
1.299     rillig   3216:            if (!ApplyModifier_Hash(p, &st))
1.165     sjg      3217:                goto default_case;
1.163     joerg    3218:            break;
1.164     sjg      3219:        case 'l':
1.299     rillig   3220:            if (!ApplyModifier_Localtime(p, &st))
1.165     sjg      3221:                goto default_case;
1.164     sjg      3222:            break;
1.108     sjg      3223:        case 't':
1.299     rillig   3224:            if (!ApplyModifier_To(p, &st))
1.236     rillig   3225:                goto bad_modifier;
                   3226:            break;
1.108     sjg      3227:        case 'N':
                   3228:        case 'M':
1.299     rillig   3229:            ApplyModifier_Match(p, &st);
1.236     rillig   3230:            break;
1.108     sjg      3231:        case 'S':
1.299     rillig   3232:            if (!ApplyModifier_Subst(p, &st))
1.236     rillig   3233:                goto cleanup;
                   3234:            break;
1.108     sjg      3235:        case '?':
1.299     rillig   3236:            if (!ApplyModifier_IfElse(p, &st))
1.236     rillig   3237:                goto cleanup;
                   3238:            break;
1.108     sjg      3239: #ifndef NO_REGEX
                   3240:        case 'C':
1.299     rillig   3241:            if (!ApplyModifier_Regex(p, &st))
1.236     rillig   3242:                goto cleanup;
                   3243:            break;
1.108     sjg      3244: #endif
1.220     christos 3245:        case 'q':
1.108     sjg      3246:        case 'Q':
1.299     rillig   3247:            if (p[1] == st.endc || p[1] == ':') {
1.236     rillig   3248:                st.newStr = VarQuote(st.nstr, st.modifier == 'q');
1.299     rillig   3249:                st.cp = p + 1;
1.236     rillig   3250:                st.termc = *st.cp;
1.108     sjg      3251:                break;
                   3252:            }
                   3253:            goto default_case;
                   3254:        case 'T':
1.299     rillig   3255:            if (p[1] == st.endc || p[1] == ':') {
1.301     rillig   3256:                st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
                   3257:                                        st.nstr, ModifyWord_Tail, NULL);
1.299     rillig   3258:                st.cp = p + 1;
1.236     rillig   3259:                st.termc = *st.cp;
1.108     sjg      3260:                break;
                   3261:            }
                   3262:            goto default_case;
                   3263:        case 'H':
1.299     rillig   3264:            if (p[1] == st.endc || p[1] == ':') {
1.301     rillig   3265:                st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
                   3266:                                        st.nstr, ModifyWord_Head, NULL);
1.299     rillig   3267:                st.cp = p + 1;
1.236     rillig   3268:                st.termc = *st.cp;
1.108     sjg      3269:                break;
                   3270:            }
                   3271:            goto default_case;
                   3272:        case 'E':
1.299     rillig   3273:            if (p[1] == st.endc || p[1] == ':') {
1.301     rillig   3274:                st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
                   3275:                                        st.nstr, ModifyWord_Suffix, NULL);
1.299     rillig   3276:                st.cp = p + 1;
1.236     rillig   3277:                st.termc = *st.cp;
1.108     sjg      3278:                break;
                   3279:            }
                   3280:            goto default_case;
                   3281:        case 'R':
1.299     rillig   3282:            if (p[1] == st.endc || p[1] == ':') {
1.301     rillig   3283:                st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
                   3284:                                        st.nstr, ModifyWord_Root, NULL);
1.299     rillig   3285:                st.cp = p + 1;
1.236     rillig   3286:                st.termc = *st.cp;
1.108     sjg      3287:                break;
                   3288:            }
                   3289:            goto default_case;
1.210     sjg      3290:        case 'r':
1.299     rillig   3291:            if (!ApplyModifier_Range(p, &st))
1.236     rillig   3292:                goto default_case;
                   3293:            break;
1.108     sjg      3294:        case 'O':
1.299     rillig   3295:            if (!ApplyModifier_Order(p, &st))
1.236     rillig   3296:                goto bad_modifier;
                   3297:            break;
1.108     sjg      3298:        case 'u':
1.299     rillig   3299:            if (p[1] == st.endc || p[1] == ':') {
1.236     rillig   3300:                st.newStr = VarUniq(st.nstr);
1.299     rillig   3301:                st.cp = p + 1;
1.236     rillig   3302:                st.termc = *st.cp;
1.108     sjg      3303:                break;
                   3304:            }
                   3305:            goto default_case;
                   3306: #ifdef SUNSHCMD
                   3307:        case 's':
1.299     rillig   3308:            if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) {
1.108     sjg      3309:                const char *emsg;
1.268     rillig   3310:                if (st.eflags & VARE_WANTRES) {
1.236     rillig   3311:                    st.newStr = Cmd_Exec(st.nstr, &emsg);
1.197     sjg      3312:                    if (emsg)
1.236     rillig   3313:                        Error(emsg, st.nstr);
1.197     sjg      3314:                } else
1.236     rillig   3315:                    st.newStr = varNoError;
1.299     rillig   3316:                st.cp = p + 2;
1.236     rillig   3317:                st.termc = *st.cp;
1.108     sjg      3318:                break;
                   3319:            }
                   3320:            goto default_case;
                   3321: #endif
                   3322:        default:
1.142     dsl      3323:        default_case:
1.236     rillig   3324:            {
1.108     sjg      3325: #ifdef SYSVVARSUB
1.299     rillig   3326:                int res = ApplyModifier_SysV(p, &st);
1.236     rillig   3327:                if (res == 'c')
1.108     sjg      3328:                    goto cleanup;
1.236     rillig   3329:                if (res != '=')
1.108     sjg      3330: #endif
                   3331:                {
1.299     rillig   3332:                    Error("Unknown modifier '%c'", *p);
                   3333:                    for (st.cp = p + 1;
1.236     rillig   3334:                         *st.cp != ':' && *st.cp != st.endc && *st.cp != '\0';
                   3335:                         st.cp++)
1.108     sjg      3336:                        continue;
1.236     rillig   3337:                    st.termc = *st.cp;
                   3338:                    st.newStr = var_Error;
1.108     sjg      3339:                }
                   3340:            }
                   3341:        }
                   3342:        if (DEBUG(VAR)) {
1.172     christos 3343:            fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
1.236     rillig   3344:                st.v->name, st.modifier, st.newStr);
1.108     sjg      3345:        }
1.25      christos 3346:
1.236     rillig   3347:        if (st.newStr != st.nstr) {
                   3348:            if (*st.freePtr) {
                   3349:                free(st.nstr);
                   3350:                *st.freePtr = NULL;
1.108     sjg      3351:            }
1.236     rillig   3352:            st.nstr = st.newStr;
                   3353:            if (st.nstr != var_Error && st.nstr != varNoError) {
                   3354:                *st.freePtr = st.nstr;
1.108     sjg      3355:            }
                   3356:        }
1.236     rillig   3357:        if (st.termc == '\0' && st.endc != '\0') {
1.246     rillig   3358:            Error("Unclosed variable specification (expecting '%c') "
                   3359:                "for \"%s\" (value \"%s\") modifier %c",
                   3360:                st.endc, st.v->name, st.nstr, st.modifier);
1.236     rillig   3361:        } else if (st.termc == ':') {
                   3362:            st.cp++;
1.108     sjg      3363:        }
1.299     rillig   3364:        p = st.cp;
1.108     sjg      3365:     }
1.240     rillig   3366: out:
1.299     rillig   3367:     *st.lengthPtr = p - st.start;
1.236     rillig   3368:     return st.nstr;
1.25      christos 3369:
1.240     rillig   3370: bad_modifier:
1.299     rillig   3371:     Error("Bad modifier `:%.*s' for %s",
                   3372:          (int)strcspn(p, ":)}"), p, st.v->name);
1.25      christos 3373:
1.240     rillig   3374: cleanup:
1.236     rillig   3375:     *st.lengthPtr = st.cp - st.start;
1.298     rillig   3376:     if (st.missing_delim != '\0')
1.108     sjg      3377:        Error("Unclosed substitution for %s (%c missing)",
1.298     rillig   3378:              st.v->name, st.missing_delim);
1.236     rillig   3379:     free(*st.freePtr);
                   3380:     *st.freePtr = NULL;
1.231     rillig   3381:     return var_Error;
1.108     sjg      3382: }
1.25      christos 3383:
1.108     sjg      3384: /*-
                   3385:  *-----------------------------------------------------------------------
                   3386:  * Var_Parse --
                   3387:  *     Given the start of a variable invocation, extract the variable
                   3388:  *     name and find its value, then modify it according to the
                   3389:  *     specification.
                   3390:  *
                   3391:  * Input:
                   3392:  *     str             The string to parse
                   3393:  *     ctxt            The context for the variable
1.259     rillig   3394:  *     flags           VARE_UNDEFERR   if undefineds are an error
                   3395:  *                     VARE_WANTRES    if we actually want the result
                   3396:  *                     VARE_ASSIGN     if we are in a := assignment
1.108     sjg      3397:  *     lengthPtr       OUT: The length of the specification
1.121     apb      3398:  *     freePtr         OUT: Non-NULL if caller should free *freePtr
1.108     sjg      3399:  *
                   3400:  * Results:
                   3401:  *     The (possibly-modified) value of the variable or var_Error if the
                   3402:  *     specification is invalid. The length of the specification is
                   3403:  *     placed in *lengthPtr (for invalid specifications, this is just
                   3404:  *     2...?).
1.121     apb      3405:  *     If *freePtr is non-NULL then it's a pointer that the caller
                   3406:  *     should pass to free() to free memory used by the result.
1.108     sjg      3407:  *
                   3408:  * Side Effects:
                   3409:  *     None.
                   3410:  *
                   3411:  *-----------------------------------------------------------------------
                   3412:  */
                   3413: /* coverity[+alloc : arg-*4] */
                   3414: char *
1.259     rillig   3415: Var_Parse(const char *str, GNode *ctxt, VarEvalFlags flags,
1.202     christos 3416:          int *lengthPtr, void **freePtr)
1.108     sjg      3417: {
1.240     rillig   3418:     const char *tstr;          /* Pointer into str */
                   3419:     Var                *v;             /* Variable in invocation */
                   3420:     Boolean     haveModifier;  /* TRUE if have modifiers for the variable */
                   3421:     char        endc;          /* Ending character when variable in parens
1.108     sjg      3422:                                 * or braces */
1.240     rillig   3423:     char        startc;        /* Starting character when variable in parens
1.108     sjg      3424:                                 * or braces */
1.240     rillig   3425:     int                 vlen;          /* Length of variable name */
                   3426:     const char         *start;         /* Points to original start of str */
                   3427:     char       *nstr;          /* New string, used during expansion */
                   3428:     Boolean     dynamic;       /* TRUE if the variable is local and we're
1.108     sjg      3429:                                 * expanding it in a non-local context. This
                   3430:                                 * is done to support dynamic sources. The
                   3431:                                 * result is just the invocation, unaltered */
1.240     rillig   3432:     const char *extramodifiers; /* extra modifiers to apply first */
                   3433:     char        name[2];
1.1       cgd      3434:
1.108     sjg      3435:     *freePtr = NULL;
1.191     dholland 3436:     extramodifiers = NULL;
1.108     sjg      3437:     dynamic = FALSE;
                   3438:     start = str;
1.1       cgd      3439:
1.141     dsl      3440:     startc = str[1];
                   3441:     if (startc != PROPEN && startc != BROPEN) {
1.108     sjg      3442:        /*
                   3443:         * If it's not bounded by braces of some sort, life is much simpler.
                   3444:         * We just need to check for the first character and return the
                   3445:         * value if it exists.
                   3446:         */
1.15      christos 3447:
1.141     dsl      3448:        /* Error out some really stupid names */
                   3449:        if (startc == '\0' || strchr(")}:$", startc)) {
                   3450:            *lengthPtr = 1;
                   3451:            return var_Error;
                   3452:        }
                   3453:        name[0] = startc;
1.108     sjg      3454:        name[1] = '\0';
1.16      christos 3455:
1.108     sjg      3456:        v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1.136     dsl      3457:        if (v == NULL) {
1.108     sjg      3458:            *lengthPtr = 2;
1.1       cgd      3459:
1.108     sjg      3460:            if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
                   3461:                /*
                   3462:                 * If substituting a local variable in a non-local context,
                   3463:                 * assume it's for dynamic source stuff. We have to handle
                   3464:                 * this specially and return the longhand for the variable
                   3465:                 * with the dollar sign escaped so it makes it back to the
                   3466:                 * caller. Only four of the local variables are treated
                   3467:                 * specially as they are the only four that will be set
                   3468:                 * when dynamic sources are expanded.
                   3469:                 */
                   3470:                switch (str[1]) {
1.242     rillig   3471:                case '@':
                   3472:                    return UNCONST("$(.TARGET)");
                   3473:                case '%':
                   3474:                    return UNCONST("$(.MEMBER)");
                   3475:                case '*':
                   3476:                    return UNCONST("$(.PREFIX)");
                   3477:                case '!':
                   3478:                    return UNCONST("$(.ARCHIVE)");
1.108     sjg      3479:                }
                   3480:            }
1.259     rillig   3481:            return (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.108     sjg      3482:        } else {
                   3483:            haveModifier = FALSE;
                   3484:            tstr = &str[1];
                   3485:            endc = str[1];
                   3486:        }
1.123     apb      3487:     } else {
1.240     rillig   3488:        Buffer buf;             /* Holds the variable name */
1.185     sjg      3489:        int depth = 1;
1.1       cgd      3490:
1.108     sjg      3491:        endc = startc == PROPEN ? PRCLOSE : BRCLOSE;
1.146     dsl      3492:        Buf_Init(&buf, 0);
1.1       cgd      3493:
1.108     sjg      3494:        /*
                   3495:         * Skip to the end character or a colon, whichever comes first.
                   3496:         */
1.249     rillig   3497:        for (tstr = str + 2; *tstr != '\0'; tstr++) {
1.240     rillig   3498:            /* Track depth so we can spot parse errors. */
                   3499:            if (*tstr == startc)
1.185     sjg      3500:                depth++;
                   3501:            if (*tstr == endc) {
                   3502:                if (--depth == 0)
                   3503:                    break;
                   3504:            }
1.240     rillig   3505:            if (depth == 1 && *tstr == ':')
1.185     sjg      3506:                break;
1.240     rillig   3507:            /* A variable inside a variable, expand. */
1.108     sjg      3508:            if (*tstr == '$') {
1.127     christos 3509:                int rlen;
1.108     sjg      3510:                void *freeIt;
1.226     rillig   3511:                char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
1.240     rillig   3512:                if (rval != NULL)
1.146     dsl      3513:                    Buf_AddBytes(&buf, strlen(rval), rval);
1.196     christos 3514:                free(freeIt);
1.108     sjg      3515:                tstr += rlen - 1;
1.242     rillig   3516:            } else
1.146     dsl      3517:                Buf_AddByte(&buf, *tstr);
1.108     sjg      3518:        }
                   3519:        if (*tstr == ':') {
                   3520:            haveModifier = TRUE;
1.185     sjg      3521:        } else if (*tstr == endc) {
1.108     sjg      3522:            haveModifier = FALSE;
                   3523:        } else {
                   3524:            /*
                   3525:             * If we never did find the end character, return NULL
                   3526:             * right now, setting the length to be the distance to
                   3527:             * the end of the string, since that's what make does.
                   3528:             */
                   3529:            *lengthPtr = tstr - str;
1.146     dsl      3530:            Buf_Destroy(&buf, TRUE);
1.231     rillig   3531:            return var_Error;
1.108     sjg      3532:        }
1.146     dsl      3533:        str = Buf_GetAll(&buf, &vlen);
1.93      sjg      3534:
1.123     apb      3535:        /*
                   3536:         * At this point, str points into newly allocated memory from
                   3537:         * buf, containing only the name of the variable.
                   3538:         *
                   3539:         * start and tstr point into the const string that was pointed
                   3540:         * to by the original value of the str parameter.  start points
                   3541:         * to the '$' at the beginning of the string, while tstr points
                   3542:         * to the char just after the end of the variable name -- this
                   3543:         * will be '\0', ':', PRCLOSE, or BRCLOSE.
                   3544:         */
                   3545:
1.108     sjg      3546:        v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1.141     dsl      3547:        /*
                   3548:         * Check also for bogus D and F forms of local variables since we're
                   3549:         * in a local context and the name is the right length.
                   3550:         */
1.136     dsl      3551:        if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
1.141     dsl      3552:                (vlen == 2) && (str[1] == 'F' || str[1] == 'D') &&
1.190     dholland 3553:                strchr("@%?*!<>", str[0]) != NULL) {
1.108     sjg      3554:            /*
1.141     dsl      3555:             * Well, it's local -- go look for it.
1.108     sjg      3556:             */
1.141     dsl      3557:            name[0] = *str;
                   3558:            name[1] = '\0';
                   3559:            v = VarFind(name, ctxt, 0);
1.15      christos 3560:
1.141     dsl      3561:            if (v != NULL) {
                   3562:                if (str[1] == 'D') {
1.240     rillig   3563:                    extramodifiers = "H:";
1.242     rillig   3564:                } else { /* F */
1.240     rillig   3565:                    extramodifiers = "T:";
1.1       cgd      3566:                }
                   3567:            }
1.108     sjg      3568:        }
                   3569:
1.136     dsl      3570:        if (v == NULL) {
1.108     sjg      3571:            if (((vlen == 1) ||
1.141     dsl      3572:                 (((vlen == 2) && (str[1] == 'F' || str[1] == 'D')))) &&
1.108     sjg      3573:                ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
                   3574:            {
                   3575:                /*
                   3576:                 * If substituting a local variable in a non-local context,
                   3577:                 * assume it's for dynamic source stuff. We have to handle
                   3578:                 * this specially and return the longhand for the variable
                   3579:                 * with the dollar sign escaped so it makes it back to the
                   3580:                 * caller. Only four of the local variables are treated
                   3581:                 * specially as they are the only four that will be set
                   3582:                 * when dynamic sources are expanded.
                   3583:                 */
                   3584:                switch (*str) {
1.242     rillig   3585:                case '@':
                   3586:                case '%':
                   3587:                case '*':
                   3588:                case '!':
                   3589:                    dynamic = TRUE;
                   3590:                    break;
1.108     sjg      3591:                }
1.240     rillig   3592:            } else if (vlen > 2 && *str == '.' &&
1.108     sjg      3593:                       isupper((unsigned char) str[1]) &&
1.240     rillig   3594:                       (ctxt == VAR_CMD || ctxt == VAR_GLOBAL))
1.108     sjg      3595:            {
1.240     rillig   3596:                int len = vlen - 1;
1.108     sjg      3597:                if ((strncmp(str, ".TARGET", len) == 0) ||
                   3598:                    (strncmp(str, ".ARCHIVE", len) == 0) ||
                   3599:                    (strncmp(str, ".PREFIX", len) == 0) ||
                   3600:                    (strncmp(str, ".MEMBER", len) == 0))
                   3601:                {
                   3602:                    dynamic = TRUE;
                   3603:                }
1.1       cgd      3604:            }
1.15      christos 3605:
1.108     sjg      3606:            if (!haveModifier) {
                   3607:                /*
                   3608:                 * No modifiers -- have specification length so we can return
                   3609:                 * now.
                   3610:                 */
                   3611:                *lengthPtr = tstr - start + 1;
                   3612:                if (dynamic) {
1.134     joerg    3613:                    char *pstr = bmake_strndup(start, *lengthPtr);
1.108     sjg      3614:                    *freePtr = pstr;
1.146     dsl      3615:                    Buf_Destroy(&buf, TRUE);
1.231     rillig   3616:                    return pstr;
1.40      sjg      3617:                } else {
1.146     dsl      3618:                    Buf_Destroy(&buf, TRUE);
1.259     rillig   3619:                    return (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.40      sjg      3620:                }
1.1       cgd      3621:            } else {
1.108     sjg      3622:                /*
                   3623:                 * Still need to get to the end of the variable specification,
                   3624:                 * so kludge up a Var structure for the modifications
                   3625:                 */
1.134     joerg    3626:                v = bmake_malloc(sizeof(Var));
1.108     sjg      3627:                v->name = UNCONST(str);
1.146     dsl      3628:                Buf_Init(&v->val, 1);
1.108     sjg      3629:                v->flags = VAR_JUNK;
1.146     dsl      3630:                Buf_Destroy(&buf, FALSE);
1.1       cgd      3631:            }
1.108     sjg      3632:        } else
1.146     dsl      3633:            Buf_Destroy(&buf, TRUE);
1.108     sjg      3634:     }
                   3635:
1.188     joerg    3636:     if (v->flags & VAR_IN_USE) {
                   3637:        Fatal("Variable %s is recursive.", v->name);
                   3638:        /*NOTREACHED*/
                   3639:     } else {
                   3640:        v->flags |= VAR_IN_USE;
                   3641:     }
                   3642:     /*
                   3643:      * Before doing any modification, we have to make sure the value
                   3644:      * has been fully expanded. If it looks like recursion might be
                   3645:      * necessary (there's a dollar sign somewhere in the variable's value)
                   3646:      * we just call Var_Subst to do any other substitutions that are
                   3647:      * necessary. Note that the value returned by Var_Subst will have
                   3648:      * been dynamically-allocated, so it will need freeing when we
                   3649:      * return.
                   3650:      */
                   3651:     nstr = Buf_GetAll(&v->val, NULL);
1.259     rillig   3652:     if (strchr(nstr, '$') != NULL && (flags & VARE_WANTRES) != 0) {
1.202     christos 3653:        nstr = Var_Subst(NULL, nstr, ctxt, flags);
1.188     joerg    3654:        *freePtr = nstr;
                   3655:     }
1.187     christos 3656:
1.188     joerg    3657:     v->flags &= ~VAR_IN_USE;
1.108     sjg      3658:
1.240     rillig   3659:     if (nstr != NULL && (haveModifier || extramodifiers != NULL)) {
1.191     dholland 3660:        void *extraFree;
1.127     christos 3661:        int used;
1.108     sjg      3662:
1.191     dholland 3663:        extraFree = NULL;
                   3664:        if (extramodifiers != NULL) {
1.240     rillig   3665:            nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
                   3666:                                  v, ctxt, flags, &used, &extraFree);
1.191     dholland 3667:        }
                   3668:
                   3669:        if (haveModifier) {
1.240     rillig   3670:            /* Skip initial colon. */
                   3671:            tstr++;
1.191     dholland 3672:
1.240     rillig   3673:            nstr = ApplyModifiers(nstr, tstr, startc, endc,
                   3674:                                  v, ctxt, flags, &used, freePtr);
                   3675:            tstr += used;
                   3676:            free(extraFree);
1.191     dholland 3677:        } else {
1.240     rillig   3678:            *freePtr = extraFree;
1.191     dholland 3679:        }
1.119     sjg      3680:     }
1.240     rillig   3681:     *lengthPtr = tstr - start + (*tstr ? 1 : 0);
1.15      christos 3682:
1.1       cgd      3683:     if (v->flags & VAR_FROM_ENV) {
1.249     rillig   3684:        Boolean destroy = FALSE;
1.15      christos 3685:
1.146     dsl      3686:        if (nstr != Buf_GetAll(&v->val, NULL)) {
1.1       cgd      3687:            destroy = TRUE;
                   3688:        } else {
                   3689:            /*
                   3690:             * Returning the value unmodified, so tell the caller to free
                   3691:             * the thing.
                   3692:             */
1.104     christos 3693:            *freePtr = nstr;
1.1       cgd      3694:        }
1.105     christos 3695:        VarFreeEnv(v, destroy);
1.1       cgd      3696:     } else if (v->flags & VAR_JUNK) {
                   3697:        /*
1.121     apb      3698:         * Perform any free'ing needed and set *freePtr to NULL so the caller
1.1       cgd      3699:         * doesn't try to free a static pointer.
1.40      sjg      3700:         * If VAR_KEEP is also set then we want to keep str as is.
1.1       cgd      3701:         */
1.58      itojun   3702:        if (!(v->flags & VAR_KEEP)) {
1.40      sjg      3703:            if (*freePtr) {
1.73      christos 3704:                free(nstr);
1.108     sjg      3705:                *freePtr = NULL;
1.40      sjg      3706:            }
                   3707:            if (dynamic) {
1.134     joerg    3708:                nstr = bmake_strndup(start, *lengthPtr);
1.104     christos 3709:                *freePtr = nstr;
1.40      sjg      3710:            } else {
1.259     rillig   3711:                nstr = (flags & VARE_UNDEFERR) ? var_Error : varNoError;
1.40      sjg      3712:            }
1.34      christos 3713:        }
1.146     dsl      3714:        if (nstr != Buf_GetAll(&v->val, NULL))
                   3715:            Buf_Destroy(&v->val, TRUE);
1.98      christos 3716:        free(v->name);
                   3717:        free(v);
1.1       cgd      3718:     }
1.231     rillig   3719:     return nstr;
1.1       cgd      3720: }
                   3721:
                   3722: /*-
                   3723:  *-----------------------------------------------------------------------
                   3724:  * Var_Subst  --
1.250     rillig   3725:  *     Substitute for all variables in the given string in the given context.
1.259     rillig   3726:  *     If flags & VARE_UNDEFERR, Parse_Error will be called when an undefined
1.1       cgd      3727:  *     variable is encountered.
                   3728:  *
1.70      wiz      3729:  * Input:
                   3730:  *     var             Named variable || NULL for all
                   3731:  *     str             the string which to substitute
                   3732:  *     ctxt            the context wherein to find variables
1.259     rillig   3733:  *     flags           VARE_UNDEFERR   if undefineds are an error
                   3734:  *                     VARE_WANTRES    if we actually want the result
                   3735:  *                     VARE_ASSIGN     if we are in a := assignment
1.70      wiz      3736:  *
1.1       cgd      3737:  * Results:
                   3738:  *     The resulting string.
                   3739:  *
                   3740:  * Side Effects:
1.250     rillig   3741:  *     None.
1.1       cgd      3742:  *-----------------------------------------------------------------------
                   3743:  */
                   3744: char *
1.259     rillig   3745: Var_Subst(const char *var, const char *str, GNode *ctxt, VarEvalFlags flags)
1.1       cgd      3746: {
1.240     rillig   3747:     Buffer     buf;            /* Buffer for forming things */
                   3748:     char       *val;           /* Value to substitute for a variable */
                   3749:     int                length;         /* Length of the variable invocation */
                   3750:     Boolean    trailingBslash; /* variable ends in \ */
                   3751:     void       *freeIt = NULL; /* Set if it should be freed */
                   3752:     static Boolean errorReported; /* Set true if an error has already
                   3753:                                 * been reported to prevent a plethora
                   3754:                                 * of messages when recursing */
1.1       cgd      3755:
1.146     dsl      3756:     Buf_Init(&buf, 0);
1.1       cgd      3757:     errorReported = FALSE;
1.96      christos 3758:     trailingBslash = FALSE;
1.1       cgd      3759:
                   3760:     while (*str) {
1.96      christos 3761:        if (*str == '\n' && trailingBslash)
1.146     dsl      3762:            Buf_AddByte(&buf, ' ');
1.48      mycroft  3763:        if (var == NULL && (*str == '$') && (str[1] == '$')) {
1.1       cgd      3764:            /*
                   3765:             * A dollar sign may be escaped either with another dollar sign.
                   3766:             * In such a case, we skip over the escape character and store the
                   3767:             * dollar sign into the buffer directly.
                   3768:             */
1.259     rillig   3769:            if (save_dollars && (flags & VARE_ASSIGN))
1.201     christos 3770:                Buf_AddByte(&buf, *str);
1.1       cgd      3771:            str++;
1.146     dsl      3772:            Buf_AddByte(&buf, *str);
1.1       cgd      3773:            str++;
                   3774:        } else if (*str != '$') {
                   3775:            /*
                   3776:             * Skip as many characters as possible -- either to the end of
                   3777:             * the string or to the next dollar sign (variable invocation).
                   3778:             */
1.249     rillig   3779:            const char *cp;
1.1       cgd      3780:
1.5       cgd      3781:            for (cp = str++; *str != '$' && *str != '\0'; str++)
                   3782:                continue;
1.146     dsl      3783:            Buf_AddBytes(&buf, str - cp, cp);
1.1       cgd      3784:        } else {
1.48      mycroft  3785:            if (var != NULL) {
                   3786:                int expand;
                   3787:                for (;;) {
1.100     christos 3788:                    if (str[1] == '\0') {
                   3789:                        /* A trailing $ is kind of a special case */
1.146     dsl      3790:                        Buf_AddByte(&buf, str[0]);
1.100     christos 3791:                        str++;
                   3792:                        expand = FALSE;
                   3793:                    } else if (str[1] != PROPEN && str[1] != BROPEN) {
1.48      mycroft  3794:                        if (str[1] != *var || strlen(var) > 1) {
1.146     dsl      3795:                            Buf_AddBytes(&buf, 2, str);
1.48      mycroft  3796:                            str += 2;
                   3797:                            expand = FALSE;
1.242     rillig   3798:                        } else
1.48      mycroft  3799:                            expand = TRUE;
                   3800:                        break;
1.240     rillig   3801:                    } else {
1.73      christos 3802:                        const char *p;
1.48      mycroft  3803:
1.242     rillig   3804:                        /* Scan up to the end of the variable name. */
1.48      mycroft  3805:                        for (p = &str[2]; *p &&
1.100     christos 3806:                             *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++)
1.48      mycroft  3807:                            if (*p == '$')
                   3808:                                break;
                   3809:                        /*
                   3810:                         * A variable inside the variable. We cannot expand
                   3811:                         * the external variable yet, so we try again with
                   3812:                         * the nested one
                   3813:                         */
                   3814:                        if (*p == '$') {
1.146     dsl      3815:                            Buf_AddBytes(&buf, p - str, str);
1.48      mycroft  3816:                            str = p;
                   3817:                            continue;
                   3818:                        }
                   3819:
1.127     christos 3820:                        if (strncmp(var, str + 2, p - str - 2) != 0 ||
1.48      mycroft  3821:                            var[p - str - 2] != '\0') {
                   3822:                            /*
                   3823:                             * Not the variable we want to expand, scan
                   3824:                             * until the next variable
                   3825:                             */
1.249     rillig   3826:                            for (; *p != '$' && *p != '\0'; p++)
1.48      mycroft  3827:                                continue;
1.146     dsl      3828:                            Buf_AddBytes(&buf, p - str, str);
1.48      mycroft  3829:                            str = p;
                   3830:                            expand = FALSE;
1.240     rillig   3831:                        } else
1.48      mycroft  3832:                            expand = TRUE;
                   3833:                        break;
                   3834:                    }
                   3835:                }
                   3836:                if (!expand)
                   3837:                    continue;
                   3838:            }
                   3839:
1.202     christos 3840:            val = Var_Parse(str, ctxt, flags, &length, &freeIt);
1.1       cgd      3841:
                   3842:            /*
                   3843:             * When we come down here, val should either point to the
                   3844:             * value of this variable, suitably modified, or be NULL.
                   3845:             * Length should be the total length of the potential
                   3846:             * variable invocation (from $ to end character...)
                   3847:             */
                   3848:            if (val == var_Error || val == varNoError) {
                   3849:                /*
                   3850:                 * If performing old-time variable substitution, skip over
                   3851:                 * the variable and continue with the substitution. Otherwise,
                   3852:                 * store the dollar sign and advance str so we continue with
                   3853:                 * the string...
                   3854:                 */
                   3855:                if (oldVars) {
                   3856:                    str += length;
1.259     rillig   3857:                } else if ((flags & VARE_UNDEFERR) || val == var_Error) {
1.1       cgd      3858:                    /*
                   3859:                     * If variable is undefined, complain and skip the
                   3860:                     * variable. The complaint will stop us from doing anything
                   3861:                     * when the file is parsed.
                   3862:                     */
                   3863:                    if (!errorReported) {
1.231     rillig   3864:                        Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"",
                   3865:                                    length, str);
1.1       cgd      3866:                    }
                   3867:                    str += length;
                   3868:                    errorReported = TRUE;
                   3869:                } else {
1.146     dsl      3870:                    Buf_AddByte(&buf, *str);
1.1       cgd      3871:                    str += 1;
                   3872:                }
                   3873:            } else {
                   3874:                /*
                   3875:                 * We've now got a variable structure to store in. But first,
                   3876:                 * advance the string pointer.
                   3877:                 */
                   3878:                str += length;
1.15      christos 3879:
1.1       cgd      3880:                /*
                   3881:                 * Copy all the characters from the variable value straight
                   3882:                 * into the new string.
                   3883:                 */
1.96      christos 3884:                length = strlen(val);
1.146     dsl      3885:                Buf_AddBytes(&buf, length, val);
1.96      christos 3886:                trailingBslash = length > 0 && val[length - 1] == '\\';
1.104     christos 3887:            }
1.196     christos 3888:            free(freeIt);
                   3889:            freeIt = NULL;
1.1       cgd      3890:        }
                   3891:     }
1.15      christos 3892:
1.168     sjg      3893:     return Buf_DestroyCompact(&buf);
1.1       cgd      3894: }
                   3895:
1.250     rillig   3896: /* Initialize the module. */
1.1       cgd      3897: void
1.70      wiz      3898: Var_Init(void)
1.1       cgd      3899: {
1.184     sjg      3900:     VAR_INTERNAL = Targ_NewGN("Internal");
1.92      christos 3901:     VAR_GLOBAL = Targ_NewGN("Global");
                   3902:     VAR_CMD = Targ_NewGN("Command");
1.6       jtc      3903: }
                   3904:
1.1       cgd      3905:
1.6       jtc      3906: void
1.70      wiz      3907: Var_End(void)
1.6       jtc      3908: {
1.286     sjg      3909:     Var_Stats();
                   3910: }
                   3911:
                   3912: void
                   3913: Var_Stats(void)
                   3914: {
                   3915:     Hash_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL");
1.1       cgd      3916: }
1.15      christos 3917:
1.1       cgd      3918:
                   3919: /****************** PRINT DEBUGGING INFO *****************/
1.36      mycroft  3920: static void
1.241     rillig   3921: VarPrintVar(void *vp, void *data MAKE_ATTR_UNUSED)
1.1       cgd      3922: {
1.242     rillig   3923:     Var *v = (Var *)vp;
1.146     dsl      3924:     fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL));
1.1       cgd      3925: }
                   3926:
                   3927: /*-
                   3928:  *-----------------------------------------------------------------------
                   3929:  * Var_Dump --
                   3930:  *     print all variables in a context
                   3931:  *-----------------------------------------------------------------------
                   3932:  */
1.5       cgd      3933: void
1.70      wiz      3934: Var_Dump(GNode *ctxt)
1.1       cgd      3935: {
1.241     rillig   3936:     Hash_ForEach(&ctxt->context, VarPrintVar, NULL);
1.1       cgd      3937: }

CVSweb <webmaster@jp.NetBSD.org>