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

1.44    ! espie       1: /*     $OpenBSD: var.c,v 1.43 2000/07/17 23:09:06 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.44    ! espie      73: static char rcsid[] = "$OpenBSD: var.c,v 1.43 2000/07/17 23:09:06 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:  */
                    774: char *
1.35      espie     775: Var_Parse(str, ctxt, err, lengthPtr, freePtr)
1.44    ! espie     776:     char       *str;           /* The string to parse */
        !           777:     SymTable           *ctxt;          /* The context for the variable */
        !           778:     Boolean    err;            /* TRUE if undefined variables are an error */
        !           779:     size_t     *lengthPtr;     /* OUT: The length of the specification */
        !           780:     Boolean    *freePtr;       /* OUT: TRUE if caller should free result */
        !           781: {
        !           782:     char       *tstr;          /* Pointer into str */
        !           783:     Var                *v;             /* Variable in invocation */
        !           784:     char       endc;           /* Ending character when variable in parens
1.1       deraadt   785:                                 * or braces */
1.44    ! espie     786:     char       *start;
        !           787:     char       *val;           /* Variable value  */
        !           788:     u_int32_t  k;
        !           789:     int                idx;
1.5       millert   790:
1.1       deraadt   791:     *freePtr = FALSE;
1.44    ! espie     792:     start = str++;
1.5       millert   793:
1.44    ! espie     794:     val = NULL;
        !           795:
        !           796:     if (*str != '(' && *str != '{') {
        !           797:        tstr = str + 1;
        !           798:        *lengthPtr = 2;
        !           799:        endc = '\0';
1.1       deraadt   800:     } else {
1.44    ! espie     801:        endc = *str == '(' ? ')' : '}';
        !           802:        str++;
1.5       millert   803:
1.44    ! espie     804:        /* Find eventual modifiers in the variable */
        !           805:        for (tstr = str; *tstr != ':'; tstr++)
        !           806:            if (*tstr == '\0' || *tstr == endc) {
        !           807:                endc = '\0';
        !           808:                break;
1.1       deraadt   809:            }
1.44    ! espie     810:        *lengthPtr = tstr+1 - start;
        !           811:     }
1.5       millert   812:
1.44    ! espie     813:     idx = quick_lookup(str, &tstr, &k);
        !           814:     v = varfind(str, tstr, ctxt, FIND_ENV | FIND_MINE, idx, k);
        !           815:     if (v == NULL) {
        !           816:        /* Find out about D and F forms of local variables. */
        !           817:        if (idx == -1 && tstr == str+2 && (str[1] == 'D' || str[1] == 'F')) {
        !           818:            switch (*str) {
        !           819:            case '@':
        !           820:                idx = TARGET_INDEX;
        !           821:                break;
        !           822:            case '!':
        !           823:                idx = ARCHIVE_INDEX;
        !           824:                break;
        !           825:            case '*':
        !           826:                idx = PREFIX_INDEX;
        !           827:                break;
        !           828:            case '%':
        !           829:                idx = MEMBER_INDEX;
        !           830:                break;
        !           831:            default:
        !           832:                break;
1.1       deraadt   833:            }
1.44    ! espie     834:            /* This is a DF form, check if we can expand it now.  */
        !           835:            if (idx != -1 && ctxt != NULL && ctxt != CTXT_GLOBAL) {
        !           836:                v = varfind(str, str+1, ctxt, 0, idx, 0);
        !           837:                /* No need for nested expansion or anything, as we're
        !           838:                 * the only one who sets these things and we sure don't
        !           839:                 * do nested invocations in them...  */
        !           840:                if (v != NULL) {
        !           841:                    val = VarValue(v);
        !           842:                    if (str[1] == 'D')
        !           843:                        val = Var_GetHead(val);
        !           844:                    else
        !           845:                        val = Var_GetTail(val);
1.1       deraadt   846:                    *freePtr = TRUE;
1.44    ! espie     847:                }
1.1       deraadt   848:            }
                    849:        }
1.44    ! espie     850:     } else {
        !           851:        if (v->flags & VAR_IN_USE)
        !           852:            Fatal("Variable %s is recursive.", v->name);
        !           853:            /*NOTREACHED*/
        !           854:        else
        !           855:            v->flags |= VAR_IN_USE;
        !           856:        /* Before doing any modification, we have to make sure the value
        !           857:         * has been fully expanded. If it looks like recursion might be
        !           858:         * necessary (there's a dollar sign somewhere in the variable's value)
        !           859:         * we just call Var_Subst to do any other substitutions that are
        !           860:         * necessary. Note that the value returned by Var_Subst will have
        !           861:         * been dynamically-allocated, so it will need freeing when we
        !           862:         * return.  */
        !           863:        val = VarValue(v);
        !           864:        if (strchr(val, '$') != NULL) {
        !           865:            val = Var_Subst(val, ctxt, err);
        !           866:            *freePtr = TRUE;
        !           867:        }
        !           868:
        !           869:        v->flags &= ~VAR_IN_USE;
1.1       deraadt   870:     }
1.44    ! espie     871:     if (endc != '\0')
        !           872:        val = VarModifiers_Apply(val, ctxt, err, freePtr, tstr+1, endc,
1.42      espie     873:            lengthPtr);
1.44    ! espie     874:     if (val == NULL) {
        !           875:        /* Dynamic source that can't be expanded for now: copy the var
        !           876:         * specification instead.  */
        !           877:        if (idx != -1 && (ctxt == NULL || ctxt == CTXT_GLOBAL)) {
1.42      espie     878:            *freePtr = TRUE;
1.44    ! espie     879:            val = interval_dup(start, start+ *lengthPtr);
        !           880:        } else
        !           881:            val = err ? var_Error : varNoError;
1.42      espie     882:     }
1.44    ! espie     883:
        !           884:     return val;
1.42      espie     885: }
                    886:
