[BACK]Return to var.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Annotation of src/usr.bin/make/var.c, Revision 1.50

1.50    ! espie       1: /*     $OpenBSD: var.c,v 1.49 2000/10/13 08:29:21 espie Exp $  */
1.6       millert     2: /*     $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $        */
1.1       deraadt     3:
                      4: /*
1.17      espie       5:  * Copyright (c) 1999 Marc Espie.
                      6:  *
                      7:  * Extensive code modifications for the OpenBSD project.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
                     19:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                     21:  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
                     22:  * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     23:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
                     24:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     28:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
                     31: /*
1.5       millert    32:  * Copyright (c) 1988, 1989, 1990, 1993
                     33:  *     The Regents of the University of California.  All rights reserved.
1.1       deraadt    34:  * Copyright (c) 1989 by Berkeley Softworks
                     35:  * All rights reserved.
                     36:  *
                     37:  * This code is derived from software contributed to Berkeley by
                     38:  * Adam de Boor.
                     39:  *
                     40:  * Redistribution and use in source and binary forms, with or without
                     41:  * modification, are permitted provided that the following conditions
                     42:  * are met:
                     43:  * 1. Redistributions of source code must retain the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer.
                     45:  * 2. Redistributions in binary form must reproduce the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer in the
                     47:  *    documentation and/or other materials provided with the distribution.
                     48:  * 3. All advertising materials mentioning features or use of this software
                     49:  *    must display the following acknowledgement:
                     50:  *     This product includes software developed by the University of
                     51:  *     California, Berkeley and its contributors.
                     52:  * 4. Neither the name of the University nor the names of its contributors
                     53:  *    may be used to endorse or promote products derived from this software
                     54:  *    without specific prior written permission.
                     55:  *
                     56:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     57:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     58:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     59:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     60:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     61:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     62:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     63:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     64:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     65:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     66:  * SUCH DAMAGE.
                     67:  */
                     68:
                     69: /*-
                     70:  * var.c --
                     71:  *     Variable-handling functions
                     72:  *
                     73:  * Interface:
                     74:  *     Var_Set             Set the value of a variable in the given
                     75:  *                         context. The variable is created if it doesn't
                     76:  *                         yet exist. The value and variable name need not
                     77:  *                         be preserved.
                     78:  *
                     79:  *     Var_Append          Append more characters to an existing variable
                     80:  *                         in the given context. The variable needn't
                     81:  *                         exist already -- it will be created if it doesn't.
                     82:  *                         A space is placed between the old value and the
                     83:  *                         new one.
                     84:  *
                     85:  *     Var_Exists          See if a variable exists.
                     86:  *
                     87:  *     Var_Value           Return the value of a variable in a context or
                     88:  *                         NULL if the variable is undefined.
                     89:  *
                     90:  *     Var_Subst           Substitute named variable, or all variables if
                     91:  *                         NULL in a string using
                     92:  *                         the given context as the top-most one. If the
                     93:  *                         third argument is non-zero, Parse_Error is
                     94:  *                         called if any variables are undefined.
                     95:  *
1.50    ! espie      96:  *     Var_SubstVar        Substitute a named variable in a string using
        !            97:  *                         the given context as the top-most one,
        !            98:  *                         accumulating the result into a user-supplied
        !            99:  *                         buffer.
        !           100:  *
1.1       deraadt   101:  *     Var_Parse           Parse a variable expansion from a string and
                    102:  *                         return the result and the number of characters
                    103:  *                         consumed.
                    104:  *
                    105:  *     Var_Delete          Delete a variable in a context.
                    106:  *
                    107:  *     Var_Init            Initialize this module.
                    108:  *
                    109:  * Debugging:
                    110:  *     Var_Dump            Print out all variables defined in the given
                    111:  *                         context.
                    112:  *
                    113:  * XXX: There's a lot of duplication in these functions.
                    114:  */
                    115:
                    116: #include    <ctype.h>
1.6       millert   117: #ifndef MAKE_BOOTSTRAP
1.9       deraadt   118: #include    <sys/types.h>
1.6       millert   119: #include    <regex.h>
                    120: #endif
                    121: #include    <stdlib.h>
1.35      espie     122: #include    <stddef.h>
1.1       deraadt   123: #include    "make.h"
                    124: #include    "buf.h"
1.38      espie     125: #include    "ohash.h"
                    126: #include    "hashconsts.h"
1.43      espie     127: #include    "varmodifiers.h"
1.34      espie     128:
1.48      espie     129: #ifndef lint
                    130: #if 0
                    131: static char sccsid[] = "@(#)var.c      8.3 (Berkeley) 3/19/94";
                    132: #else
                    133: UNUSED
1.50    ! espie     134: static char rcsid[] = "$OpenBSD: var.c,v 1.49 2000/10/13 08:29:21 espie Exp $";
1.48      espie     135: #endif
                    136: #endif /* not lint */
                    137:
1.37      espie     138: static SymTable *CTXT_GLOBAL, *CTXT_CMD, *CTXT_ENV;
                    139:
1.34      espie     140: static char *varnames[] = {
                    141:     TARGET,
                    142:     OODATE,
                    143:     ALLSRC,
                    144:     IMPSRC,
                    145:     PREFIX,
                    146:     ARCHIVE,
                    147:     MEMBER };
                    148:
1.1       deraadt   149: /*
                    150:  * This is a harmless return value for Var_Parse that can be used by Var_Subst
                    151:  * to determine if there was an error in parsing -- easier than returning
                    152:  * a flag, as things outside this module don't give a hoot.
                    153:  */
                    154: char   var_Error[] = "";
                    155:
                    156: /*
                    157:  * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
                    158:  * set false. Why not just use a constant? Well, gcc likes to condense
                    159:  * identical string instances...
                    160:  */
                    161: static char    varNoError[] = "";
                    162:
                    163: /*
                    164:  * Internally, variables are contained in four different contexts.
                    165:  *     1) the environment. They may not be changed. If an environment
                    166:  *         variable is appended-to, the result is placed in the global
                    167:  *         context.
                    168:  *     2) the global context. Variables set in the Makefile are located in
                    169:  *         the global context. It is the penultimate context searched when
                    170:  *         substituting.
                    171:  *     3) the command-line context. All variables set on the command line
                    172:  *        are placed in this context. They are UNALTERABLE once placed here.
                    173:  *     4) the local context. Each target has associated with it a context
                    174:  *        list. On this list are located the structures describing such
                    175:  *        local variables as $(@) and $(*)
                    176:  * The four contexts are searched in the reverse order from which they are
                    177:  * listed.
                    178:  */
