From e15597c3e85dedc015ff923a88febd46a1551f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20THIERRY?= Date: Wed, 5 Nov 2014 08:27:15 +0100 Subject: Imported Upstream version 4.0 --- variable.c | 702 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 403 insertions(+), 299 deletions(-) (limited to 'variable.c') diff --git a/variable.c b/variable.c index 915be20..2ff14b6 100644 --- a/variable.c +++ b/variable.c @@ -1,7 +1,5 @@ /* Internals of variables for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, -2010 Free Software Foundation, Inc. +Copyright (C) 1988-2013 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 @@ -16,12 +14,12 @@ 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 . */ -#include "make.h" +#include "makeint.h" #include -#include "dep.h" #include "filedef.h" +#include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" @@ -100,7 +98,7 @@ static struct pattern_var * lookup_pattern_var (struct pattern_var *start, const char *target) { struct pattern_var *p; - unsigned int targlen = strlen(target); + unsigned int targlen = strlen (target); for (p = start ? start->next : pattern_vars; p != 0; p = p->next) { @@ -160,14 +158,14 @@ variable_hash_cmp (const void *xv, const void *yv) return_STRING_N_COMPARE (x->name, y->name, x->length); } -#ifndef VARIABLE_BUCKETS -#define VARIABLE_BUCKETS 523 +#ifndef VARIABLE_BUCKETS +#define VARIABLE_BUCKETS 523 #endif -#ifndef PERFILE_VARIABLE_BUCKETS -#define PERFILE_VARIABLE_BUCKETS 23 +#ifndef PERFILE_VARIABLE_BUCKETS +#define PERFILE_VARIABLE_BUCKETS 23 #endif -#ifndef SMALL_SCOPE_VARIABLE_BUCKETS -#define SMALL_SCOPE_VARIABLE_BUCKETS 13 +#ifndef SMALL_SCOPE_VARIABLE_BUCKETS +#define SMALL_SCOPE_VARIABLE_BUCKETS 13 #endif static struct variable_set global_variable_set; @@ -181,7 +179,7 @@ void init_hash_global_variable_set (void) { hash_init (&global_variable_set.table, VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); + variable_hash_1, variable_hash_2, variable_hash_cmp); } /* Define variable named NAME with value VALUE in SET. VALUE is copied. @@ -195,7 +193,7 @@ 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 struct floc *flocp) + const gmk_floc *flocp) { struct variable *v; struct variable **var_slot; @@ -215,25 +213,25 @@ define_variable_in_set (const char *name, unsigned int length, 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; + /* 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 the old definition is from a stronger source + than this one, don't redefine it. */ if ((int) origin >= (int) v->origin) - { - if (v->value != 0) - free (v->value); - v->value = xstrdup (value); + { + if (v->value != 0) + free (v->value); + v->value = xstrdup (value); if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; - v->origin = origin; - v->recursive = recursive; - } + v->origin = origin; + v->recursive = recursive; + } return v; } @@ -282,7 +280,21 @@ define_variable_in_set (const char *name, unsigned int length, variable (makefile, command line or environment). */ static void -free_variable_name_and_value (const void *item); +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, @@ -307,17 +319,17 @@ undefine_variable_in_set (const char *name, unsigned int length, 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; + /* 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; /* If the definition is from a stronger source than this one, don't undefine it. */ if ((int) origin >= (int) v->origin) - { + { hash_delete_at (&set->table, var_slot); free_variable_name_and_value (v); - } + } } } @@ -412,7 +424,7 @@ lookup_special_var (struct variable *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 + Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * @@ -433,7 +445,7 @@ lookup_variable (const char *name, unsigned int length) 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; + return v->special ? lookup_special_var (v) : v; is_parent |= setlist->next_is_parent; } @@ -499,7 +511,7 @@ lookup_variable (const char *name, unsigned int length) /* 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 + Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * @@ -531,7 +543,7 @@ initialize_file_variables (struct file *file, int reading) if (l == 0) { l = (struct variable_set_list *) - xmalloc (sizeof (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); @@ -634,7 +646,7 @@ create_new_variable_set (void) set = xmalloc (sizeof (struct variable_set)); hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); + variable_hash_1, variable_hash_2, variable_hash_cmp); setlist = (struct variable_set_list *) xmalloc (sizeof (struct variable_set_list)); @@ -645,23 +657,6 @@ create_new_variable_set (void) return setlist; } -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); -} - /* 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 @@ -671,7 +666,7 @@ free_variable_set (struct variable_set_list *list) struct variable_set_list * push_new_variable_scope (void) { - current_variable_set_list = create_new_variable_set(); + 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 @@ -694,7 +689,7 @@ pop_variable_scope (void) struct variable_set *set; /* Can't call this if there's no scope to pop! */ - assert(current_variable_set_list->next != NULL); + assert (current_variable_set_list->next != NULL); if (current_variable_set_list != &global_setlist) { @@ -734,17 +729,17 @@ merge_variable_sets (struct variable_set *to_set, 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); - else - { - /* GKM FIXME: delete in from_set->table */ - free (from_var->value); - free (from_var); - } + 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); + else + { + /* GKM FIXME: delete in from_set->table */ + free (from_var->value); + free (from_var); + } } } @@ -778,9 +773,9 @@ merge_variable_set_lists (struct variable_set_list **setlist0, if (setlist1 != &global_setlist) { if (last0 == 0) - *setlist0 = setlist1; + *setlist0 = setlist1; else - last0->next = setlist1; + last0->next = setlist1; } } @@ -802,12 +797,13 @@ define_automatic_variables (void) 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); + 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, @@ -821,14 +817,14 @@ define_automatic_variables (void) /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */ if (mshp) (void) define_variable (shell_str, shlen, - mshp->value, o_env_override, 0); + mshp->value, o_env_override, 0); else if (comp) { - /* $(COMSPEC) shouldn't override $(SHELL). */ - struct variable *shp = lookup_variable (shell_str, shlen); + /* $(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); + if (!shp) + (void) define_variable (shell_str, shlen, comp->value, o_env, 0); } } #elif defined(__EMX__) @@ -846,13 +842,13 @@ define_automatic_variables (void) 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; - } + || 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. @@ -872,11 +868,11 @@ define_automatic_variables (void) if (replace && *replace->value) /* overwrite $SHELL */ (void) define_variable (shell_str, shlen, replace->value, - replace->origin, 0); + replace->origin, 0); else /* provide a definition if there is none */ (void) define_variable (shell_str, shlen, default_shell, - o_default, 0); + o_default, 0); } #endif @@ -917,7 +913,23 @@ define_automatic_variables (void) define_variable_cname ("?D", "$(dir $?)", o_automatic, 1); define_variable_cname ("^D", "$(dir $^)", o_automatic, 1); define_variable_cname ("+D", "$(dir $+)", o_automatic, 1); -#else +#elif 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 ("variables; hash_init (&table, VARIABLE_BUCKETS, - variable_hash_1, variable_hash_2, variable_hash_cmp); + variable_hash_1, variable_hash_2, variable_hash_cmp); /* Run through all the variable sets in the list, accumulating variables in TABLE. */ @@ -969,68 +981,68 @@ target_environment (struct file *file) 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), + 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; - } + 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; + 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. */ - extern struct variable shell_var; - 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); - } + 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. */ + extern struct variable shell_var; + 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 = MAKELEVEL_NAME; @@ -1044,32 +1056,32 @@ target_environment (struct file *file) 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); + 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, ';'); + 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 - { + *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, ';'); + 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++ = xstrdup (concat (3, v->name, "=", v->value)); + } } *result = xmalloc (100); @@ -1095,11 +1107,34 @@ set_special_var (struct variable *var) 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. */ + +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 struct floc *flocp, const char *varname, +do_variable_definition (const gmk_floc *flocp, const char *varname, const char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var) { @@ -1120,10 +1155,20 @@ do_variable_definition (const struct floc *flocp, const char *varname, 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 + 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. */ @@ -1136,7 +1181,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, /* FALLTHROUGH */ case f_recursive: /* A recursive variable definition "var = value". - The value is used verbatim. */ + The value is used verbatim. */ p = value; break; case f_append: @@ -1201,7 +1246,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, #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, + 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 @@ -1220,62 +1265,62 @@ do_variable_definition (const struct floc *flocp, const char *varname, /* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */ if (__dosexec_find_on_path (p, NULL, shellpath)) - { - char *tp; + { + char *tp; - for (tp = shellpath; *tp; tp++) + for (tp = shellpath; *tp; tp++) if (*tp == '\\') *tp = '/'; - v = define_variable_loc (varname, strlen (varname), + 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++) + { + 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), + v = define_variable_loc (varname, strlen (varname), shellpath, origin, flavor == f_recursive, flocp); - } - else - v = lookup_variable (varname, strlen (varname)); + } + else + v = lookup_variable (varname, strlen (varname)); - free (path_string); - } + free (path_string); + } } else #endif /* __MSDOS__ */ @@ -1286,7 +1331,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, extern char *default_shell; /* Call shell locator function. If it returns TRUE, then - set no_default_sh_exe to indicate sh was found and + set no_default_sh_exe to indicate sh was found and set new value for SHELL variable. */ if (find_and_set_default_shell (p)) @@ -1347,61 +1392,72 @@ do_variable_definition (const struct floc *flocp, const char *varname, /* Parse P (a null-terminated string) as a variable definition. - If it is not a variable definition, return NULL. + 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 *FLAVOR to the type of variable assignment. */ + 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, enum variable_flavor *flavor) +parse_variable_definition (const char *p, struct variable *var) { int wspace = 0; + const char *e = NULL; p = 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 (c == '\0' || c == '#') - return NULL; + 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; - int count; - c = *p++; - if (c == '(') - closeparen = ')'; - else if (c == '{') - closeparen = '}'; - else + { + /* This begins a variable expansion reference. Make sure we don't + treat chars inside the reference as assignment tokens. */ + char closeparen; + int count; + c = *p++; + if (c == '(') + closeparen = ')'; + else if (c == '{') + closeparen = '}'; + 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. */ - count = 0; - for (; *p != '\0'; ++p) - { - if (*p == c) - ++count; - else if (*p == closeparen && --count < 0) - { - ++p; - break; - } - } + continue; + + /* P now points past the opening paren or brace. + Count parens or braces until it is matched. */ + count = 0; + for (; *p != '\0'; ++p) + { + if (*p == c) + ++count; + else if (*p == closeparen && --count < 0) + { + ++p; + break; + } + } continue; - } + } /* If we find whitespace skip it, and remember we found it. */ if (isblank ((unsigned char)c)) { wspace = 1; + e = p - 1; p = next_token (p); c = *p; if (c == '\0') @@ -1411,24 +1467,29 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor) if (c == '=') - { - *flavor = f_recursive; - return (char *)p; - } + { + var->flavor = f_recursive; + if (! e) + e = p - 1; + break; + } - /* Match assignment variants (:=, +=, ?=) */ + /* Match assignment variants (:=, +=, ?=, !=) */ if (*p == '=') { switch (c) { case ':': - *flavor = f_simple; + var->flavor = f_simple; break; case '+': - *flavor = f_append; + var->flavor = f_append; break; case '?': - *flavor = f_conditional; + var->flavor = f_conditional; + break; + case '!': + var->flavor = f_shell; break; default: /* If we skipped whitespace, non-assignments means no var. */ @@ -1438,50 +1499,55 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor) /* Might be assignment, or might be $= or #=. Check. */ continue; } - return (char *)++p; + 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; } - else if (c == ':') - /* A colon other than := is a rule line, not a variable defn. */ - return NULL; /* 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 + 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, char *line) { - char *beg; - char *end; - enum variable_flavor flavor; char *name; - beg = next_token (line); - line = parse_variable_definition (beg, &flavor); - if (!line) + if (!parse_variable_definition (line, v)) return NULL; - end = line - (flavor == f_recursive ? 1 : 2); - while (end > beg && isblank ((unsigned char)end[-1])) - --end; - line = next_token (line); - v->value = line; - v->flavor = flavor; - /* Expand the name, so "$(foo)bar = baz" works. */ - name = alloca (end - beg + 1); - memcpy (name, beg, end - beg); - name[end - beg] = '\0'; + 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') @@ -1499,12 +1565,12 @@ assign_variable_definition (struct variable *v, char *line) See the comments for assign_variable_definition(). - If LINE was recognized as a variable definition, a pointer to its `struct + 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 struct floc *flocp, char *line, +try_variable_definition (const gmk_floc *flocp, char *line, enum variable_origin origin, int target_var) { struct variable v; @@ -1537,6 +1603,9 @@ print_variable (const void *item, void *arg) switch (v->origin) { + case o_automatic: + origin = _("automatic"); + break; case o_default: origin = _("default"); break; @@ -1553,10 +1622,7 @@ print_variable (const void *item, void *arg) origin = _("command line"); break; case o_override: - origin = _("`override' directive"); - break; - case o_automatic: - origin = _("automatic"); + origin = _("'override' directive"); break; case o_invalid: default: @@ -1567,12 +1633,12 @@ print_variable (const void *item, void *arg) if (v->private_var) fputs (" private", stdout); if (v->fileinfo.filenm) - printf (_(" (from `%s', line %lu)"), + printf (_(" (from '%s', line %lu)"), v->fileinfo.filenm, v->fileinfo.lineno); putchar ('\n'); fputs (prefix, stdout); - /* Is this a `define'? */ + /* Is this a 'define'? */ if (v->recursive && strchr (v->value, '\n') != 0) printf ("define %s\n%s\nendef\n", v->name, v->value); else @@ -1584,30 +1650,51 @@ print_variable (const void *item, void *arg) /* 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); + /* All whitespace. */ + printf ("$(subst ,,%s)", v->value); else if (v->recursive) - fputs (v->value, stdout); + fputs (v->value, stdout); else - /* Double up dollar signs. */ - for (p = v->value; *p != '\0'; ++p) - { - if (*p == '$') - putchar ('$'); - putchar (*p); - } + /* 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). */ void -print_variable_set (struct variable_set *set, char *prefix) +print_variable_set (struct variable_set *set, char *prefix, int pauto) { - hash_map_arg (&set->table, print_variable, prefix); + hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable), + prefix); fputs (_("# variable set hash-table stats:\n"), stdout); fputs ("# ", stdout); @@ -1622,7 +1709,7 @@ print_variable_data_base (void) { puts (_("\n# Variables\n")); - print_variable_set (&global_variable_set, ""); + print_variable_set (&global_variable_set, "", 0); puts (_("\n# Pattern-specific Variable Values")); @@ -1651,7 +1738,24 @@ void print_file_variables (const struct file *file) { if (file->variables != 0) - print_variable_set (file->variables->set, "# "); + 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 -- cgit v1.2.3