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

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

CVSweb <webmaster@jp.NetBSD.org>