1.37      espie     179: GSymT          *VAR_GLOBAL;    /* variables from the makefile */
                    180: GSymT          *VAR_CMD;       /* variables defined on the command-line */
                    181: static GSymT   *VAR_ENV;       /* variables read from env */
1.1       deraadt   182:
1.39      espie     183: #define FIND_MINE      0x1   /* look in CTXT_CMD and CTXT_GLOBAL */
                    184: #define FIND_ENV       0x2   /* look in the environment */
1.1       deraadt   185:
1.37      espie     186: typedef struct Var_ {
1.23      espie     187:     BUFFER       val;          /* its value */
1.1       deraadt   188:     int                  flags;        /* miscellaneous status flags */
                    189: #define VAR_IN_USE     1           /* Variable's value currently being used.
                    190:                                     * Used to avoid recursion */
                    191: #define VAR_JUNK       4           /* Variable is a junk variable that
                    192:                                     * should be destroyed when done with
                    193:                                     * it. Used by Var_Parse for undefined,
                    194:                                     * modified variables */
1.38      espie     195:     char          name[1];     /* the variable's name */
1.1       deraadt   196: }  Var;
                    197:
1.38      espie     198: static struct hash_info var_info = {
                    199:        offsetof(Var, name),
                    200:     NULL, hash_alloc, hash_free, element_alloc };
                    201: static int quick_lookup __P((const char *, const char **, u_int32_t *));
1.23      espie     202: #define VarValue(v)    Buf_Retrieve(&((v)->val))
1.39      espie     203: static Var *varfind __P((const char *, const char *, SymTable *, int, int, u_int32_t));
                    204: static Var *VarFind_interval __P((const char *, const char *, SymTable *, int));
                    205: #define VarFind(n, ctxt, flags)        VarFind_interval(n, NULL, ctxt, flags)
                    206: static Var *VarAdd __P((const char *, const char *, GSymT *));
1.32      espie     207: static void VarDelete __P((void *));
                    208: static void VarPrintVar __P((void *));
1.38      espie     209: static const char *context_name __P((GSymT *));
1.39      espie     210: static Var *new_var __P((const char *, const char *));
                    211: static Var *getvar __P((GSymT *, const char *, const char *, u_int32_t));
1.45      espie     212: static Var *var_name_with_dollar __P((char *, char **, SymTable *, Boolean, char));
1.37      espie     213:
                    214: void
                    215: SymTable_Init(ctxt)
                    216:     SymTable   *ctxt;
                    217: {
                    218:     static SymTable sym_template;
                    219:     memcpy(ctxt, &sym_template, sizeof(*ctxt));
                    220: }
                    221:
                    222: void
                    223: SymTable_Destroy(ctxt)
                    224:     SymTable   *ctxt;
                    225: {
                    226:     int i;
                    227:
                    228:     for (i = 0; i < LOCAL_SIZE; i++)
                    229:        if (ctxt->locals[i] != NULL)
                    230:            VarDelete(ctxt->locals[i]);
                    231: }
                    232:
1.38      espie     233: static int
                    234: quick_lookup(name, end, pk)
                    235:     const char *name;
                    236:     const char **end;
                    237:     u_int32_t *pk;
                    238: {
                    239:     size_t len;
                    240:
                    241:     *pk = hash_interval(name, end);
                    242:     len = *end - name;
                    243:        /* substitute short version for long local name */
                    244:     switch (*pk % MAGICSLOTS) {                    /* MAGICSLOTS should be the    */
                    245:     case K_LONGALLSRC % MAGICSLOTS:        /* smallest constant yielding  */
                    246:                                            /* distinct case values        */
                    247:        if (*pk == K_LONGALLSRC && strncmp(name, LONGALLSRC, len) == 0 &&
                    248:            len == strlen(LONGALLSRC))
                    249:            return ALLSRC_INDEX;
                    250:        break;
                    251:     case K_LONGARCHIVE % MAGICSLOTS:
                    252:        if (*pk == K_LONGARCHIVE && strncmp(name, LONGARCHIVE, len) == 0 &&
                    253:            len == strlen(LONGARCHIVE))
                    254:            return ARCHIVE_INDEX;
                    255:        break;
                    256:     case K_LONGIMPSRC % MAGICSLOTS:
                    257:        if (*pk == K_LONGIMPSRC && strncmp(name, LONGIMPSRC, len) == 0 &&
                    258:            len == strlen(LONGIMPSRC))
                    259:            return IMPSRC_INDEX;
                    260:        break;
                    261:     case K_LONGMEMBER % MAGICSLOTS:
                    262:        if (*pk == K_LONGMEMBER && strncmp(name, LONGMEMBER, len) == 0 &&
                    263:            len == strlen(LONGMEMBER))
                    264:            return MEMBER_INDEX;
                    265:        break;
                    266:     case K_LONGOODATE % MAGICSLOTS:
                    267:        if (*pk == K_LONGOODATE && strncmp(name, LONGOODATE, len) == 0 &&
                    268:            len == strlen(LONGOODATE))
                    269:            return OODATE_INDEX;
                    270:        break;
                    271:     case K_LONGPREFIX % MAGICSLOTS:
                    272:        if (*pk == K_LONGPREFIX && strncmp(name, LONGPREFIX, len) == 0 &&
                    273:            len == strlen(LONGPREFIX))
                    274:            return PREFIX_INDEX;
                    275:        break;
                    276:     case K_LONGTARGET % MAGICSLOTS:
                    277:        if (*pk == K_LONGTARGET && strncmp(name, LONGTARGET, len) == 0 &&
                    278:            len == strlen(LONGTARGET))
                    279:            return TARGET_INDEX;
                    280:        break;
                    281:     case K_TARGET % MAGICSLOTS:
                    282:        if (name[0] == TARGET[0] && len == 1)
                    283:            return TARGET_INDEX;
                    284:        break;
                    285:     case K_OODATE % MAGICSLOTS:
                    286:        if (name[0] == OODATE[0] && len == 1)
                    287:            return OODATE_INDEX;
                    288:        break;
                    289:     case K_ALLSRC % MAGICSLOTS:
                    290:        if (name[0] == ALLSRC[0] && len == 1)
                    291:            return ALLSRC_INDEX;
                    292:        break;
                    293:     case K_IMPSRC % MAGICSLOTS:
                    294:        if (name[0] == IMPSRC[0] && len == 1)
                    295:            return IMPSRC_INDEX;
                    296:        break;
                    297:     case K_PREFIX % MAGICSLOTS:
                    298:        if (name[0] == PREFIX[0] && len == 1)
                    299:            return PREFIX_INDEX;
                    300:        break;
                    301:     case K_ARCHIVE % MAGICSLOTS:
                    302:        if (name[0] == ARCHIVE[0] && len == 1)
                    303:            return ARCHIVE_INDEX;
                    304:        break;
                    305:     case K_MEMBER % MAGICSLOTS:
                    306:        if (name[0] == MEMBER[0] && len == 1)
                    307:            return MEMBER_INDEX;
                    308:        break;
                    309:     default:
                    310:        break;
                    311:     }
                    312:     return -1;
                    313: }
1.37      espie     314:
                    315: void
                    316: Varq_Set(idx, val, gn)
                    317:     int        idx;
1.48      espie     318:     const char         *val;
1.37      espie     319:     GNode      *gn;
                    320: {
1.38      espie     321:     /* We only look for a variable in the given context since anything set
                    322:      * here will override anything in a lower context, so there's not much
                    323:      * point in searching them all just to save a bit of memory...  */
1.37      espie     324:     Var *v = gn->context.locals[idx];
                    325:
                    326:     if (v == NULL) {
                    327:        v = new_var(varnames[idx], val);
                    328:        v->flags = 0;
                    329:        gn->context.locals[idx] = v;
                    330:     } else {
                    331:        Buf_Reset(&(v->val));
                    332:        Buf_AddString(&(v->val), val);
                    333:     }
                    334:     if (DEBUG(VAR))
                    335:        printf("%s:%s = %s\n", gn->name, varnames[idx], val);
                    336: }
                    337:
                    338: void
                    339: Varq_Append(idx, val, gn)
                    340:     int                idx;
1.48      espie     341:     const char *val;
1.37      espie     342:     GNode      *gn;
                    343: {
1.48      espie     344:     Var        *v = gn->context.locals[idx];
1.37      espie     345:
                    346:     if (v == NULL) {
                    347:        v = new_var(varnames[idx], val);
                    348:        v->flags = 0;
                    349:        gn->context.locals[idx] = v;
                    350:     } else {
                    351:        Buf_AddSpace(&(v->val));
                    352:        Buf_AddString(&(v->val), val);
                    353:     }
                    354:     if (DEBUG(VAR))
                    355:        printf("%s:%s = %s\n", gn->name, varnames[idx], VarValue(v));
                    356: }
                    357:
                    358: char *
                    359: Varq_Value(idx, gn)
                    360:     int                idx;
                    361:     GNode      *gn;
                    362: {
                    363:     Var *v = gn->context.locals[idx];
                    364:
                    365:     if (v != NULL)
                    366:        return VarValue(v);
                    367:     else
                    368:        return NULL;
                    369: }
                    370:
                    371: Boolean
                    372: Varq_Exists(idx, gn)
                    373:     int                idx;
                    374:     GNode      *gn;
                    375: {
                    376:     return gn->context.locals[idx] != NULL;
                    377: }
1.1       deraadt   378:
1.35      espie     379:
1.38      espie     380: static const char *
1.35      espie     381: context_name(ctxt)
1.37      espie     382:     GSymT *ctxt;
1.35      espie     383: {
                    384:     if (ctxt == VAR_GLOBAL)
                    385:        return "Global";
1.37      espie     386:     else if (ctxt == VAR_CMD)
1.35      espie     387:        return "Command";
1.37      espie     388:     else
1.35      espie     389:        return "Environment";
                    390: }
                    391:
1.37      espie     392: /* Create a variable, to pass to VarAdd.  */
                    393: static Var *
                    394: new_var(name, val)
1.39      espie     395:     const char *name;
                    396:     const char *val;
1.37      espie     397: {
                    398:     Var *v;
1.38      espie     399:     const char *end = NULL;
1.37      espie     400:
1.38      espie     401:     v = hash_create_entry(&var_info, name, &end);
1.37      espie     402:
                    403:     if (val != NULL) {
                    404:        size_t len = strlen(val);
                    405:        Buf_Init(&(v->val), len+1);
                    406:        Buf_AddChars(&(v->val), len, val);
                    407:     } else
                    408:        Buf_Init(&(v->val), 1);
                    409:
                    410:     return v;
                    411: }
                    412:
1.38      espie     413: static Var *
                    414: getvar(ctxt, name, end, k)
                    415:     GSymT      *ctxt;
1.39      espie     416:     const char         *name;
1.38      espie     417:     const char *end;
                    418:     u_int32_t  k;
1.1       deraadt   419: {
1.38      espie     420:     return hash_find(ctxt, hash_lookup_interval(ctxt, name, end, k));
1.37      espie     421: }
                    422:
1.1       deraadt   423: /*-
                    424:  *-----------------------------------------------------------------------
1.39      espie     425:  * VarFind_interval --
1.1       deraadt   426:  *     Find the given variable in the given context and any other contexts
1.39      espie     427:  *     indicated.  if end is NULL, name is a string, otherwise, only
                    428:  *      the interval name - end  is concerned.
1.1       deraadt   429:  *
                    430:  * Results:
                    431:  *     A pointer to the structure describing the desired variable or
1.26      espie     432:  *     NULL if the variable does not exist.
1.1       deraadt   433:  *
                    434:  * Side Effects:
1.17      espie     435:  *     Caches env variables in the VAR_ENV context.
1.1       deraadt   436:  *-----------------------------------------------------------------------
                    437:  */
                    438: static Var *
1.39      espie     439: VarFind_interval(name, end, ctxt, flags)
                    440:     const char          *name; /* name to find */
                    441:     const char         *end;   /* end of name */
