diff options
author | JinWang An <jinwang.an@samsung.com> | 2021-12-28 15:15:18 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2021-12-28 15:15:18 +0900 |
commit | b11e2699c7ec42e6d2fc0f4c940f14e7c89b3974 (patch) | |
tree | 14002517ee70130303762f511b4d1b50251267ca /variable.c | |
parent | 0a1cba99f5ce73ae0cacdbf9ab1186137efd77f7 (diff) | |
download | make-b11e2699c7ec42e6d2fc0f4c940f14e7c89b3974.tar.gz make-b11e2699c7ec42e6d2fc0f4c940f14e7c89b3974.tar.bz2 make-b11e2699c7ec42e6d2fc0f4c940f14e7c89b3974.zip |
Imported Upstream version 4.3upstream/4.3
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 1802 |
1 files changed, 0 insertions, 1802 deletions
diff --git a/variable.c b/variable.c deleted file mode 100644 index 36ab1f4..0000000 --- a/variable.c +++ /dev/null @@ -1,1802 +0,0 @@ -/* Internals of variables for GNU Make. -Copyright (C) 1988-2016 Free Software Foundation, Inc. -This file is part of GNU Make. - -GNU Make is free software; you can redistribute it and/or modify it under the -terms of the GNU General Public License as published by the Free Software -Foundation; either version 3 of the License, or (at your option) any later -version. - -GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "makeint.h" - -#include <assert.h> - -#include "filedef.h" -#include "dep.h" -#include "job.h" -#include "commands.h" -#include "variable.h" -#include "rule.h" -#ifdef WINDOWS32 -#include "pathstuff.h" -#endif -#include "hash.h" - -/* Incremented every time we add or remove a global variable. */ -static unsigned long variable_changenum; - -/* Chain of all pattern-specific variables. */ - -static struct pattern_var *pattern_vars; - -/* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/ - -static struct pattern_var *last_pattern_vars[256]; - -/* Create a new pattern-specific variable struct. The new variable is - inserted into the PATTERN_VARS list in the shortest patterns first - order to support the shortest stem matching (the variables are - matched in the reverse order so the ones with the longest pattern - will be considered first). Variables with the same pattern length - are inserted in the definition order. */ - -struct pattern_var * -create_pattern_var (const char *target, const char *suffix) -{ - register unsigned int len = strlen (target); - register struct pattern_var *p = xmalloc (sizeof (struct pattern_var)); - - if (pattern_vars != 0) - { - if (len < 256 && last_pattern_vars[len] != 0) - { - p->next = last_pattern_vars[len]->next; - last_pattern_vars[len]->next = p; - } - else - { - /* Find the position where we can insert this variable. */ - register struct pattern_var **v; - - for (v = &pattern_vars; ; v = &(*v)->next) - { - /* Insert at the end of the pack so that patterns with the - same length appear in the order they were defined .*/ - - if (*v == 0 || (*v)->len > len) - { - p->next = *v; - *v = p; - break; - } - } - } - } - else - { - pattern_vars = p; - p->next = 0; - } - - p->target = target; - p->len = len; - p->suffix = suffix + 1; - - if (len < 256) - last_pattern_vars[len] = p; - - return p; -} - -/* Look up a target in the pattern-specific variable list. */ - -static struct pattern_var * -lookup_pattern_var (struct pattern_var *start, const char *target) -{ - struct pattern_var *p; - unsigned int targlen = strlen (target); - - for (p = start ? start->next : pattern_vars; p != 0; p = p->next) - { - const char *stem; - unsigned int stemlen; - - if (p->len > targlen) - /* It can't possibly match. */ - continue; - - /* From the lengths of the filename and the pattern parts, - find the stem: the part of the filename that matches the %. */ - stem = target + (p->suffix - p->target - 1); - stemlen = targlen - p->len + 1; - - /* Compare the text in the pattern before the stem, if any. */ - if (stem > target && !strneq (p->target, target, stem - target)) - continue; - - /* Compare the text in the pattern after the stem, if any. - We could test simply using streq, but this way we compare the - first two characters immediately. This saves time in the very - common case where the first character matches because it is a - period. */ - if (*p->suffix == stem[stemlen] - && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1]))) - break; - } - - return p; -} - -/* Hash table of all global variable definitions. */ - -static unsigned long -variable_hash_1 (const void *keyv) -{ - struct variable const *key = (struct variable const *) keyv; - return_STRING_N_HASH_1 (key->name, key->length); -} - -static unsigned long -variable_hash_2 (const void *keyv) -{ - struct variable const *key = (struct variable const *) keyv; - return_STRING_N_HASH_2 (key->name, key->length); -} - -static int -variable_hash_cmp (const void *xv, const void *yv) -{ - struct variable const *x = (struct variable const *) xv; - struct variable const *y = (struct variable const *) yv; - int result = x->length - y->length; - if (result) - return result; - return_STRING_N_COMPARE (x->name, y->name, x->length); -} - -#ifndef VARIABLE_BUCKETS -#define VARIABLE_BUCKETS 523 -#endif -#ifndef PERFILE_VARIABLE_BUCKETS -#define PERFILE_VARIABLE_BUCKETS 23 -#endif -#ifndef SMALL_SCOPE_VARIABLE_BUCKETS -#define SMALL_SCOPE_VARIABLE_BUCKETS 13 -#endif - -static struct variable_set global_variable_set; -static struct variable_set_list global_setlist - = { 0, &global_variable_set, 0 }; -struct variable_set_list *current_variable_set_list = &global_setlist; - -/* Implement variables. */ - -void -init_hash_global_variable_set (void) -{ - hash_init (&global_variable_set.table, VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); -} - -/* Define variable named NAME with value VALUE in SET. VALUE is copied. - LENGTH is the length of NAME, which does not need to be null-terminated. - ORIGIN specifies the origin of the variable (makefile, command line - or environment). - If RECURSIVE is nonzero a flag is set in the variable saying - that it should be recursively re-expanded. */ - -struct variable * -define_variable_in_set (const char *name, unsigned int length, - const char *value, enum variable_origin origin, - int recursive, struct variable_set *set, - const floc *flocp) -{ - struct variable *v; - struct variable **var_slot; - struct variable var_key; - - if (set == NULL) - set = &global_variable_set; - - var_key.name = (char *) name; - var_key.length = length; - var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); - v = *var_slot; - -#ifdef VMS - /* VMS does not populate envp[] with DCL symbols and logical names which - historically are mapped to environent variables. - If the variable is not yet defined, then we need to check if getenv() - can find it. Do not do this for origin == o_env to avoid infinte - recursion */ - if (HASH_VACANT (v) && (origin != o_env)) - { - struct variable * vms_variable; - char * vname = alloca (length + 1); - char * vvalue; - - strncpy (vname, name, length); - vvalue = getenv(vname); - - /* Values starting with '$' are probably foreign commands. - We want to treat them as Shell aliases and not look them up here */ - if ((vvalue != NULL) && (vvalue[0] != '$')) - { - vms_variable = lookup_variable(name, length); - /* Refresh the slot */ - var_slot = (struct variable **) hash_find_slot (&set->table, - &var_key); - v = *var_slot; - } - } -#endif - - if (env_overrides && origin == o_env) - origin = o_env_override; - - if (! HASH_VACANT (v)) - { - if (env_overrides && v->origin == o_env) - /* V came from in the environment. Since it was defined - before the switches were parsed, it wasn't affected by -e. */ - v->origin = o_env_override; - - /* A variable of this name is already defined. - If the old definition is from a stronger source - than this one, don't redefine it. */ - if ((int) origin >= (int) v->origin) - { - free (v->value); - v->value = xstrdup (value); - if (flocp != 0) - v->fileinfo = *flocp; - else - v->fileinfo.filenm = 0; - v->origin = origin; - v->recursive = recursive; - } - return v; - } - - /* Create a new variable definition and add it to the hash table. */ - - v = xmalloc (sizeof (struct variable)); - v->name = xstrndup (name, length); - v->length = length; - hash_insert_at (&set->table, v, var_slot); - if (set == &global_variable_set) - ++variable_changenum; - - v->value = xstrdup (value); - if (flocp != 0) - v->fileinfo = *flocp; - else - v->fileinfo.filenm = 0; - v->origin = origin; - v->recursive = recursive; - v->special = 0; - v->expanding = 0; - v->exp_count = 0; - v->per_target = 0; - v->append = 0; - v->private_var = 0; - v->export = v_default; - - v->exportable = 1; - if (*name != '_' && (*name < 'A' || *name > 'Z') - && (*name < 'a' || *name > 'z')) - v->exportable = 0; - else - { - for (++name; *name != '\0'; ++name) - if (*name != '_' && (*name < 'a' || *name > 'z') - && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name)) - break; - - if (*name != '\0') - v->exportable = 0; - } - - return v; -} - - -/* Undefine variable named NAME in SET. LENGTH is the length of NAME, which - does not need to be null-terminated. ORIGIN specifies the origin of the - variable (makefile, command line or environment). */ - -static void -free_variable_name_and_value (const void *item) -{ - struct variable *v = (struct variable *) item; - free (v->name); - free (v->value); -} - -void -free_variable_set (struct variable_set_list *list) -{ - hash_map (&list->set->table, free_variable_name_and_value); - hash_free (&list->set->table, 1); - free (list->set); - free (list); -} - -void -undefine_variable_in_set (const char *name, unsigned int length, - enum variable_origin origin, - struct variable_set *set) -{ - struct variable *v; - struct variable **var_slot; - struct variable var_key; - - if (set == NULL) - set = &global_variable_set; - - var_key.name = (char *) name; - var_key.length = length; - var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); - - if (env_overrides && origin == o_env) - origin = o_env_override; - - v = *var_slot; - if (! HASH_VACANT (v)) - { - if (env_overrides && v->origin == o_env) - /* V came from in the environment. Since it was defined - before the switches were parsed, it wasn't affected by -e. */ - v->origin = o_env_override; - - /* Undefine only if this undefinition is from an equal or stronger - source than the variable definition. */ - if ((int) origin >= (int) v->origin) - { - hash_delete_at (&set->table, var_slot); - free_variable_name_and_value (v); - free (v); - if (set == &global_variable_set) - ++variable_changenum; - } - } -} - -/* If the variable passed in is "special", handle its special nature. - Currently there are two such variables, both used for introspection: - .VARIABLES expands to a list of all the variables defined in this instance - of make. - .TARGETS expands to a list of all the targets defined in this - instance of make. - Returns the variable reference passed in. */ - -#define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500) - -static struct variable * -lookup_special_var (struct variable *var) -{ - static unsigned long last_changenum = 0; - - - /* This one actually turns out to be very hard, due to the way the parser - records targets. The way it works is that target information is collected - internally until make knows the target is completely specified. It unitl - it sees that some new construct (a new target or variable) is defined that - it knows the previous one is done. In short, this means that if you do - this: - - all: - - TARGS := $(.TARGETS) - - then $(TARGS) won't contain "all", because it's not until after the - variable is created that the previous target is completed. - - Changing this would be a major pain. I think a less complex way to do it - would be to pre-define the target files as soon as the first line is - parsed, then come back and do the rest of the definition as now. That - would allow $(.TARGETS) to be correct without a major change to the way - the parser works. - - if (streq (var->name, ".TARGETS")) - var->value = build_target_list (var->value); - else - */ - - if (variable_changenum != last_changenum && streq (var->name, ".VARIABLES")) - { - unsigned long max = EXPANSION_INCREMENT (strlen (var->value)); - unsigned long len; - char *p; - struct variable **vp = (struct variable **) global_variable_set.table.ht_vec; - struct variable **end = &vp[global_variable_set.table.ht_size]; - - /* Make sure we have at least MAX bytes in the allocated buffer. */ - var->value = xrealloc (var->value, max); - - /* Walk through the hash of variables, constructing a list of names. */ - p = var->value; - len = 0; - for (; vp < end; ++vp) - if (!HASH_VACANT (*vp)) - { - struct variable *v = *vp; - int l = v->length; - - len += l + 1; - if (len > max) - { - unsigned long off = p - var->value; - - max += EXPANSION_INCREMENT (l + 1); - var->value = xrealloc (var->value, max); - p = &var->value[off]; - } - - memcpy (p, v->name, l); - p += l; - *(p++) = ' '; - } - *(p-1) = '\0'; - - /* Remember the current variable change number. */ - last_changenum = variable_changenum; - } - - return var; -} - - -/* Lookup a variable whose name is a string starting at NAME - and with LENGTH chars. NAME need not be null-terminated. - Returns address of the 'struct variable' containing all info - on the variable, or nil if no such variable is defined. */ - -struct variable * -lookup_variable (const char *name, unsigned int length) -{ - const struct variable_set_list *setlist; - struct variable var_key; - int is_parent = 0; - - var_key.name = (char *) name; - var_key.length = length; - - for (setlist = current_variable_set_list; - setlist != 0; setlist = setlist->next) - { - const struct variable_set *set = setlist->set; - struct variable *v; - - v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); - if (v && (!is_parent || !v->private_var)) - return v->special ? lookup_special_var (v) : v; - - is_parent |= setlist->next_is_parent; - } - -#ifdef VMS - /* VMS does not populate envp[] with DCL symbols and logical names which - historically are mapped to enviroment varables and returned by getenv() */ - { - char *vname = alloca (length + 1); - char *value; - strncpy (vname, name, length); - vname[length] = 0; - value = getenv (vname); - if (value != 0) - { - char *sptr; - int scnt; - - sptr = value; - scnt = 0; - - while ((sptr = strchr (sptr, '$'))) - { - scnt++; - sptr++; - } - - if (scnt > 0) - { - char *nvalue; - char *nptr; - - nvalue = alloca (strlen (value) + scnt + 1); - sptr = value; - nptr = nvalue; - - while (*sptr) - { - if (*sptr == '$') - { - *nptr++ = '$'; - *nptr++ = '$'; - } - else - { - *nptr++ = *sptr; - } - sptr++; - } - - *nptr = '\0'; - return define_variable (vname, length, nvalue, o_env, 1); - - } - - return define_variable (vname, length, value, o_env, 1); - } - } -#endif /* VMS */ - - return 0; -} - -/* Lookup a variable whose name is a string starting at NAME - and with LENGTH chars in set SET. NAME need not be null-terminated. - Returns address of the 'struct variable' containing all info - on the variable, or nil if no such variable is defined. */ - -struct variable * -lookup_variable_in_set (const char *name, unsigned int length, - const struct variable_set *set) -{ - struct variable var_key; - - var_key.name = (char *) name; - var_key.length = length; - - return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); -} - -/* Initialize FILE's variable set list. If FILE already has a variable set - list, the topmost variable set is left intact, but the the rest of the - chain is replaced with FILE->parent's setlist. If FILE is a double-colon - rule, then we will use the "root" double-colon target's variable set as the - parent of FILE's variable set. - - If we're READING a makefile, don't do the pattern variable search now, - since the pattern variable might not have been defined yet. */ - -void -initialize_file_variables (struct file *file, int reading) -{ - struct variable_set_list *l = file->variables; - - if (l == 0) - { - l = (struct variable_set_list *) - xmalloc (sizeof (struct variable_set_list)); - l->set = xmalloc (sizeof (struct variable_set)); - hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); - file->variables = l; - } - - /* If this is a double-colon, then our "parent" is the "root" target for - this double-colon rule. Since that rule has the same name, parent, - etc. we can just use its variables as the "next" for ours. */ - - if (file->double_colon && file->double_colon != file) - { - initialize_file_variables (file->double_colon, reading); - l->next = file->double_colon->variables; - l->next_is_parent = 0; - return; - } - - if (file->parent == 0) - l->next = &global_setlist; - else - { - initialize_file_variables (file->parent, reading); - l->next = file->parent->variables; - } - l->next_is_parent = 1; - - /* If we're not reading makefiles and we haven't looked yet, see if - we can find pattern variables for this target. */ - - if (!reading && !file->pat_searched) - { - struct pattern_var *p; - - p = lookup_pattern_var (0, file->name); - if (p != 0) - { - struct variable_set_list *global = current_variable_set_list; - - /* We found at least one. Set up a new variable set to accumulate - all the pattern variables that match this target. */ - - file->pat_variables = create_new_variable_set (); - current_variable_set_list = file->pat_variables; - - do - { - /* We found one, so insert it into the set. */ - - struct variable *v; - - if (p->variable.flavor == f_simple) - { - v = define_variable_loc ( - p->variable.name, strlen (p->variable.name), - p->variable.value, p->variable.origin, - 0, &p->variable.fileinfo); - - v->flavor = f_simple; - } - else - { - v = do_variable_definition ( - &p->variable.fileinfo, p->variable.name, - p->variable.value, p->variable.origin, - p->variable.flavor, 1); - } - - /* Also mark it as a per-target and copy export status. */ - v->per_target = p->variable.per_target; - v->export = p->variable.export; - v->private_var = p->variable.private_var; - } - while ((p = lookup_pattern_var (p, file->name)) != 0); - - current_variable_set_list = global; - } - file->pat_searched = 1; - } - - /* If we have a pattern variable match, set it up. */ - - if (file->pat_variables != 0) - { - file->pat_variables->next = l->next; - file->pat_variables->next_is_parent = l->next_is_parent; - l->next = file->pat_variables; - l->next_is_parent = 0; - } -} - -/* Pop the top set off the current variable set list, - and free all its storage. */ - -struct variable_set_list * -create_new_variable_set (void) -{ - register struct variable_set_list *setlist; - register struct variable_set *set; - - set = xmalloc (sizeof (struct variable_set)); - hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); - - setlist = (struct variable_set_list *) - xmalloc (sizeof (struct variable_set_list)); - setlist->set = set; - setlist->next = current_variable_set_list; - setlist->next_is_parent = 0; - - return setlist; -} - -/* Create a new variable set and push it on the current setlist. - If we're pushing a global scope (that is, the current scope is the global - scope) then we need to "push" it the other way: file variable sets point - directly to the global_setlist so we need to replace that with the new one. - */ - -struct variable_set_list * -push_new_variable_scope (void) -{ - current_variable_set_list = create_new_variable_set (); - if (current_variable_set_list->next == &global_setlist) - { - /* It was the global, so instead of new -> &global we want to replace - &global with the new one and have &global -> new, with current still - pointing to &global */ - struct variable_set *set = current_variable_set_list->set; - current_variable_set_list->set = global_setlist.set; - global_setlist.set = set; - current_variable_set_list->next = global_setlist.next; - global_setlist.next = current_variable_set_list; - current_variable_set_list = &global_setlist; - } - return (current_variable_set_list); -} - -void -pop_variable_scope (void) -{ - struct variable_set_list *setlist; - struct variable_set *set; - - /* Can't call this if there's no scope to pop! */ - assert (current_variable_set_list->next != NULL); - - if (current_variable_set_list != &global_setlist) - { - /* We're not pointing to the global setlist, so pop this one. */ - setlist = current_variable_set_list; - set = setlist->set; - current_variable_set_list = setlist->next; - } - else - { - /* This set is the one in the global_setlist, but there is another global - set beyond that. We want to copy that set to global_setlist, then - delete what used to be in global_setlist. */ - setlist = global_setlist.next; - set = global_setlist.set; - global_setlist.set = setlist->set; - global_setlist.next = setlist->next; - global_setlist.next_is_parent = setlist->next_is_parent; - } - - /* Free the one we no longer need. */ - free (setlist); - hash_map (&set->table, free_variable_name_and_value); - hash_free (&set->table, 1); - free (set); -} - -/* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */ - -static void -merge_variable_sets (struct variable_set *to_set, - struct variable_set *from_set) -{ - struct variable **from_var_slot = (struct variable **) from_set->table.ht_vec; - struct variable **from_var_end = from_var_slot + from_set->table.ht_size; - - int inc = to_set == &global_variable_set ? 1 : 0; - - for ( ; from_var_slot < from_var_end; from_var_slot++) - if (! HASH_VACANT (*from_var_slot)) - { - struct variable *from_var = *from_var_slot; - struct variable **to_var_slot - = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot); - if (HASH_VACANT (*to_var_slot)) - { - hash_insert_at (&to_set->table, from_var, to_var_slot); - variable_changenum += inc; - } - else - { - /* GKM FIXME: delete in from_set->table */ - free (from_var->value); - free (from_var); - } - } -} - -/* Merge SETLIST1 into SETLIST0, freeing unused storage in SETLIST1. */ - -void -merge_variable_set_lists (struct variable_set_list **setlist0, - struct variable_set_list *setlist1) -{ - struct variable_set_list *to = *setlist0; - struct variable_set_list *last0 = 0; - - /* If there's nothing to merge, stop now. */ - if (!setlist1) - return; - - /* This loop relies on the fact that all setlists terminate with the global - setlist (before NULL). If that's not true, arguably we SHOULD die. */ - if (to) - while (setlist1 != &global_setlist && to != &global_setlist) - { - struct variable_set_list *from = setlist1; - setlist1 = setlist1->next; - - merge_variable_sets (to->set, from->set); - - last0 = to; - to = to->next; - } - - if (setlist1 != &global_setlist) - { - if (last0 == 0) - *setlist0 = setlist1; - else - last0->next = setlist1; - } -} - -/* Define the automatic variables, and record the addresses - of their structures so we can change their values quickly. */ - -void -define_automatic_variables (void) -{ - struct variable *v; - char buf[200]; - - sprintf (buf, "%u", makelevel); - define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0); - - sprintf (buf, "%s%s%s", - version_string, - (remote_description == 0 || remote_description[0] == '\0') - ? "" : "-", - (remote_description == 0 || remote_description[0] == '\0') - ? "" : remote_description); - define_variable_cname ("MAKE_VERSION", buf, o_default, 0); - define_variable_cname ("MAKE_HOST", make_host, o_default, 0); - -#ifdef __MSDOS__ - /* Allow to specify a special shell just for Make, - and use $COMSPEC as the default $SHELL when appropriate. */ - { - static char shell_str[] = "SHELL"; - const int shlen = sizeof (shell_str) - 1; - struct variable *mshp = lookup_variable ("MAKESHELL", 9); - struct variable *comp = lookup_variable ("COMSPEC", 7); - - /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */ - if (mshp) - (void) define_variable (shell_str, shlen, - mshp->value, o_env_override, 0); - else if (comp) - { - /* $(COMSPEC) shouldn't override $(SHELL). */ - struct variable *shp = lookup_variable (shell_str, shlen); - - if (!shp) - (void) define_variable (shell_str, shlen, comp->value, o_env, 0); - } - } -#elif defined(__EMX__) - { - static char shell_str[] = "SHELL"; - const int shlen = sizeof (shell_str) - 1; - struct variable *shell = lookup_variable (shell_str, shlen); - struct variable *replace = lookup_variable ("MAKESHELL", 9); - - /* if $MAKESHELL is defined in the environment assume o_env_override */ - if (replace && *replace->value && replace->origin == o_env) - replace->origin = o_env_override; - - /* if $MAKESHELL is not defined use $SHELL but only if the variable - did not come from the environment */ - if (!replace || !*replace->value) - if (shell && *shell->value && (shell->origin == o_env - || shell->origin == o_env_override)) - { - /* overwrite whatever we got from the environment */ - free (shell->value); - shell->value = xstrdup (default_shell); - shell->origin = o_default; - } - - /* Some people do not like cmd to be used as the default - if $SHELL is not defined in the Makefile. - With -DNO_CMD_DEFAULT you can turn off this behaviour */ -# ifndef NO_CMD_DEFAULT - /* otherwise use $COMSPEC */ - if (!replace || !*replace->value) - replace = lookup_variable ("COMSPEC", 7); - - /* otherwise use $OS2_SHELL */ - if (!replace || !*replace->value) - replace = lookup_variable ("OS2_SHELL", 9); -# else -# warning NO_CMD_DEFAULT: GNU make will not use CMD.EXE as default shell -# endif - - if (replace && *replace->value) - /* overwrite $SHELL */ - (void) define_variable (shell_str, shlen, replace->value, - replace->origin, 0); - else - /* provide a definition if there is none */ - (void) define_variable (shell_str, shlen, default_shell, - o_default, 0); - } - -#endif - - /* This won't override any definition, but it will provide one if there - isn't one there. */ - v = define_variable_cname ("SHELL", default_shell, o_default, 0); -#ifdef __MSDOS__ - v->export = v_export; /* Export always SHELL. */ -#endif - - /* On MSDOS we do use SHELL from environment, since it isn't a standard - environment variable on MSDOS, so whoever sets it, does that on purpose. - On OS/2 we do not use SHELL from environment but we have already handled - that problem above. */ -#if !defined(__MSDOS__) && !defined(__EMX__) - /* Don't let SHELL come from the environment. */ - if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) - { - free (v->value); - v->origin = o_file; - v->value = xstrdup (default_shell); - } -#endif - - /* Make sure MAKEFILES gets exported if it is set. */ - v = define_variable_cname ("MAKEFILES", "", o_default, 0); - v->export = v_ifset; - - /* Define the magic D and F variables in terms of - the automatic variables they are variations of. */ - -#if defined(__MSDOS__) || defined(WINDOWS32) - /* For consistency, remove the trailing backslash as well as slash. */ - define_variable_cname ("@D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $@)))", - o_automatic, 1); - define_variable_cname ("%D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $%)))", - o_automatic, 1); - define_variable_cname ("*D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $*)))", - o_automatic, 1); - define_variable_cname ("<D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $<)))", - o_automatic, 1); - define_variable_cname ("?D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $?)))", - o_automatic, 1); - define_variable_cname ("^D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $^)))", - o_automatic, 1); - define_variable_cname ("+D", "$(patsubst %/,%,$(patsubst %\\,%,$(dir $+)))", - o_automatic, 1); -#else /* not __MSDOS__, not WINDOWS32 */ - define_variable_cname ("@D", "$(patsubst %/,%,$(dir $@))", o_automatic, 1); - define_variable_cname ("%D", "$(patsubst %/,%,$(dir $%))", o_automatic, 1); - define_variable_cname ("*D", "$(patsubst %/,%,$(dir $*))", o_automatic, 1); - define_variable_cname ("<D", "$(patsubst %/,%,$(dir $<))", o_automatic, 1); - define_variable_cname ("?D", "$(patsubst %/,%,$(dir $?))", o_automatic, 1); - define_variable_cname ("^D", "$(patsubst %/,%,$(dir $^))", o_automatic, 1); - define_variable_cname ("+D", "$(patsubst %/,%,$(dir $+))", o_automatic, 1); -#endif - define_variable_cname ("@F", "$(notdir $@)", o_automatic, 1); - define_variable_cname ("%F", "$(notdir $%)", o_automatic, 1); - define_variable_cname ("*F", "$(notdir $*)", o_automatic, 1); - define_variable_cname ("<F", "$(notdir $<)", o_automatic, 1); - define_variable_cname ("?F", "$(notdir $?)", o_automatic, 1); - define_variable_cname ("^F", "$(notdir $^)", o_automatic, 1); - define_variable_cname ("+F", "$(notdir $+)", o_automatic, 1); -} - -int export_all_variables; - -/* Create a new environment for FILE's commands. - If FILE is nil, this is for the 'shell' function. - The child's MAKELEVEL variable is incremented. */ - -char ** -target_environment (struct file *file) -{ - struct variable_set_list *set_list; - register struct variable_set_list *s; - struct hash_table table; - struct variable **v_slot; - struct variable **v_end; - struct variable makelevel_key; - char **result_0; - char **result; - - if (file == 0) - set_list = current_variable_set_list; - else - set_list = file->variables; - - hash_init (&table, VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); - - /* Run through all the variable sets in the list, - accumulating variables in TABLE. */ - for (s = set_list; s != 0; s = s->next) - { - struct variable_set *set = s->set; - v_slot = (struct variable **) set->table.ht_vec; - v_end = v_slot + set->table.ht_size; - for ( ; v_slot < v_end; v_slot++) - if (! HASH_VACANT (*v_slot)) - { - struct variable **new_slot; - struct variable *v = *v_slot; - - /* If this is a per-target variable and it hasn't been touched - already then look up the global version and take its export - value. */ - if (v->per_target && v->export == v_default) - { - struct variable *gv; - - gv = lookup_variable_in_set (v->name, strlen (v->name), - &global_variable_set); - if (gv) - v->export = gv->export; - } - - switch (v->export) - { - case v_default: - if (v->origin == o_default || v->origin == o_automatic) - /* Only export default variables by explicit request. */ - continue; - - /* The variable doesn't have a name that can be exported. */ - if (! v->exportable) - continue; - - if (! export_all_variables - && v->origin != o_command - && v->origin != o_env && v->origin != o_env_override) - continue; - break; - - case v_export: - break; - - case v_noexport: - { - /* If this is the SHELL variable and it's not exported, - then add the value from our original environment, if - the original environment defined a value for SHELL. */ - if (streq (v->name, "SHELL") && shell_var.value) - { - v = &shell_var; - break; - } - continue; - } - - case v_ifset: - if (v->origin == o_default) - continue; - break; - } - - new_slot = (struct variable **) hash_find_slot (&table, v); - if (HASH_VACANT (*new_slot)) - hash_insert_at (&table, v, new_slot); - } - } - - makelevel_key.name = (char *)MAKELEVEL_NAME; - makelevel_key.length = MAKELEVEL_LENGTH; - hash_delete (&table, &makelevel_key); - - result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *)); - - v_slot = (struct variable **) table.ht_vec; - v_end = v_slot + table.ht_size; - for ( ; v_slot < v_end; v_slot++) - if (! HASH_VACANT (*v_slot)) - { - struct variable *v = *v_slot; - - /* If V is recursively expanded and didn't come from the environment, - expand its value. If it came from the environment, it should - go back into the environment unchanged. */ - if (v->recursive - && v->origin != o_env && v->origin != o_env_override) - { - char *value = recursively_expand_for_file (v, file); -#ifdef WINDOWS32 - if (strcmp (v->name, "Path") == 0 || - strcmp (v->name, "PATH") == 0) - convert_Path_to_windows32 (value, ';'); -#endif - *result++ = xstrdup (concat (3, v->name, "=", value)); - free (value); - } - else - { -#ifdef WINDOWS32 - if (strcmp (v->name, "Path") == 0 || - strcmp (v->name, "PATH") == 0) - convert_Path_to_windows32 (v->value, ';'); -#endif - *result++ = xstrdup (concat (3, v->name, "=", v->value)); - } - } - - *result = xmalloc (100); - sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1); - *++result = 0; - - hash_free (&table, 0); - - return result_0; -} - -static struct variable * -set_special_var (struct variable *var) -{ - if (streq (var->name, RECIPEPREFIX_NAME)) - { - /* The user is resetting the command introduction prefix. This has to - happen immediately, so that subsequent rules are interpreted - properly. */ - cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0]; - } - - return var; -} - -/* Given a string, shell-execute it and return a malloc'ed string of the - * result. This removes only ONE newline (if any) at the end, for maximum - * compatibility with the *BSD makes. If it fails, returns NULL. */ - -static char * -shell_result (const char *p) -{ - char *buf; - unsigned int len; - char *args[2]; - char *result; - - install_variable_buffer (&buf, &len); - - args[0] = (char *) p; - args[1] = NULL; - variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1); - result = strdup (variable_buffer); - - restore_variable_buffer (buf, len); - return result; -} - -/* Given a variable, a value, and a flavor, define the variable. - See the try_variable_definition() function for details on the parameters. */ - -struct variable * -do_variable_definition (const floc *flocp, const char *varname, - const char *value, enum variable_origin origin, - enum variable_flavor flavor, int target_var) -{ - const char *p; - char *alloc_value = NULL; - struct variable *v; - int append = 0; - int conditional = 0; - - /* Calculate the variable's new value in VALUE. */ - - switch (flavor) - { - default: - case f_bogus: - /* Should not be possible. */ - abort (); - case f_simple: - /* A simple variable definition "var := value". Expand the value. - We have to allocate memory since otherwise it'll clobber the - variable buffer, and we may still need that if we're looking at a - target-specific variable. */ - p = alloc_value = allocated_variable_expand (value); - break; - case f_shell: - { - /* A shell definition "var != value". Expand value, pass it to - the shell, and store the result in recursively-expanded var. */ - char *q = allocated_variable_expand (value); - p = alloc_value = shell_result (q); - free (q); - flavor = f_recursive; - break; - } - case f_conditional: - /* A conditional variable definition "var ?= value". - The value is set IFF the variable is not defined yet. */ - v = lookup_variable (varname, strlen (varname)); - if (v) - return v->special ? set_special_var (v) : v; - - conditional = 1; - flavor = f_recursive; - /* FALLTHROUGH */ - case f_recursive: - /* A recursive variable definition "var = value". - The value is used verbatim. */ - p = value; - break; - case f_append: - { - /* If we have += but we're in a target variable context, we want to - append only with other variables in the context of this target. */ - if (target_var) - { - append = 1; - v = lookup_variable_in_set (varname, strlen (varname), - current_variable_set_list->set); - - /* Don't append from the global set if a previous non-appending - target-specific variable definition exists. */ - if (v && !v->append) - append = 0; - } - else - v = lookup_variable (varname, strlen (varname)); - - if (v == 0) - { - /* There was no old value. - This becomes a normal recursive definition. */ - p = value; - flavor = f_recursive; - } - else - { - /* Paste the old and new values together in VALUE. */ - - unsigned int oldlen, vallen; - const char *val; - char *tp = NULL; - - val = value; - if (v->recursive) - /* The previous definition of the variable was recursive. - The new value is the unexpanded old and new values. */ - flavor = f_recursive; - else - /* The previous definition of the variable was simple. - The new value comes from the old value, which was expanded - when it was set; and from the expanded new value. Allocate - memory for the expansion as we may still need the rest of the - buffer if we're looking at a target-specific variable. */ - val = tp = allocated_variable_expand (val); - - oldlen = strlen (v->value); - vallen = strlen (val); - p = alloc_value = xmalloc (oldlen + 1 + vallen + 1); - memcpy (alloc_value, v->value, oldlen); - alloc_value[oldlen] = ' '; - memcpy (&alloc_value[oldlen + 1], val, vallen + 1); - - free (tp); - } - } - } - -#ifdef __MSDOS__ - /* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but - non-Unix systems don't conform to this default configuration (in - fact, most of them don't even have '/bin'). On the other hand, - $SHELL in the environment, if set, points to the real pathname of - the shell. - Therefore, we generally won't let lines like "SHELL=/bin/sh" from - the Makefile override $SHELL from the environment. But first, we - look for the basename of the shell in the directory where SHELL= - points, and along the $PATH; if it is found in any of these places, - we define $SHELL to be the actual pathname of the shell. Thus, if - you have bash.exe installed as d:/unix/bash.exe, and d:/unix is on - your $PATH, then SHELL=/usr/local/bin/bash will have the effect of - defining SHELL to be "d:/unix/bash.exe". */ - if ((origin == o_file || origin == o_override) - && strcmp (varname, "SHELL") == 0) - { - PATH_VAR (shellpath); - extern char * __dosexec_find_on_path (const char *, char *[], char *); - - /* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */ - if (__dosexec_find_on_path (p, NULL, shellpath)) - { - char *tp; - - for (tp = shellpath; *tp; tp++) - if (*tp == '\\') - *tp = '/'; - - v = define_variable_loc (varname, strlen (varname), - shellpath, origin, flavor == f_recursive, - flocp); - } - else - { - const char *shellbase, *bslash; - struct variable *pathv = lookup_variable ("PATH", 4); - char *path_string; - char *fake_env[2]; - size_t pathlen = 0; - - shellbase = strrchr (p, '/'); - bslash = strrchr (p, '\\'); - if (!shellbase || bslash > shellbase) - shellbase = bslash; - if (!shellbase && p[1] == ':') - shellbase = p + 1; - if (shellbase) - shellbase++; - else - shellbase = p; - - /* Search for the basename of the shell (with standard - executable extensions) along the $PATH. */ - if (pathv) - pathlen = strlen (pathv->value); - path_string = xmalloc (5 + pathlen + 2 + 1); - /* On MSDOS, current directory is considered as part of $PATH. */ - sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : ""); - fake_env[0] = path_string; - fake_env[1] = 0; - if (__dosexec_find_on_path (shellbase, fake_env, shellpath)) - { - char *tp; - - for (tp = shellpath; *tp; tp++) - if (*tp == '\\') - *tp = '/'; - - v = define_variable_loc (varname, strlen (varname), - shellpath, origin, - flavor == f_recursive, flocp); - } - else - v = lookup_variable (varname, strlen (varname)); - - free (path_string); - } - } - else -#endif /* __MSDOS__ */ -#ifdef WINDOWS32 - if ((origin == o_file || origin == o_override || origin == o_command) - && streq (varname, "SHELL")) - { - extern const char *default_shell; - - /* Call shell locator function. If it returns TRUE, then - set no_default_sh_exe to indicate sh was found and - set new value for SHELL variable. */ - - if (find_and_set_default_shell (p)) - { - v = define_variable_in_set (varname, strlen (varname), default_shell, - origin, flavor == f_recursive, - (target_var - ? current_variable_set_list->set - : NULL), - flocp); - no_default_sh_exe = 0; - } - else - { - char *tp = alloc_value; - - alloc_value = allocated_variable_expand (p); - - if (find_and_set_default_shell (alloc_value)) - { - v = define_variable_in_set (varname, strlen (varname), p, - origin, flavor == f_recursive, - (target_var - ? current_variable_set_list->set - : NULL), - flocp); - no_default_sh_exe = 0; - } - else - v = lookup_variable (varname, strlen (varname)); - - free (tp); - } - } - else -#endif - - /* If we are defining variables inside an $(eval ...), we might have a - different variable context pushed, not the global context (maybe we're - inside a $(call ...) or something. Since this function is only ever - invoked in places where we want to define globally visible variables, - make sure we define this variable in the global set. */ - - v = define_variable_in_set (varname, strlen (varname), p, - origin, flavor == f_recursive, - (target_var - ? current_variable_set_list->set : NULL), - flocp); - v->append = append; - v->conditional = conditional; - - free (alloc_value); - - return v->special ? set_special_var (v) : v; -} - -/* Parse P (a null-terminated string) as a variable definition. - - If it is not a variable definition, return NULL and the contents of *VAR - are undefined, except NAME is set to the first non-space character or NIL. - - If it is a variable definition, return a pointer to the char after the - assignment token and set the following fields (only) of *VAR: - name : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!) - length : length of the variable name - value : value of the variable (nul-terminated) - flavor : flavor of the variable - Other values in *VAR are unchanged. - */ - -char * -parse_variable_definition (const char *p, struct variable *var) -{ - int wspace = 0; - const char *e = NULL; - - NEXT_TOKEN (p); - var->name = (char *)p; - var->length = 0; - - while (1) - { - int c = *p++; - - /* If we find a comment or EOS, it's not a variable definition. */ - if (STOP_SET (c, MAP_COMMENT|MAP_NUL)) - return NULL; - - if (c == '$') - { - /* This begins a variable expansion reference. Make sure we don't - treat chars inside the reference as assignment tokens. */ - char closeparen; - unsigned int count; - - c = *p++; - if (c == '(') - closeparen = ')'; - else if (c == '{') - closeparen = '}'; - else if (c == '\0') - return NULL; - else - /* '$$' or '$X'. Either way, nothing special to do here. */ - continue; - - /* P now points past the opening paren or brace. - Count parens or braces until it is matched. */ - for (count = 1; *p != '\0'; ++p) - { - if (*p == closeparen && --count == 0) - { - ++p; - break; - } - if (*p == c) - ++count; - } - continue; - } - - /* If we find whitespace skip it, and remember we found it. */ - if (ISBLANK (c)) - { - wspace = 1; - e = p - 1; - NEXT_TOKEN (p); - c = *p; - if (c == '\0') - return NULL; - ++p; - } - - - if (c == '=') - { - var->flavor = f_recursive; - if (! e) - e = p - 1; - break; - } - - /* Match assignment variants (:=, +=, ?=, !=) */ - if (*p == '=') - { - switch (c) - { - case ':': - var->flavor = f_simple; - break; - case '+': - var->flavor = f_append; - break; - case '?': - var->flavor = f_conditional; - break; - case '!': - var->flavor = f_shell; - break; - default: - /* If we skipped whitespace, non-assignments means no var. */ - if (wspace) - return NULL; - - /* Might be assignment, or might be $= or #=. Check. */ - continue; - } - if (! e) - e = p - 1; - ++p; - break; - } - - /* Check for POSIX ::= syntax */ - if (c == ':') - { - /* A colon other than :=/::= is not a variable defn. */ - if (*p != ':' || p[1] != '=') - return NULL; - - /* POSIX allows ::= to be the same as GNU make's := */ - var->flavor = f_simple; - if (! e) - e = p - 1; - p += 2; - break; - } - - /* If we skipped whitespace, non-assignments means no var. */ - if (wspace) - return NULL; - } - - var->length = e - var->name; - var->value = next_token (p); - return (char *)p; -} - -/* Try to interpret LINE (a null-terminated string) as a variable definition. - - If LINE was recognized as a variable definition, a pointer to its 'struct - variable' is returned. If LINE is not a variable definition, NULL is - returned. */ - -struct variable * -assign_variable_definition (struct variable *v, const char *line) -{ - char *name; - - if (!parse_variable_definition (line, v)) - return NULL; - - /* Expand the name, so "$(foo)bar = baz" works. */ - name = alloca (v->length + 1); - memcpy (name, v->name, v->length); - name[v->length] = '\0'; - v->name = allocated_variable_expand (name); - - if (v->name[0] == '\0') - O (fatal, &v->fileinfo, _("empty variable name")); - - return v; -} - -/* Try to interpret LINE (a null-terminated string) as a variable definition. - - ORIGIN may be o_file, o_override, o_env, o_env_override, - or o_command specifying that the variable definition comes - from a makefile, an override directive, the environment with - or without the -e switch, or the command line. - - See the comments for assign_variable_definition(). - - If LINE was recognized as a variable definition, a pointer to its 'struct - variable' is returned. If LINE is not a variable definition, NULL is - returned. */ - -struct variable * -try_variable_definition (const floc *flocp, const char *line, - enum variable_origin origin, int target_var) -{ - struct variable v; - struct variable *vp; - - if (flocp != 0) - v.fileinfo = *flocp; - else - v.fileinfo.filenm = 0; - - if (!assign_variable_definition (&v, line)) - return 0; - - vp = do_variable_definition (flocp, v.name, v.value, - origin, v.flavor, target_var); - - free (v.name); - - return vp; -} - -/* Print information for variable V, prefixing it with PREFIX. */ - -static void -print_variable (const void *item, void *arg) -{ - const struct variable *v = item; - const char *prefix = arg; - const char *origin; - - switch (v->origin) - { - case o_automatic: - origin = _("automatic"); - break; - case o_default: - origin = _("default"); - break; - case o_env: - origin = _("environment"); - break; - case o_file: - origin = _("makefile"); - break; - case o_env_override: - origin = _("environment under -e"); - break; - case o_command: - origin = _("command line"); - break; - case o_override: - origin = _("'override' directive"); - break; - case o_invalid: - default: - abort (); - } - fputs ("# ", stdout); - fputs (origin, stdout); - if (v->private_var) - fputs (" private", stdout); - if (v->fileinfo.filenm) - printf (_(" (from '%s', line %lu)"), - v->fileinfo.filenm, v->fileinfo.lineno + v->fileinfo.offset); - putchar ('\n'); - fputs (prefix, stdout); - - /* Is this a 'define'? */ - if (v->recursive && strchr (v->value, '\n') != 0) - printf ("define %s\n%s\nendef\n", v->name, v->value); - else - { - char *p; - - printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); - - /* Check if the value is just whitespace. */ - p = next_token (v->value); - if (p != v->value && *p == '\0') - /* All whitespace. */ - printf ("$(subst ,,%s)", v->value); - else if (v->recursive) - fputs (v->value, stdout); - else - /* Double up dollar signs. */ - for (p = v->value; *p != '\0'; ++p) - { - if (*p == '$') - putchar ('$'); - putchar (*p); - } - putchar ('\n'); - } -} - - -static void -print_auto_variable (const void *item, void *arg) -{ - const struct variable *v = item; - - if (v->origin == o_automatic) - print_variable (item, arg); -} - - -static void -print_noauto_variable (const void *item, void *arg) -{ - const struct variable *v = item; - - if (v->origin != o_automatic) - print_variable (item, arg); -} - - -/* Print all the variables in SET. PREFIX is printed before - the actual variable definitions (everything else is comments). */ - -static void -print_variable_set (struct variable_set *set, const char *prefix, int pauto) -{ - hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable), - (void *)prefix); - - fputs (_("# variable set hash-table stats:\n"), stdout); - fputs ("# ", stdout); - hash_print_stats (&set->table, stdout); - putc ('\n', stdout); -} - -/* Print the data base of variables. */ - -void -print_variable_data_base (void) -{ - puts (_("\n# Variables\n")); - - print_variable_set (&global_variable_set, "", 0); - - puts (_("\n# Pattern-specific Variable Values")); - - { - struct pattern_var *p; - unsigned int rules = 0; - - for (p = pattern_vars; p != 0; p = p->next) - { - ++rules; - printf ("\n%s :\n", p->target); - print_variable (&p->variable, (void *)"# "); - } - - if (rules == 0) - puts (_("\n# No pattern-specific variable values.")); - else - printf (_("\n# %u pattern-specific variable values"), rules); - } -} - - -/* Print all the local variables of FILE. */ - -void -print_file_variables (const struct file *file) -{ - if (file->variables != 0) - print_variable_set (file->variables->set, "# ", 1); -} - -void -print_target_variables (const struct file *file) -{ - if (file->variables != 0) - { - int l = strlen (file->name); - char *t = alloca (l + 3); - - strcpy (t, file->name); - t[l] = ':'; - t[l+1] = ' '; - t[l+2] = '\0'; - - hash_map_arg (&file->variables->set->table, print_noauto_variable, t); - } -} - -#ifdef WINDOWS32 -void -sync_Path_environment (void) -{ - char *path = allocated_variable_expand ("$(PATH)"); - static char *environ_path = NULL; - - if (!path) - return; - - /* If done this before, free the previous entry before allocating new one. */ - free (environ_path); - - /* Create something WINDOWS32 world can grok. */ - convert_Path_to_windows32 (path, ';'); - environ_path = xstrdup (concat (3, "PATH", "=", path)); - putenv (environ_path); - free (path); -} -#endif |