1.1       deraadt   887: /*-
                    888:  *-----------------------------------------------------------------------
                    889:  * Var_Subst  --
1.24      espie     890:  *     Substitute for all variables in a string in a context
1.1       deraadt   891:  *     If undefErr is TRUE, Parse_Error will be called when an undefined
                    892:  *     variable is encountered.
                    893:  *
                    894:  * Results:
                    895:  *     The resulting string.
                    896:  *
                    897:  * Side Effects:
                    898:  *     None. The old string must be freed by the caller
                    899:  *-----------------------------------------------------------------------
                    900:  */
                    901: char *
1.24      espie     902: Var_Subst(str, ctxt, undefErr)
1.1       deraadt   903:     char         *str;             /* the string in which to substitute */
1.35      espie     904:     SymTable      *ctxt;           /* the context wherein to find variables */
1.1       deraadt   905:     Boolean      undefErr;         /* TRUE if undefineds are an error */
                    906: {
1.24      espie     907:     BUFFER       buf;              /* Buffer for forming things */
1.1       deraadt   908:     static Boolean errorReported;   /* Set true if an error has already
                    909:                                     * been reported to prevent a plethora
                    910:                                     * of messages when recursing */
                    911:
1.23      espie     912:     Buf_Init(&buf, MAKE_BSIZE);
1.1       deraadt   913:     errorReported = FALSE;
                    914:
1.24      espie     915:     for (;;) {
                    916:        char            *val;           /* Value to substitute for a variable */
                    917:        size_t          length;         /* Length of the variable invocation */
                    918:        Boolean         doFree;         /* Set true if val should be freed */
                    919:        const char *cp;
                    920:
                    921:        /* copy uninteresting stuff */
                    922:        for (cp = str; *str != '\0' && *str != '$'; str++)
                    923:            ;
                    924:        Buf_AddInterval(&buf, cp, str);
                    925:        if (*str == '\0')
                    926:            break;
                    927:        if (str[1] == '$') {
                    928:            /* A dollar sign may be escaped with another dollar sign.  */
                    929:            Buf_AddChar(&buf, '$');
                    930:            str += 2;
                    931:            continue;
                    932:        }
                    933:        val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
                    934:        /* When we come down here, val should either point to the
                    935:         * value of this variable, suitably modified, or be NULL.
                    936:         * Length should be the total length of the potential
                    937:         * variable invocation (from $ to end character...) */
                    938:        if (val == var_Error || val == varNoError) {
                    939:            /* If performing old-time variable substitution, skip over
                    940:             * the variable and continue with the substitution. Otherwise,
                    941:             * store the dollar sign and advance str so we continue with
                    942:             * the string...  */
                    943:            if (oldVars) {
                    944:                str += length;
                    945:            } else if (undefErr) {
                    946:                /* If variable is undefined, complain and skip the
                    947:                 * variable. The complaint will stop us from doing anything
                    948:                 * when the file is parsed.  */
                    949:                if (!errorReported) {
                    950:                    Parse_Error(PARSE_FATAL,
                    951:                                 "Undefined variable \"%.*s\"",length,str);
                    952:                }
                    953:                str += length;
                    954:                errorReported = TRUE;
                    955:            } else {
                    956:                Buf_AddChar(&buf, *str);
                    957:                str += 1;
                    958:            }
                    959:        } else {
                    960:            /* We've now got a variable structure to store in. But first,
                    961:             * advance the string pointer.  */
                    962:            str += length;
                    963:
                    964:            /* Copy all the characters from the variable value straight
                    965:             * into the new string.  */
                    966:            Buf_AddString(&buf, val);
                    967:            if (doFree)
                    968:                free(val);
                    969:        }
                    970:     }
                    971:     return  Buf_Retrieve(&buf);
                    972: }