1.35      espie     442:     SymTable           *ctxt;  /* context in which to find it */
1.39      espie     443:     int                flags;  /* FIND_MINE set means to look in the
                    444:                                 * CTXT_GLOBAL and CTXT_CMD contexts also.
1.1       deraadt   445:                                 * FIND_ENV set means to look in the
1.39      espie     446:                                 * environment */
1.1       deraadt   447: {
1.38      espie     448:     int                idx;
                    449:     u_int32_t          k;
                    450:
                    451:     idx = quick_lookup(name, &end, &k);
1.39      espie     452:     return varfind(name, end, ctxt, flags, idx, k);
                    453: }
                    454:
                    455: static Var *
                    456: varfind(name, end, ctxt, flags, idx, k)
                    457:     const char         *name;
                    458:     const char         *end;
                    459:     SymTable           *ctxt;
                    460:     int                        flags;
                    461:     int                        idx;
                    462:     u_int32_t          k;
                    463: {
                    464:     Var                        *v;
1.1       deraadt   465:
                    466:     /*
                    467:      * First look for the variable in the given context. If it's not there,
                    468:      * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
                    469:      * depending on the FIND_* flags in 'flags'
                    470:      */
1.37      espie     471:     if (ctxt == NULL)
                    472:        v = NULL;
                    473:     else if (ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD || ctxt == CTXT_ENV)
1.38      espie     474:        v = getvar((GSymT *)ctxt, name, end, k);
1.37      espie     475:     else {
1.38      espie     476:        if (idx == -1)
                    477:            v = NULL;
                    478:        else
                    479:            v = ctxt->locals[idx];
1.37      espie     480:     }
                    481:     if (v != NULL)
                    482:        return v;
                    483:
1.39      espie     484:     if ((flags & FIND_MINE) && ctxt != CTXT_CMD)
1.38      espie     485:        v = getvar(VAR_CMD, name, end, k);
1.37      espie     486:     if (v != NULL)
                    487:        return v;
                    488:
1.39      espie     489:     if (!checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL)
1.38      espie     490:        v = getvar(VAR_GLOBAL, name, end, k);
1.37      espie     491:     if (v != NULL)
                    492:        return v;
                    493:
                    494:     if ((flags & FIND_ENV)) {
                    495:        char *env;
1.42      espie     496:        char *n;
1.37      espie     497:
1.38      espie     498:        v = getvar(VAR_ENV, name, end, k);
1.37      espie     499:        if (v != NULL)
                    500:            return v;
1.1       deraadt   501:
1.42      espie     502:        /* getenv requires a null-terminated name */
                    503:        n = interval_dup(name, end);
                    504:        env = getenv(n);
                    505:        free(n);
                    506:        if (env != NULL)
1.37      espie     507:            return VarAdd(name, env, VAR_ENV);
                    508:     }
1.17      espie     509:
1.39      espie     510:     if (checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL)
1.38      espie     511:        v = getvar(VAR_GLOBAL, name, end, k);
1.37      espie     512:     return v;
1.1       deraadt   513: }
                    514:
                    515: /*-
                    516:  *-----------------------------------------------------------------------
                    517:  * VarAdd  --
                    518:  *     Add a new variable of name name and value val to the given context
                    519:  *
                    520:  * Results:
1.17      espie     521:  *     The added variable
1.1       deraadt   522:  *
                    523:  * Side Effects:
1.48      espie     524:  *     The new variable is placed in the given context.
1.1       deraadt   525:  *     The name and val arguments are duplicated so they may
                    526:  *     safely be freed.
                    527:  *-----------------------------------------------------------------------
                    528:  */
1.17      espie     529: static Var *
                    530: VarAdd(name, val, ctxt)
1.39      espie     531:     const char *name;  /* name of variable to add */
                    532:     const char *val;   /* value to set it to */
1.37      espie     533:     GSymT      *ctxt;  /* context in which to set it */
1.1       deraadt   534: {
1.38      espie     535:     Var        *v;
                    536:     const char         *end = NULL;
                    537:     int        idx;
                    538:     u_int32_t  k;
1.1       deraadt   539:
1.37      espie     540:     v = new_var(name, val);
1.1       deraadt   541:
                    542:     v->flags = 0;
                    543:
1.38      espie     544:     idx = quick_lookup(name, &end, &k);
                    545:
1.48      espie     546:     if (idx != -1)
1.38      espie     547:        Parse_Error(PARSE_FATAL, "Trying to set dynamic variable %s",
                    548:            v->name);
1.48      espie     549:     else
1.38      espie     550:        hash_insert(ctxt, hash_lookup_interval(ctxt, name, end, k), v);
1.17      espie     551:     return v;
1.1       deraadt   552: }
                    553:
                    554:
                    555: /*-
                    556:  *-----------------------------------------------------------------------
                    557:  * VarDelete  --
                    558:  *     Delete a variable and all the space associated with it.
                    559:  *-----------------------------------------------------------------------
                    560:  */
                    561: static void
                    562: VarDelete(vp)
1.48      espie     563:     void       *vp;
1.1       deraadt   564: {
1.48      espie     565:     Var        *v = (Var *) vp;
                    566:
1.23      espie     567:     Buf_Destroy(&(v->val));
                    568:     free(v);
1.1       deraadt   569: }
                    570:
                    571:
                    572:
                    573: /*-
                    574:  *-----------------------------------------------------------------------
                    575:  * Var_Delete --
                    576:  *     Remove a variable from a context.
                    577:  *
                    578:  * Side Effects:
                    579:  *     The Var structure is removed and freed.
                    580:  *-----------------------------------------------------------------------
                    581:  */
                    582: void
                    583: Var_Delete(name, ctxt)
1.48      espie     584:     const char *name;
                    585:     GSymT      *ctxt;
1.1       deraadt   586: {
1.48      espie     587:     Var        *v;
                    588:     u_int32_t  k;
                    589:     const char         *end = NULL;
1.1       deraadt   590:
1.37      espie     591:     if (DEBUG(VAR))
1.35      espie     592:        printf("%s:delete %s\n", context_name(ctxt), name);
1.38      espie     593:     (void)quick_lookup(name, &end, &k);
                    594:     v = hash_remove(ctxt, hash_lookup_interval(ctxt, name, end, k));
1.37      espie     595:
1.38      espie     596:     if (v != NULL)
1.30      espie     597:        VarDelete(v);
1.1       deraadt   598: }
                    599:
                    600: /*-
                    601:  *-----------------------------------------------------------------------
                    602:  * Var_Set --
                    603:  *     Set the variable name to the value val in the given context.
                    604:  *
                    605:  * Side Effects:
                    606:  *     If the variable doesn't yet exist, a new record is created for it.
                    607:  *     Else the old value is freed and the new one stuck in its place
                    608:  *
                    609:  * Notes:
                    610:  *     The variable is searched for only in its context before being
                    611:  *     created in that context. I.e. if the context is VAR_GLOBAL,
                    612:  *     only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
                    613:  *     VAR_CMD->context is searched. This is done to avoid the literally
                    614:  *     thousands of unnecessary strcmp's that used to be done to
                    615:  *     set, say, $(@) or $(<).
                    616:  *-----------------------------------------------------------------------
                    617:  */
                    618: void
1.35      espie     619: Var_Set(name, val, ctxt)
1.48      espie     620:     const char *name;  /* name of variable to set */
                    621:     const char *val;   /* value to give to the variable */
