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

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