1.1       deraadt   973:
1.24      espie     974: /*-
                    975:  *-----------------------------------------------------------------------
                    976:  * Var_SubstVar  --
                    977:  *     Substitute for one variable in the given string in the given context
                    978:  *     If undefErr is TRUE, Parse_Error will be called when an undefined
                    979:  *     variable is encountered.
                    980:  *
                    981:  * Side Effects:
                    982:  *     Append the result to the buffer
                    983:  *-----------------------------------------------------------------------
                    984:  */
                    985: void
                    986: Var_SubstVar(buf, str, var, ctxt)
                    987:     Buffer     buf;            /* Where to store the result */
                    988:     char       *str;           /* The string in which to substitute */
                    989:     const char *var;           /* Named variable */
1.37      espie     990:     GSymT      *ctxt;          /* The context wherein to find variables */
1.24      espie     991: {
                    992:     char       *val;           /* Value substituted for a variable */
                    993:     size_t     length;         /* Length of the variable invocation */
                    994:     Boolean    doFree;         /* Set true if val should be freed */
                    995:
                    996:     for (;;) {
                    997:        const char *cp;
                    998:        /* copy uninteresting stuff */
                    999:        for (cp = str; *str != '\0' && *str != '$'; str++)
                   1000:            ;
                   1001:        Buf_AddInterval(buf, cp, str);
                   1002:        if (*str == '\0')
                   1003:            break;
                   1004:        if (str[1] == '$') {
                   1005:            Buf_AddString(buf, "$$");
                   1006:            str += 2;
                   1007:            continue;
                   1008:        }
                   1009:        if (str[1] != '(' && str[1] != '{') {
                   1010:            if (str[1] != *var || var[1] != '\0') {
                   1011:                Buf_AddChars(buf, 2, str);
                   1012:                str += 2;
1.1       deraadt  1013:                continue;
1.24      espie    1014:            }
1.1       deraadt  1015:        } else {
1.24      espie    1016:            char *p;
                   1017:            char endc;
1.1       deraadt  1018:
1.24      espie    1019:            if (str[1] == '(')
                   1020:                endc = ')';
                   1021:            else if (str[1] == '{')
                   1022:                endc = '}';
                   1023:
                   1024:            /* Find the end of the variable specification.  */
                   1025:            p = str+2;
                   1026:            while (*p != '\0' && *p != ':' && *p != endc && *p != '$')
                   1027:                p++;
                   1028:            /* A variable inside the variable.  We don't know how to
                   1029:             * expand the external variable at this point, so we try
                   1030:             * again with the nested variable.  */
                   1031:            if (*p == '$') {
                   1032:                Buf_AddInterval(buf, str, p);
                   1033:                str = p;
                   1034:                continue;
1.1       deraadt  1035:            }
1.5       millert  1036:
1.24      espie    1037:            if (strncmp(var, str + 2, p - str - 2) != 0 ||
                   1038:                var[p - str - 2] != '\0') {
                   1039:                /* Not the variable we want to expand.  */
                   1040:                Buf_AddInterval(buf, str, p);
                   1041:                str = p;
                   1042:                continue;
                   1043:            }
1.1       deraadt  1044:        }
1.24      espie    1045:        /* okay, so we've found the variable we want to expand.  */
1.37      espie    1046:        val = Var_Parse(str, (SymTable *)ctxt, FALSE, &length, &doFree);
1.24      espie    1047:        /* We've now got a variable structure to store in. But first,
                   1048:         * advance the string pointer.  */
                   1049:        str += length;
                   1050:
                   1051:        /* Copy all the characters from the variable value straight
                   1052:         * into the new string.  */
                   1053:        Buf_AddString(buf, val);
                   1054:        if (doFree)
                   1055:            free(val);
1.1       deraadt  1056:     }
                   1057: }
                   1058:
                   1059: /*-
                   1060:  *-----------------------------------------------------------------------
                   1061:  * Var_Init --
                   1062:  *     Initialize the module
                   1063:  *
                   1064:  * Side Effects:
1.5       millert  1065:  *     The VAR_CMD and VAR_GLOBAL contexts are created
1.1       deraadt  1066:  *-----------------------------------------------------------------------
                   1067:  */
                   1068: void