1.37      espie     622:     GSymT       *ctxt; /* context in which to set it */
1.1       deraadt   623: {
1.48      espie     624:     Var   *v;
1.1       deraadt   625:
                    626:     /*
                    627:      * We only look for a variable in the given context since anything set
                    628:      * here will override anything in a lower context, so there's not much
                    629:      * point in searching them all just to save a bit of memory...
                    630:      */
1.37      espie     631:     v = VarFind(name, (SymTable *)ctxt, 0);
1.38      espie     632:     if (v == NULL)
1.17      espie     633:        (void)VarAdd(name, val, ctxt);
1.38      espie     634:     else {
1.23      espie     635:        Buf_Reset(&(v->val));
                    636:        Buf_AddString(&(v->val), val);
1.1       deraadt   637:     }
1.37      espie     638:     if (DEBUG(VAR))
                    639:        printf("%s:%s = %s\n", context_name(ctxt), name, val);
1.1       deraadt   640:     /*
                    641:      * Any variables given on the command line are automatically exported
1.17      espie     642:      * to the environment (as per POSIX standard).
                    643:      * We put them into the env cache directly.
                    644:      * (Note that additions to VAR_CMD occur very early, so VAR_ENV is
                    645:      * actually empty at this point).
1.1       deraadt   646:      */
                    647:     if (ctxt == VAR_CMD) {
1.49      espie     648:        esetenv(name, val);
1.17      espie     649:        (void)VarAdd(name, val, VAR_ENV);
1.1       deraadt   650:     }
                    651: }
                    652:
                    653: /*-
                    654:  *-----------------------------------------------------------------------
                    655:  * Var_Append --
                    656:  *     The variable of the given name has the given value appended to it in
                    657:  *     the given context.
                    658:  *
                    659:  * Side Effects:
                    660:  *     If the variable doesn't exist, it is created. Else the strings
                    661:  *     are concatenated (with a space in between).
                    662:  *
                    663:  * Notes:
                    664:  *     Only if the variable is being sought in the global context is the
                    665:  *     environment searched.
                    666:  *     XXX: Knows its calling circumstances in that if called with ctxt
                    667:  *     an actual target, it will only search that context since only
                    668:  *     a local variable could be being appended to. This is actually
                    669:  *     a big win and must be tolerated.
                    670:  *-----------------------------------------------------------------------
                    671:  */
                    672: void
1.35      espie     673: Var_Append(name, val, ctxt)
1.48      espie     674:     const char *name;  /* Name of variable to modify */
                    675:     const char *val;   /* String to append to it */
