home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bsd
/
src
/
make
/
make-amiga
/
var.c
< prev
Wrap
C/C++ Source or Header
|
1993-09-23
|
53KB
|
1,880 lines
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* Copyright (c) 1988, 1989 by Adam de Boor
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)var.c 5.7 (Berkeley) 6/1/90";
#endif /* not lint */
/*-
* var.c --
* Variable-handling functions
*
* Interface:
* Var_Set Set the value of a variable in the given
* context. The variable is created if it doesn't
* yet exist. The value and variable name need not
* be preserved.
*
* Var_Append Append more characters to an existing variable
* in the given context. The variable needn't
* exist already -- it will be created if it doesn't.
* A space is placed between the old value and the
* new one.
*
* Var_Exists See if a variable exists.
*
* Var_Value Return the value of a variable in a context or
* NULL if the variable is undefined.
*
* Var_Subst Substitute for all variables in a string using
* the given context as the top-most one. If the
* third argument is non-zero, Parse_Error is
* called if any variables are undefined.
*
* Var_Parse Parse a variable expansion from a string and
* return the result and the number of characters
* consumed.
*
* Var_Delete Delete a variable in a context.
*
* Var_Init Initialize this module.
*
* Debugging:
* Var_Dump Print out all variables defined in the given
* context.
*
* XXX: There's a lot of duplication in these functions.
*/
#include <ctype.h>
#include "make.h"
#include "buf.h"
extern char *getenv();
/*
* This is a harmless return value for Var_Parse that can be used by Var_Subst
* to determine if there was an error in parsing -- easier than returning
* a flag, as things outside this module don't give a hoot.
*/
char var_Error[] = "";
/*
* Similar to var_Error, but returned when the 'err' flag for Var_Parse is
* set false. Why not just use a constant? Well, gcc likes to condense
* identical string instances...
*/
char varNoError[] = "";
/*
* Internally, variables are contained in four different contexts.
* 1) the environment. They may not be changed. If an environment
* variable is appended-to, the result is placed in the global
* context.
* 2) the global context. Variables set in the Makefile are located in
* the global context. It is the penultimate context searched when
* substituting.
* 3) the command-line context. All variables set on the command line
* are placed in this context. They are UNALTERABLE once placed here.
* 4) the local context. Each target has associated with it a context
* list. On this list are located the structures describing such
* local variables as $(@) and $(*)
* The four contexts are searched in the reverse order from which they are
* listed.
*/
GNode *VAR_GLOBAL; /* variables from the makefile */
GNode *VAR_CMD; /* variables defined on the command-line */
#define FIND_CMD 0x1 /* look in VAR_CMD when searching */
#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
#define FIND_ENV 0x4 /* look in the environment also */
typedef struct Var {
char *name; /* the variable's name */
Buffer val; /* its value */
int flags; /* miscellaneous status flags */
#define VAR_IN_USE 1 /* Variable's value currently being used.
* Used to avoid recursion */
#define VAR_FROM_ENV 2 /* Variable comes from the environment */
#define VAR_JUNK 4 /* Variable is a junk variable that
* should be destroyed when done with
* it. Used by Var_Parse for undefined,
* modified variables */
} Var;
/*-
*-----------------------------------------------------------------------
* VarCmp --
* See if the given variable matches the named one. Called from
* Lst_Find when searching for a variable of a given name.
*
* Results:
* 0 if they match. non-zero otherwise.
*
* Side Effects:
* none
*-----------------------------------------------------------------------
*/
static int
VarCmp (v, name)
Var *v; /* VAR structure to compare */
char *name; /* name to look for */
{
return (strcmp (name, v->name));
}
/*-
*-----------------------------------------------------------------------
* VarFind --
* Find the given variable in the given context and any other contexts
* indicated.
*
* Results:
* A pointer to the structure describing the desired variable or
* NIL if the variable does not exist.
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static Var *
VarFind (name, ctxt, flags)
char *name; /* name to find */
GNode *ctxt; /* context in which to find it */
int flags; /* FIND_GLOBAL set means to look in the
* VAR_GLOBAL context as well.
* FIND_CMD set means to look in the VAR_CMD
* context also.
* FIND_ENV set means to look in the
* environment */
{
LstNode var;
Var *v;
/*
* If the variable name begins with a '.', it could very well be one of
* the local ones. We check the name against all the local variables
* and substitute the short version in for 'name' if it matches one of
* them.
*/
if (*name == '.' && isupper(name[1]))
switch (name[1]) {
case 'A':
if (!strcmp(name, ".ALLSRC"))
name = ALLSRC;
if (!strcmp(name, ".ARCHIVE"))
name = ARCHIVE;
break;
case 'I':
if (!strcmp(name, ".IMPSRC"))
name = IMPSRC;
break;
case 'M':
if (!strcmp(name, ".MEMBER"))
name = MEMBER;
break;
case 'O':
if (!strcmp(name, ".OODATE"))
name = OODATE;
break;
case 'P':
if (!strcmp(name, ".PREFIX"))
name = PREFIX;
break;
case 'T':
if (!strcmp(name, ".TARGET"))
name = TARGET;
break;
}
/*
* First look for the variable in the given context. If it's not there,
* look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
* depending on the FIND_* flags in 'flags'
*/
var = Lst_Find (ctxt->context, (ClientData)name, VarCmp);
if ((var == NILLNODE) && (flags & FIND_C