summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2023-02-26 18:24:30 -0500
committerPaul Smith <psmith@gnu.org>2023-04-01 11:13:12 -0400
commit03ecd94488b85adc38746ec3e7c2a297a522598e (patch)
tree26f47e9d5e1dd9ba730c24f86c099005a923bb68 /src
parent2611e1991fabe2a3ae929c6ebd4afbd4f550f306 (diff)
downloadmake-git-03ecd94488b85adc38746ec3e7c2a297a522598e.tar.gz
Add new warnings invalid-var and invalid-ref
The "invalid-var" warning triggers if the makefile attempts to assign a value to an invalid variable name (a name containing whitespace). The "invalid-ref" warning triggers if the makefile attempts to reference an invalid variable name. Both new warnings have a default action of "warn". * NEWS: Add these new warnings. * doc/make.1: Document them in the man page. * doc/make.texi (Warnings): Document them in the user's manual. * src/warning.h: Add enum values for the new warning types. * src/main.c (initialize_warnings): Initialize the new warnings. * src/variable.h (undefine_variable_in_set, undefine_variable_global): Ask callers to provide a struct floc specifying where the variable is undefined. * src/read.c (do_undefine): Pass floc when undefining. * src/variable.c (check_valid_name): If invalid-var is enabled, check the variable name. (define_variable_in_set): Call it. (undefine_variable_in_set): Ditto. (check_variable_reference): If invalid-ref is enabled, check the variable reference. (lookup_variable): Call it. (lookup_variable_in_set): Ditto. * tests/scripts/options/warn: Add tests for the new warning types.
Diffstat (limited to 'src')
-rw-r--r--src/default.c2
-rw-r--r--src/main.c8
-rw-r--r--src/read.c2
-rw-r--r--src/variable.c53
-rw-r--r--src/variable.h8
-rw-r--r--src/warning.h4
6 files changed, 68 insertions, 9 deletions
diff --git a/src/default.c b/src/default.c
index 82b52c4b..eb8da0cd 100644
--- a/src/default.c
+++ b/src/default.c
@@ -764,5 +764,5 @@ undefine_default_variables (void)
const char **s;
for (s = default_variables; *s != 0; s += 2)
- undefine_variable_global (s[0], strlen (s[0]), o_default);
+ undefine_variable_global (NILF, s[0], strlen (s[0]), o_default);
}
diff --git a/src/main.c b/src/main.c
index 221870ab..843cab09 100644
--- a/src/main.c
+++ b/src/main.c
@@ -667,6 +667,8 @@ static void
initialize_warnings ()
{
/* All warnings must have a default. */
+ default_warnings[wt_invalid_var] = w_warn;
+ default_warnings[wt_invalid_ref] = w_warn;
default_warnings[wt_undefined_var] = w_ignore;
}
@@ -885,7 +887,9 @@ decode_debug_flags (void)
}
static const char *w_state_map[w_error+1] = {NULL, "ignore", "warn", "error"};
-static const char *w_name_map[wt_max] = {"undefined-var"};
+static const char *w_name_map[wt_max] = {"invalid-var",
+ "invalid-ref",
+ "undefined-var"};
#define encode_warn_state(_b,_s) variable_buffer_output (_b, w_state_map[_s], strlen (w_state_map[_s]))
#define encode_warn_name(_b,_t) variable_buffer_output (_b, w_name_map[_t], strlen (w_name_map[_t]))
@@ -906,7 +910,7 @@ decode_warn_state (const char *state, size_t length)
static enum warning_type
decode_warn_name (const char *name, size_t length)
{
- for (enum warning_type wt = wt_undefined_var; wt < wt_max; ++wt)
+ for (enum warning_type wt = wt_invalid_var; wt < wt_max; ++wt)
{
size_t len = strlen (w_name_map[wt]);
if (length == len && strncasecmp (name, w_name_map[wt], length) == 0)
diff --git a/src/read.c b/src/read.c
index 6913928f..1694ec7d 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1368,7 +1368,7 @@ do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)
--p;
p[1] = '\0';
- undefine_variable_global (name, p - name + 1, origin);
+ undefine_variable_global (&ebuf->floc, name, p - name + 1, origin);
free (var);
}
diff --git a/src/variable.c b/src/variable.c
index f1911759..d2cfcc94 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -184,6 +184,26 @@ struct variable_set_list *current_variable_set_list = &global_setlist;
/* Implement variables. */
+static void
+check_valid_name (const floc* flocp, const char *name, size_t length)
+{
+ const char *cp, *end;
+
+ if (!warn_check (wt_invalid_var))
+ return;
+
+ for (cp = name, end = name + length; cp < end; ++cp)
+ if (ISSPACE (*cp))
+ break;
+ if (cp == end)
+ return;
+
+ if (warn_error (wt_invalid_var))
+ ONS (fatal, flocp, _("invalid variable name '%.*s'"), (int)length, name);
+
+ ONS (error, flocp, _("invalid variable name '%.*s'"), (int)length, name);
+}
+
void
init_hash_global_variable_set (void)
{
@@ -208,6 +228,8 @@ define_variable_in_set (const char *name, size_t length,
struct variable **var_slot;
struct variable var_key;
+ check_valid_name (flocp, name, length);
+
if (set == NULL)
set = &global_variable_set;
@@ -330,7 +352,7 @@ free_variable_set (struct variable_set_list *list)
}
void
-undefine_variable_in_set (const char *name, size_t length,
+undefine_variable_in_set (const floc *flocp, const char *name, size_t length,
enum variable_origin origin,
struct variable_set *set)
{
@@ -338,6 +360,8 @@ undefine_variable_in_set (const char *name, size_t length,
struct variable **var_slot;
struct variable var_key;
+ check_valid_name (flocp, name, length);
+
if (set == NULL)
set = &global_variable_set;
@@ -452,6 +476,29 @@ lookup_special_var (struct variable *var)
}
+/* Check the variable name for validity. */
+static void
+check_variable_reference (const char *name, size_t length)
+{
+ const char *cp, *end;
+
+ if (!warn_check (wt_invalid_ref))
+ return;
+
+ for (cp = name, end = name + length; cp < end; ++cp)
+ if (ISSPACE (*cp))
+ break;
+ if (cp == end)
+ return;
+
+ if (warn_error (wt_invalid_ref))
+ ONS (fatal, *expanding_var,
+ _("invalid variable reference '%.*s'"), (int)length, name);
+
+ ONS (error, *expanding_var,
+ _("invalid variable reference '%.*s'"), (int)length, name);
+}
+
/* 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
@@ -464,6 +511,8 @@ lookup_variable (const char *name, size_t length)
struct variable var_key;
int is_parent = 0;
+ check_variable_reference (name, length);
+
var_key.name = (char *) name;
var_key.length = (unsigned int) length;
@@ -573,6 +622,8 @@ lookup_variable_in_set (const char *name, size_t length,
{
struct variable var_key;
+ check_variable_reference (name, length);
+
var_key.name = (char *) name;
var_key.length = (unsigned int) length;
diff --git a/src/variable.h b/src/variable.h
index bbda212f..ade57531 100644
--- a/src/variable.h
+++ b/src/variable.h
@@ -184,6 +184,7 @@ void hash_init_function_table (void);
void define_new_function(const floc *flocp, const char *name,
unsigned int min, unsigned int max, unsigned int flags,
gmk_func_ptr func);
+
struct variable *lookup_variable (const char *name, size_t length);
struct variable *lookup_variable_for_file (const char *name, size_t length,
struct file *file);
@@ -226,14 +227,15 @@ void warn_undefined (const char* name, size_t length);
#define define_variable_for_file(n,l,v,o,r,f) \
define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)
-void undefine_variable_in_set (const char *name, size_t length,
+void undefine_variable_in_set (const floc *flocp,
+ const char *name, size_t length,
enum variable_origin origin,
struct variable_set *set);
/* Remove variable from the current variable set. */
-#define undefine_variable_global(n,l,o) \
- undefine_variable_in_set((n),(l),(o),NULL)
+#define undefine_variable_global(f,n,l,o) \
+ undefine_variable_in_set((f),(n),(l),(o),NULL)
char **target_environment (struct file *file, int recursive);
diff --git a/src/warning.h b/src/warning.h
index 778ee407..78e99893 100644
--- a/src/warning.h
+++ b/src/warning.h
@@ -17,7 +17,9 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Types of warnings we can show. */
enum warning_type
{
- wt_undefined_var = 0, /* Reference an undefined variable name. */
+ wt_invalid_var = 0, /* Assign to an invalid variable name. */
+ wt_invalid_ref, /* Reference an invalid variable name. */
+ wt_undefined_var, /* Reference an undefined variable name. */
wt_max
};