1.37      espie     676:     GSymT      *ctxt;  /* Context in which this should occur */
1.1       deraadt   677: {
1.48      espie     678:     Var        *v;
1.1       deraadt   679:
1.37      espie     680:     v = VarFind(name, (SymTable *)ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
1.1       deraadt   681:
1.26      espie     682:     if (v == NULL) {
1.47      espie     683:        v = VarAdd(name, val, ctxt);
1.1       deraadt   684:     } else {
1.23      espie     685:        Buf_AddSpace(&(v->val));
                    686:        Buf_AddString(&(v->val), val);
1.1       deraadt   687:     }
1.37      espie     688:     if (DEBUG(VAR))
                    689:        printf("%s:%s = %s\n", context_name(ctxt), name, VarValue(v));
1.1       deraadt   690: }
                    691:
                    692: /*-
                    693:  *-----------------------------------------------------------------------
                    694:  * Var_Exists --
                    695:  *     See if the given variable exists.
                    696:  *
                    697:  * Results:
                    698:  *     TRUE if it does, FALSE if it doesn't
                    699:  *-----------------------------------------------------------------------
                    700:  */
                    701: Boolean
                    702: Var_Exists(name, ctxt)
1.48      espie     703:     const char *name;          /* Variable to find */
1.37      espie     704:     GSymT      *ctxt;          /* Context in which to start search */
1.1       deraadt   705: {
1.48      espie     706:     Var                *v;
1.1       deraadt   707:
1.39      espie     708:     v = VarFind(name, (SymTable *)ctxt, FIND_MINE|FIND_ENV);
1.1       deraadt   709:
1.26      espie     710:     if (v == NULL)
1.17      espie     711:        return FALSE;
                    712:     else
                    713:        return TRUE;
1.1       deraadt   714: }
                    715:
                    716: /*-
                    717:  *-----------------------------------------------------------------------
                    718:  * Var_Value --
                    719:  *     Return the value of the named variable in the given context
                    720:  *
                    721:  * Results:
                    722:  *     The value if the variable exists, NULL if it doesn't
                    723:  *-----------------------------------------------------------------------
                    724:  */
                    725: char *
1.18      espie     726: Var_Value(name, ctxt)
1.48      espie     727:     const char *name;  /* name to find */
1.37      espie     728:     GSymT      *ctxt;  /* context in which to search for it */
1.1       deraadt   729: {
1.48      espie     730:     Var                *v;
1.1       deraadt   731:
1.39      espie     732:     v = VarFind(name, (SymTable *)ctxt, FIND_ENV | FIND_MINE);
1.26      espie     733:     if (v != NULL)
1.23      espie     734:        return VarValue(v);
1.21      espie     735:     else
1.17      espie     736:        return NULL;
1.1       deraadt   737: }
                    738:
1.45      espie     739: /*
                    740:  *-----------------------------------------------------------------------
                    741:  * v = var_name_with_dollar(str, &pos, ctxt, err, endc)
                    742:  *   handle variable name that contains a dollar
                    743:  *   str points to the first letter of the variable name,
                    744:  *   &pos to the current position in the name (first dollar at invocation,
                    745:  *   end of name specification at return).
                    746:  *   returns the corresponding variable.
                    747:  *-----------------------------------------------------------------------
                    748:  */
                    749: static Var *
                    750: var_name_with_dollar(str, pos, ctxt, err, endc)
1.48      espie     751:     char       *str;           /* First dollar in variable name */
                    752:     char       **pos;          /* Current position in variable spec */
1.45      espie     753:     SymTable           *ctxt;          /* The context for the variable */
                    754:     Boolean    err;            /* TRUE if undefined variables are an error */
                    755:     char       endc;           /* End character for spec */
                    756: {
1.48      espie     757:     BUFFER     buf;            /* Store the variable name */
                    758:     size_t     sublen;         /* Deal with recursive expansions */
                    759:     Boolean    subfree;
                    760:     char       *n;             /* Sub name */
                    761:     Var        *v;
1.45      espie     762:
                    763:     Buf_Init(&buf, MAKE_BSIZE);
                    764:
1.48      espie     765:     for (;;) {
1.45      espie     766:        Buf_AddInterval(&buf, str, *pos);
                    767:        n = Var_Parse(*pos, ctxt, err, &sublen, &subfree);
                    768:        if (n != NULL)
                    769:            Buf_AddString(&buf, n);
                    770:        if (subfree)
                    771:            free(n);
                    772:        *pos += sublen;
                    773:        str = *pos;
                    774:        for (; **pos != '$'; (*pos)++) {
                    775:            if (**pos == '\0' || **pos == endc || **pos == ':') {
                    776:                v = VarFind(Buf_Retrieve(&buf), ctxt, FIND_ENV | FIND_MINE);
                    777:                Buf_Destroy(&buf);
                    778:                return v;
                    779:            }
                    780:        }
                    781:     }
                    782: }
                    783:
1.1       deraadt   784: /*-
                    785:  *-----------------------------------------------------------------------
                    786:  * Var_Parse --
                    787:  *     Given the start of a variable invocation, extract the variable
                    788:  *     name and find its value, then modify it according to the
                    789:  *     specification.
                    790:  *
                    791:  * Results:
                    792:  *     The (possibly-modified) value of the variable or var_Error if the
                    793:  *     specification is invalid. The length of the specification is
                    794:  *     placed in *lengthPtr (for invalid specifications, this is just
                    795:  *     2...?).
                    796:  *     A Boolean in *freePtr telling whether the returned string should
                    797:  *     be freed by the caller.
                    798:  *-----------------------------------------------------------------------
                    799:  */
                    800: char *
1.35      espie     801: Var_Parse(str, ctxt, err, lengthPtr, freePtr)
1.44      espie     802:     char       *str;           /* The string to parse */
                    803:     SymTable           *ctxt;          /* The context for the variable */
                    804:     Boolean    err;            /* TRUE if undefined variables are an error */
                    805:     size_t     *lengthPtr;     /* OUT: The length of the specification */
                    806:     Boolean    *freePtr;       /* OUT: TRUE if caller should free result */
                    807: {
                    808:     char       *tstr;          /* Pointer into str */
                    809:     Var                *v;             /* Variable in invocation */
                    810:     char       endc;           /* Ending character when variable in parens
1.1       deraadt   811:                                 * or braces */
1.44      espie     812:     char       *start;
                    813:     char       *val;           /* Variable value  */
                    814:     u_int32_t  k;
                    815:     int                idx;
1.5       millert   816:
1.1       deraadt   817:     *freePtr = FALSE;
1.44      espie     818:     start = str++;
1.5       millert   819:
1.44      espie     820:     val = NULL;
1.45      espie     821:     v = NULL;
                    822:     idx = 0;
1.44      espie     823:
                    824:     if (*str != '(' && *str != '{') {
                    825:        tstr = str + 1;
                    826:        *lengthPtr = 2;
                    827:        endc = '\0';
1.1       deraadt   828:     } else {
1.44      espie     829:        endc = *str == '(' ? ')' : '}';
                    830:        str++;
1.5       millert   831:
1.44      espie     832:        /* Find eventual modifiers in the variable */
1.45      espie     833:        for (tstr = str; *tstr != ':'; tstr++) {
                    834:            if (*tstr == '$') {
                    835:                v = var_name_with_dollar(str, &tstr, ctxt, err, endc);
                    836:                if (*tstr == '\0' || *tstr == endc)
                    837:                    endc = '\0';
                    838:                break;
                    839:            } else if (*tstr == '\0' || *tstr == endc) {
1.44      espie     840:                endc = '\0';
                    841:                break;
1.1       deraadt   842:            }
1.45      espie     843:        }
1.44      espie     844:        *lengthPtr = tstr+1 - start;
                    845:     }
1.5       millert   846:
1.45      espie     847:     if (v == NULL) {
                    848:        idx = quick_lookup(str, &tstr, &k);
                    849:        v = varfind(str, tstr, ctxt, FIND_ENV | FIND_MINE, idx, k);
                    850:     }
1.44      espie     851:     if (v == NULL) {
                    852:        /* Find out about D and F forms of local variables. */
                    853:        if (idx == -1 && tstr == str+2 && (str[1] == 'D' || str[1] == 'F')) {
                    854:            switch (*str) {
                    855:            case '@':
                    856:                idx = TARGET_INDEX;
                    857:                break;
                    858:            case '!':
                    859:                idx = ARCHIVE_INDEX;
                    860:                break;
                    861:            case '*':
                    862:                idx = PREFIX_INDEX;
                    863:                break;
                    864:            case '%':
                    865:                idx = MEMBER_INDEX;
                    866:                break;
                    867:            default:
                    868:                break;
1.1       deraadt   869:            }
1.44      espie     870:            /* This is a DF form, check if we can expand it now.  */
                    871:            if (idx != -1 && ctxt != NULL && ctxt != CTXT_GLOBAL) {
                    872:                v = varfind(str, str+1, ctxt, 0, idx, 0);
                    873:                /* No need for nested expansion or anything, as we're
                    874:                 * the only one who sets these things and we sure don't
                    875:                 * do nested invocations in them...  */
                    876:                if (v != NULL) {
                    877:                    val = VarValue(v);
                    878:                    if (str[1] == 'D')
                    879:                        val = Var_GetHead(val);
                    880:                    else
                    881:                        val = Var_GetTail(val);
1.1       deraadt   882:                    *freePtr = TRUE;
1.44      espie     883:                }
1.1       deraadt   884:            }
                    885:        }
1.44      espie     886:     } else {
                    887:        if (v->flags & VAR_IN_USE)
                    888:            Fatal("Variable %s is recursive.", v->name);
                    889:            /*NOTREACHED*/
                    890:        else
                    891:            v->flags |= VAR_IN_USE;
                    892:        /* Before doing any modification, we have to make sure the value
                    893:         * has been fully expanded. If it looks like recursion might be
                    894:         * necessary (there's a dollar sign somewhere in the variable's value)
                    895:         * we just call Var_Subst to do any other substitutions that are
                    896:         * necessary. Note that the value returned by Var_Subst will have
                    897:         * been dynamically-allocated, so it will need freeing when we
                    898:         * return.  */
                    899:        val = VarValue(v);
                    900:        if (strchr(val, '$') != NULL) {
                    901:            val = Var_Subst(val, ctxt, err);
                    902:            *freePtr = TRUE;
                    903:        }
                    904:
                    905:        v->flags &= ~VAR_IN_USE;
1.1       deraadt   906:     }
1.44      espie     907:     if (endc != '\0')
                    908:        val = VarModifiers_Apply(val, ctxt, err, freePtr, tstr+1, endc,
1.42      espie     909:            lengthPtr);
1.44      espie     910:     if (val == NULL) {
                    911:        /* Dynamic source that can't be expanded for now: copy the var
                    912:         * specification instead.  */
                    913:        if (idx != -1 && (ctxt == NULL || ctxt == CTXT_GLOBAL)) {
1.42      espie     914:            *freePtr = TRUE;
1.44      espie     915:            val = interval_dup(start, start+ *lengthPtr);
                    916:        } else
                    917:            val = err ? var_Error : varNoError;
1.42      espie     918:     }
1.44      espie     919:
                    920:     return val;
1.42      espie     921: }
                    922:
1.1       deraadt   923: /*-
                    924:  *-----------------------------------------------------------------------
                    925:  * Var_Subst  --
1.24      espie     926:  *     Substitute for all variables in a string in a context
1.1       deraadt   927:  *     If undefErr is TRUE, Parse_Error will be called when an undefined
                    928:  *     variable is encountered.
                    929:  *
                    930:  * Results:
                    931:  *     The resulting string.
                    932:  *
                    933:  * Side Effects:
                    934:  *     None. The old string must be freed by the caller
                    935:  *-----------------------------------------------------------------------
                    936:  */
                    937: char *
1.24      espie     938: Var_Subst(str, ctxt, undefErr)
1.1       deraadt   939:     char         *str;             /* the string in which to substitute */
1.35      espie     940:     SymTable      *ctxt;           /* the context wherein to find variables */
1.1       deraadt   941:     Boolean      undefErr;         /* TRUE if undefineds are an error */
                    942: {
1.24      espie     943:     BUFFER       buf;              /* Buffer for forming things */
1.1       deraadt   944:     static Boolean errorReported;   /* Set true if an error has already
                    945:                                     * been reported to prevent a plethora
                    946:                                     * of messages when recursing */
                    947:
1.23      espie     948:     Buf_Init(&buf, MAKE_BSIZE);
1.1       deraadt   949:     errorReported = FALSE;
                    950:
1.24      espie     951:     for (;;) {
                    952:        char            *val;           /* Value to substitute for a variable */
                    953:        size_t          length;         /* Length of the variable invocation */
                    954:        Boolean         doFree;         /* Set true if val should be freed */
                    955:        const char *cp;
                    956:
                    957:        /* copy uninteresting stuff */
                    958:        for (cp = str; *str != '\0' && *str != '$'; str++)
                    959:            ;
                    960:        Buf_AddInterval(&buf, cp, str);
                    961:        if (*str == '\0')
                    962:            break;
                    963:        if (str[1] == '$') {
                    964:            /* A dollar sign may be escaped with another dollar sign.  */
                    965:            Buf_AddChar(&buf, '$');
                    966:            str += 2;
                    967:            continue;
                    968:        }
                    969:        val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
                    970:        /* When we come down here, val should either point to the
                    971:         * value of this variable, suitably modified, or be NULL.
                    972:         * Length should be the total length of the potential
                    973:         * variable invocation (from $ to end character...) */
                    974:        if (val == var_Error || val == varNoError) {
                    975:            /* If performing old-time variable substitution, skip over
                    976:             * the variable and continue with the substitution. Otherwise,
                    977:             * store the dollar sign and advance str so we continue with
                    978:             * the string...  */
                    979:            if (oldVars) {
                    980:                str += length;
                    981:            } else if (undefErr) {
                    982:                /* If variable is undefined, complain and skip the
                    983:                 * variable. The complaint will stop us from doing anything
                    984:                 * when the file is parsed.  */
                    985:                if (!errorReported) {
                    986:                    Parse_Error(PARSE_FATAL,
                    987:                                 "Undefined variable \"%.*s\"",length,str);
                    988:                }
                    989:                str += length;
                    990:                errorReported = TRUE;
                    991:            } else {
                    992:                Buf_AddChar(&buf, *str);
                    993:                str += 1;
                    994:            }
                    995:        } else {
                    996:            /* We've now got a variable structure to store in. But first,
                    997:             * advance the string pointer.  */
                    998:            str += length;
                    999:
                   1000:            /* Copy all the characters from the variable value straight
                   1001:             * into the new string.  */
                   1002:            Buf_AddString(&buf, val);
                   1003:            if (doFree)
                   1004:                free(val);
                   1005:        }
                   1006:     }
                   1007:     return  Buf_Retrieve(&buf);
                   1008: }
1.1       deraadt  1009:
1.24      espie    1010: /*-
                   1011:  *-----------------------------------------------------------------------
                   1012:  * Var_SubstVar  --
                   1013:  *     Substitute for one variable in the given string in the given context
                   1014:  *     If undefErr is TRUE, Parse_Error will be called when an undefined
1.50    ! espie    1015:  *     variable is encountered. Returns the string with substitutions.
1.24      espie    1016:  *-----------------------------------------------------------------------
                   1017:  */
1.50    ! espie    1018: char *
        !          1019: Var_SubstVar(str, var, val, estimate)
        !          1020:     const char *str;           /* The string in which to substitute */
1.24      espie    1021:     const char *var;           /* Named variable */
1.50    ! espie    1022:     const char *val;           /* Its value */
        !          1023:     size_t     estimate;       /* Size estimate for the result buffer */
1.24      espie    1024: {
1.50    ! espie    1025:     BUFFER     buf;            /* Where to store the result */
1.24      espie    1026:
1.50    ! espie    1027:     Buf_Init(&buf, estimate);
1.24      espie    1028:     for (;;) {
1.50    ! espie    1029:        const char *start;
        !          1030:        /* Copy uninteresting stuff */
        !          1031:        for (start = str; *str != '\0' && *str != '$'; str++)
1.24      espie    1032:            ;
1.50    ! espie    1033:        Buf_AddInterval(&buf, start, str);
        !          1034:
        !          1035:        start = str;
        !          1036:        if (*str++ == '\0')
1.24      espie    1037:            break;
1.50    ! espie    1038:        str++;
        !          1039:        /* and escaped dollars */
        !          1040:        if (start[1] == '$') {
        !          1041:            Buf_AddInterval(&buf, start, start+2);
1.24      espie    1042:            continue;
                   1043:        }
1.50    ! espie    1044:        /* Simple variable, if it's not us, copy.  */
        !          1045:        if (start[1] != '(' && start[1] != '{') {
        !          1046:            if (start[1] != *var || var[1] != '\0') {
        !          1047:                Buf_AddChars(&buf, 2, start);
1.1       deraadt  1048:                continue;
1.24      espie    1049:            }
1.1       deraadt  1050:        } else {
1.50    ! espie    1051:            const char *p;
1.24      espie    1052:            char endc;
1.1       deraadt  1053:
1.50    ! espie    1054:            if (start[1] == '(')
1.24      espie    1055:                endc = ')';
1.50    ! espie    1056:            else
1.24      espie    1057:                endc = '}';
                   1058:
                   1059:            /* Find the end of the variable specification.  */
1.50    ! espie    1060:            p = str;
1.24      espie    1061:            while (*p != '\0' && *p != ':' && *p != endc && *p != '$')
                   1062:                p++;
                   1063:            /* A variable inside the variable.  We don't know how to
                   1064:             * expand the external variable at this point, so we try
                   1065:             * again with the nested variable.  */
                   1066:            if (*p == '$') {
1.50    ! espie    1067:                Buf_AddInterval(&buf, start, p);
1.24      espie    1068:                str = p;
                   1069:                continue;
1.1       deraadt  1070:            }
1.5       millert  1071:
1.50    ! espie    1072:            if (strncmp(var, str, p - str) != 0 ||
        !          1073:                var[p - str] != '\0') {
1.24      espie    1074:                /* Not the variable we want to expand.  */
1.50    ! espie    1075:                Buf_AddInterval(&buf, start, p);
1.24      espie    1076:                str = p;
                   1077:                continue;
                   1078:            }
1.50    ! espie    1079:            if (*p == ':') {
        !          1080:                size_t  length;         /* Length of the variable invocation */
        !          1081:                Boolean doFree;         /* Set true if val should be freed */
        !          1082:                char    *newval;        /* Value substituted for a variable */
        !          1083:
        !          1084:                length = p - str + 1;
        !          1085:                doFree = FALSE;
        !          1086:
        !          1087:                /* val won't be freed since doFree == FALSE, but
        !          1088:                 * VarModifiers_Apply doesn't know that, hence the cast. */
        !          1089:                newval = VarModifiers_Apply((char *)val, NULL, FALSE,
        !          1090:                    &doFree, p+1, endc, &length);
        !          1091:                Buf_AddString(&buf, newval);
        !          1092:                if (doFree)
        !          1093:                    free(newval);
        !          1094:                str += length;
        !          1095:                continue;
        !          1096:            } else
        !          1097:                str = p+1;
1.1       deraadt  1098:        }
1.50    ! espie    1099:        Buf_AddString(&buf, val);
1.1       deraadt  1100:     }
1.50    ! espie    1101:     return Buf_Retrieve(&buf);
1.1       deraadt  1102: }
                   1103:
                   1104: /*-
                   1105:  *-----------------------------------------------------------------------
                   1106:  * Var_Init --
                   1107:  *     Initialize the module
                   1108:  *
                   1109:  * Side Effects:
1.5       millert  1110:  *     The VAR_CMD and VAR_GLOBAL contexts are created
1.1       deraadt  1111:  *-----------------------------------------------------------------------
                   1112:  */
                   1113: void
1.33      espie    1114: Var_Init()
1.1       deraadt  1115: {
1.37      espie    1116:     static GSymT global_vars, cmd_vars, env_vars;
1.35      espie    1117:
                   1118:     VAR_GLOBAL = &global_vars;
                   1119:     VAR_CMD = &cmd_vars;
                   1120:     VAR_ENV = &env_vars;
1.38      espie    1121:     hash_init(VAR_GLOBAL, 10, &var_info);
                   1122:     hash_init(VAR_CMD, 5, &var_info);
                   1123:     hash_init(VAR_ENV, 5, &var_info);
1.37      espie    1124:     CTXT_GLOBAL = (SymTable *)VAR_GLOBAL;
                   1125:     CTXT_CMD = (SymTable *)VAR_CMD;
                   1126:     CTXT_ENV = (SymTable *)VAR_ENV;
1.1       deraadt  1127: }
                   1128:
                   1129:
                   1130: void
1.33      espie    1131: Var_End()
1.1       deraadt  1132: {
1.37      espie    1133: #ifdef CLEANUP
1.38      espie    1134:     Var *v;
                   1135:     unsigned int i;
                   1136:
                   1137:     for (v = hash_first(VAR_GLOBAL, &i); v != NULL;
                   1138:        v = hash_next(VAR_GLOBAL, &i))
                   1139:            VarDelete(v);
                   1140:     for (v = hash_first(VAR_CMD, &i); v != NULL;
                   1141:        v = hash_next(VAR_CMD, &i))
                   1142:            VarDelete(v);
                   1143:     for (v = hash_first(VAR_ENV, &i); v != NULL;
                   1144:        v = hash_next(VAR_ENV, &i))
                   1145:            VarDelete(v);
1.37      espie    1146: #endif
1.1       deraadt  1147: }
1.5       millert  1148:
1.1       deraadt  1149:
                   1150: /****************** PRINT DEBUGGING INFO *****************/
1.31      espie    1151: static void
                   1152: VarPrintVar(vp)
1.32      espie    1153:     void *vp;
1.1       deraadt  1154: {
1.31      espie    1155:     Var    *v = (Var *)vp;
                   1156:
1.23      espie    1157:     printf("%-16s = %s\n", v->name, VarValue(v));
1.1       deraadt  1158: }
                   1159:
                   1160: /*-
                   1161:  *-----------------------------------------------------------------------
                   1162:  * Var_Dump --
                   1163:  *     print all variables in a context
                   1164:  *-----------------------------------------------------------------------
                   1165:  */
                   1166: void
1.35      espie    1167: Var_Dump(ctxt)
1.37      espie    1168:    GSymT       *ctxt;
1.1       deraadt  1169: {
1.38      espie    1170:        Var *v;
                   1171:        unsigned int i;
                   1172:
                   1173:        for (v = hash_first(ctxt, &i); v != NULL;
                   1174:            v = hash_next(ctxt, &i))
                   1175:                VarPrintVar(v);
1.1       deraadt  1176: }
1.37      espie    1177:
1.46      espie    1178:
                   1179: #ifdef POSIX
                   1180:
                   1181: static const char *quotable = " \t\n\\'\"";
                   1182:
                   1183: /* In POSIX mode, variable assignments passed on the command line are
                   1184:  * propagated to sub makes through MAKEFLAGS.
                   1185:  */
                   1186: void
                   1187: Var_AddCmdline(name)
                   1188:        const char *name;
                   1189: {
                   1190:     Var *v;
                   1191:     unsigned int i;
                   1192:     BUFFER buf;
                   1193:     char *s;
                   1194:
                   1195:     Buf_Init(&buf, MAKE_BSIZE);
                   1196:
                   1197:     for (v = hash_first(VAR_CMD, &i); v != NULL;
                   1198:        v = hash_next(VAR_CMD, &i)) {
                   1199:                /* We assume variable names don't need quoting */
                   1200:                Buf_AddString(&buf, v->name);
                   1201:                Buf_AddChar(&buf, '=');
                   1202:                for (s = VarValue(v); *s != '\0'; s++) {
                   1203:                        if (strchr(quotable, *s))
                   1204:                                Buf_AddChar(&buf, '\\');
                   1205:                        Buf_AddChar(&buf, *s);
                   1206:                }
                   1207:                Buf_AddSpace(&buf);
                   1208:     }
                   1209:     Var_Append(name, Buf_Retrieve(&buf), VAR_GLOBAL);
                   1210:     Buf_Destroy(&buf);
                   1211: }
                   1212: #endif