[SV 63537] Remember the origin of command line options

Certain options can be flipped on and off: -k/-S, -s/--no-silent, and
-w/--no-print-directory.  Ensure they behave as follows:
 1. A switch can be enabled or disabled on the command line.
 2. A switch can be enabled or disabled in env.
 3. A switch can be enabled or disabled in makefile.
 4. Command line beats env and makefile.
 5. Env beats makefile.

* src/main.c: Add variables to hold the origin of relevant options.
(struct command_switch): Add origin field.
(switches): Set a pointer to hold the origin of relevant options.
(decode_switches): For any switch that can be specified in makefile or
env, honor the switch only if cs->origin is not set or the specified
origin beats cs->origin.  Set cs->origin when relevant.
This commit is contained in:
Dmitry Goncharov 2022-12-18 10:01:30 -05:00 committed by Paul Smith
parent 8f9e7722ff
commit 132528b266

View File

@ -136,6 +136,7 @@ int verify_flag;
static int silent_flag;
static const int default_silent_flag = 0;
static enum variable_origin silent_origin = o_default;
/* Nonzero means either -s was given, or .SILENT-with-no-deps was seen. */
@ -190,6 +191,7 @@ int no_builtin_variables_flag = 0;
int keep_going_flag;
static const int default_keep_going_flag = 0;
static enum variable_origin keep_going_origin = o_default;
/* Nonzero means check symlink mtimes. */
@ -197,6 +199,7 @@ int check_symlink_flag = 0;
static int print_directory_flag = -1;
static const int default_print_directory_flag = -1;
static enum variable_origin print_directory_origin = o_default;
/* Nonzero means print version information. */
@ -405,30 +408,31 @@ static int trace_flag = 0;
struct command_switch
{
int c; /* The switch character. */
int c; /* The switch character. */
enum /* Type of the value. */
enum /* Type of the value. */
{
flag, /* Turn int flag on. */
flag_off, /* Turn int flag off. */
string, /* One string per invocation. */
strlist, /* One string per switch. */
filename, /* A string containing a file name. */
positive_int, /* A positive integer. */
floating, /* A floating-point number (double). */
ignore /* Ignored. */
flag, /* Turn int flag on. */
flag_off, /* Turn int flag off. */
string, /* One string per invocation. */
strlist, /* One string per switch. */
filename, /* A string containing a file name. */
positive_int, /* A positive integer. */
floating, /* A floating-point number (double). */
ignore /* Ignored. */
} type;
void *value_ptr; /* Pointer to the value-holding variable. */
void *value_ptr; /* Pointer to the value-holding variable. */
unsigned int env:1; /* Can come from MAKEFLAGS. */
unsigned int toenv:1; /* Should be put in MAKEFLAGS. */
unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */
unsigned int env:1; /* Can come from MAKEFLAGS. */
unsigned int toenv:1; /* Should be put in MAKEFLAGS. */
unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */
const void *noarg_value; /* Pointer to value used if no arg given. */
const void *default_value; /* Pointer to default value. */
const void *noarg_value; /* Pointer to value used if no arg given. */
const void *default_value; /* Pointer to default value. */
const char *long_name; /* Long option name. */
const char *long_name; /* Long option name. */
enum variable_origin *origin; /* Origin of the value. */
};
/* The table of command switches.
@ -439,61 +443,62 @@ struct command_switch
static const struct command_switch switches[] =
{
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" },
{ 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 },
{ 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", },
{ 'E', strlist, &eval_strings, 1, 0, 0, 0, 0, "eval" },
{ 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" },
{ 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" },
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make", 0 },
{ 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0, 0 },
{ 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", 0 },
{ 'E', strlist, &eval_strings, 1, 0, 0, 0, 0, "eval", 0 },
{ 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help", 0 },
{ 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors", 0 },
{ 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag,
"keep-going" },
{ 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" },
{ 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
{ 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" },
{ 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" },
{ 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" },
"keep-going", &keep_going_origin },
{ 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times", 0 },
{ 'm', ignore, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print", 0 },
{ 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base", 0 },
{ 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question", 0 },
{ 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules", 0 },
{ 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0,
"no-builtin-variables" },
{ 's', flag, &silent_flag, 1, 1, 0, 0, &default_silent_flag, "silent" },
"no-builtin-variables", 0 },
{ 's', flag, &silent_flag, 1, 1, 0, 0, &default_silent_flag, "silent",
&silent_origin },
{ 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag,
"no-keep-going" },
{ 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" },
{ 'v', flag, &print_version_flag, 1, 0, 0, 0, 0, "version" },
"no-keep-going", &keep_going_origin },
{ 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch", 0 },
{ 'v', flag, &print_version_flag, 1, 0, 0, 0, 0, "version", 0 },
{ 'w', flag, &print_directory_flag, 1, 1, 0, 0,
&default_print_directory_flag, "print-directory" },
&default_print_directory_flag, "print-directory", &print_directory_origin },
/* These options take arguments. */
{ 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" },
{ 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" },
{ 'C', filename, &directories, 0, 0, 0, 0, 0, "directory", 0 },
{ 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file", 0 },
{ 'I', filename, &include_dirs, 1, 1, 0, 0, 0,
"include-dir" },
"include-dir", 0 },
{ 'j', positive_int, &arg_job_slots, 1, 1, 0, &inf_jobs, &default_job_slots,
"jobs" },
"jobs", 0 },
{ 'l', floating, &max_load_average, 1, 1, 0, &default_load_average,
&default_load_average, "load-average" },
{ 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" },
{ 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync" },
{ 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" },
&default_load_average, "load-average", 0 },
{ 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file", 0 },
{ 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync", 0 },
{ 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if", 0 },
/* These are long-style options. */
{ CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, "basic", 0, "debug" },
{ CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, JOBSERVER_AUTH_OPT },
{ CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, "trace" },
{ CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, "basic", 0, "debug", 0 },
{ CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, JOBSERVER_AUTH_OPT, 0 },
{ CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, "trace", 0 },
{ CHAR_MAX+4, flag_off, &print_directory_flag, 1, 1, 0, 0,
&default_print_directory_flag, "no-print-directory" },
&default_print_directory_flag, "no-print-directory", &print_directory_origin },
{ CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables" },
{ CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, "sync-mutex" },
"warn-undefined-variables", 0 },
{ CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, "sync-mutex", 0 },
{ CHAR_MAX+8, flag_off, &silent_flag, 1, 1, 0, 0, &default_silent_flag,
"no-silent" },
{ CHAR_MAX+9, string, &jobserver_auth, 1, 0, 0, 0, 0, "jobserver-fds" },
"no-silent", &silent_origin },
{ CHAR_MAX+9, string, &jobserver_auth, 1, 0, 0, 0, 0, "jobserver-fds", 0 },
/* There is special-case handling for this in decode_switches() as well. */
{ TEMP_STDIN_OPT, filename, &makefiles, 0, 0, 0, 0, 0, "temp-stdin" },
{ CHAR_MAX+11, string, &shuffle_mode, 1, 1, 0, "random", 0, "shuffle" },
{ CHAR_MAX+12, string, &jobserver_style, 1, 0, 0, 0, 0, "jobserver-style" },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
{ TEMP_STDIN_OPT, filename, &makefiles, 0, 0, 0, 0, 0, "temp-stdin", 0 },
{ CHAR_MAX+11, string, &shuffle_mode, 1, 1, 0, "random", 0, "shuffle", 0 },
{ CHAR_MAX+12, string, &jobserver_style, 1, 0, 0, 0, 0, "jobserver-style", 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* Secondary long names for options. */
@ -3148,7 +3153,9 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
this switch. We test this individually inside the
switch below rather than just once outside it, so that
options which are to be ignored still consume args. */
int doit = origin == o_command || cs->env;
int doit = (origin == o_command
|| (cs->env &&
(cs->origin == NULL || origin >= *cs->origin)));
switch (cs->type)
{
@ -3161,7 +3168,11 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
case flag:
case flag_off:
if (doit)
*(int *) cs->value_ptr = cs->type == flag;
{
*(int *) cs->value_ptr = cs->type == flag;
if (cs->origin)
*cs->origin = origin;
}
break;
case string:
@ -3194,6 +3205,8 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
char **val = (char **)cs->value_ptr;
free (*val);
*val = xstrdup (coptarg);
if (cs->origin)
*cs->origin = origin;
break;
}
@ -3227,7 +3240,11 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
}
if (cs->type == strlist)
sl->list[sl->idx++] = xstrdup (coptarg);
{
sl->list[sl->idx++] = xstrdup (coptarg);
if (cs->origin)
*cs->origin = origin;
}
else if (cs->c == TEMP_STDIN_OPT)
{
if (stdin_offset > 0)
@ -3235,9 +3252,15 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
/* We don't need to expand the temp file. */
stdin_offset = sl->idx;
sl->list[sl->idx++] = strcache_add (coptarg);
if (cs->origin)
*cs->origin = origin;
}
else
sl->list[sl->idx++] = expand_command_line_file (coptarg);
{
sl->list[sl->idx++] = expand_command_line_file (coptarg);
if (cs->origin)
*cs->origin = origin;
}
sl->list[sl->idx] = 0;
break;
@ -3269,11 +3292,19 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
bad = 1;
}
else
*(unsigned int *) cs->value_ptr = i;
{
*(unsigned int *) cs->value_ptr = i;
if (cs->origin)
*cs->origin = origin;
}
}
else
*(unsigned int *) cs->value_ptr
= *(unsigned int *) cs->noarg_value;
{
*(unsigned int *) cs->value_ptr
= *(unsigned int *) cs->noarg_value;
if (cs->origin)
*cs->origin = origin;
}
break;
case floating:
@ -3282,8 +3313,12 @@ decode_switches (int argc, const char **argv, enum variable_origin origin)
coptarg = argv[optind++];
if (doit)
*(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg)
: *(double *) cs->noarg_value);
{
*(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg)
: *(double *) cs->noarg_value);
if (cs->origin)
*cs->origin = origin;
}
break;
}