1.33      espie    1069: Var_Init()
1.1       deraadt  1070: {
1.37      espie    1071:     static GSymT global_vars, cmd_vars, env_vars;
1.35      espie    1072:
                   1073:     VAR_GLOBAL = &global_vars;
                   1074:     VAR_CMD = &cmd_vars;
                   1075:     VAR_ENV = &env_vars;
1.38      espie    1076:     hash_init(VAR_GLOBAL, 10, &var_info);
                   1077:     hash_init(VAR_CMD, 5, &var_info);
                   1078:     hash_init(VAR_ENV, 5, &var_info);
1.37      espie    1079:     CTXT_GLOBAL = (SymTable *)VAR_GLOBAL;
                   1080:     CTXT_CMD = (SymTable *)VAR_CMD;
                   1081:     CTXT_ENV = (SymTable *)VAR_ENV;
1.1       deraadt  1082: }
                   1083:
                   1084:
                   1085: void
1.33      espie    1086: Var_End()
1.1       deraadt  1087: {
1.37      espie    1088: #ifdef CLEANUP
1.38      espie    1089:     Var *v;
                   1090:     unsigned int i;
                   1091:
                   1092:     for (v = hash_first(VAR_GLOBAL, &i); v != NULL;
                   1093:        v = hash_next(VAR_GLOBAL, &i))
                   1094:            VarDelete(v);
                   1095:     for (v = hash_first(VAR_CMD, &i); v != NULL;
                   1096:        v = hash_next(VAR_CMD, &i))
                   1097:            VarDelete(v);
                   1098:     for (v = hash_first(VAR_ENV, &i); v != NULL;
                   1099:        v = hash_next(VAR_ENV, &i))
                   1100:            VarDelete(v);
1.37      espie    1101: #endif
1.1       deraadt  1102: }
1.5       millert  1103:
1.1       deraadt  1104:
                   1105: /****************** PRINT DEBUGGING INFO *****************/
1.31      espie    1106: static void
                   1107: VarPrintVar(vp)
1.32      espie    1108:     void *vp;
1.1       deraadt  1109: {
1.31      espie    1110:     Var    *v = (Var *)vp;
                   1111:
1.23      espie    1112:     printf("%-16s = %s\n", v->name, VarValue(v));
1.1       deraadt  1113: }
                   1114:
                   1115: /*-
                   1116:  *-----------------------------------------------------------------------
                   1117:  * Var_Dump --
                   1118:  *     print all variables in a context
                   1119:  *-----------------------------------------------------------------------
                   1120:  */
                   1121: void
1.35      espie    1122: Var_Dump(ctxt)
1.37      espie    1123:    GSymT       *ctxt;
1.1       deraadt  1124: {
1.38      espie    1125:        Var *v;
                   1126:        unsigned int i;
                   1127:
                   1128:        for (v = hash_first(ctxt, &i); v != NULL;
                   1129:            v = hash_next(ctxt, &i))
                   1130:                VarPrintVar(v);
1.1       deraadt  1131: }
1.37      espie    1132: