summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c206
1 files changed, 145 insertions, 61 deletions
diff --git a/main.c b/main.c
index bfba756..954a00c 100644
--- a/main.c
+++ b/main.c
@@ -307,6 +307,16 @@ static struct option long_option_aliases[] =
/* List of goal targets. */
static struct dep *goals, *lastgoal;
+
+/* List of variables which were defined on the command line
+ (or, equivalently, in MAKEFLAGS). */
+
+struct command_variable
+ {
+ struct command_variable *next;
+ struct variable *variable;
+ };
+static struct command_variable *command_variables;
/* The name we were invoked with. */
@@ -1077,7 +1087,7 @@ init_switches ()
p = options;
/* Return switch and non-switch args in order, regardless of
- POSIXLY_CORRECT. Non-switch args are returned as option '\0'. */
+ POSIXLY_CORRECT. Non-switch args are returned as option 1. */
*p++ = '-';
for (i = 0; switches[i].c != '\0'; ++i)
@@ -1148,11 +1158,22 @@ decode_switches (argc, argv, env)
while ((c = getopt_long (argc, argv,
options, long_options, (int *) 0)) != EOF)
{
- if (c == '\0')
+ if (c == 1)
{
/* Non-option argument. It might be a variable definition. */
- if (! try_variable_definition ((char *) 0, 0, optarg, o_command)
- && ! env)
+ struct variable *v;
+ v = try_variable_definition ((char *) 0, 0, optarg, o_command);
+ if (v != 0)
+ {
+ /* It is indeed a variable definition. Record a pointer to
+ the variable for later use in define_makeflags. */
+ struct command_variable *cv
+ = (struct command_variable *) xmalloc (sizeof (*cv));
+ cv->variable = v;
+ cv->next = command_variables;
+ command_variables = cv;
+ }
+ else if (! env)
{
/* Not an option or variable definition; it must be a goal
target! Enter it as a file and add it to the dep chain of
@@ -1415,10 +1436,21 @@ decode_env_switches (envar, len)
Either this is the single-word form and we should prepend a dash
before calling decode_switches, or this is the multi-word form and
there is no dash because it is a variable definition. */
- if (try_variable_definition ((char *) 0, 0, argv[1], o_command))
- /* It was indeed a variable definition, and now it has been
- processed. There is nothing for decode_switches to do. */
- return;
+ struct variable *v;
+ v = try_variable_definition ((char *) 0, 0, argv[1], o_command);
+ if (v != 0)
+ {
+ /* It was indeed a variable definition, and now it has been
+ processed. There is nothing for decode_switches to do.
+ Record a pointer to the variable for later use in
+ define_makeflags. */
+ struct command_variable *cv
+ = (struct command_variable *) xmalloc (sizeof (*cv));
+ cv->variable = v;
+ cv->next = command_variables;
+ command_variables = cv;
+ return;
+ }
/* It wasn't a variable definition, so it's some switches without a
leading dash. Add one and pass it along to decode_switches. We
@@ -1441,7 +1473,10 @@ define_makeflags (all, makefile)
{
register const struct command_switch *cs;
char *flagstring;
+ register char *p;
+ unsigned int words;
struct variable *v;
+ struct command_variable *cv;
/* We will construct a linked list of `struct flag's describing
all the flags which need to go in MAKEFLAGS. Then, once we
@@ -1554,70 +1589,119 @@ define_makeflags (all, makefile)
#undef ADD_FLAG
- if (flags == 0)
- /* No flags. Use a string of two nulls so [1] works below. */
- flagstring = "\0";
- else
+ if (all && command_variables != 0)
{
- /* Construct the value in FLAGSTRING.
- We allocate enough space for a preceding dash and trailing null. */
- register char *p;
- flagstring = (char *) alloca (1 + flagslen + 1);
- p = flagstring;
- *p++ = '-';
- do
+ /* Now figure out how much space will be taken up
+ by the command-line variable definitions. */
+ flagslen += 4; /* For the possible " -- ". */
+ for (cv = command_variables; cv != 0; cv = cv->next)
{
- /* Add the flag letter or name to the string. */
- if (!isalnum (flags->cs->c))
- {
- *p++ = '-';
- strcpy (p, flags->cs->long_name);
- p += strlen (p);
- }
- else
- *p++ = flags->cs->c;
- if (flags->arg != 0)
+ v = cv->variable;
+ flagslen += strlen (v->name);
+ if (! v->recursive)
+ ++flagslen;
+ ++flagslen;
+ flagslen += strlen (v->value);
+ }
+ }
+
+ /* Construct the value in FLAGSTRING.
+ We allocate enough space for a preceding dash and trailing null. */
+ flagstring = (char *) alloca (1 + flagslen + 1);
+ p = flagstring;
+ words = 1;
+ *p++ = '-';
+ while (flags != 0)
+ {
+ /* Add the flag letter or name to the string. */
+ if (!isalnum (flags->cs->c))
+ {
+ *p++ = '-';
+ strcpy (p, flags->cs->long_name);
+ p += strlen (p);
+ }
+ else
+ *p++ = flags->cs->c;
+ if (flags->arg != 0)
+ {
+ /* A flag that takes an optional argument which in this case
+ is omitted is specified by ARG being "" and ARGLEN being 0.
+ We must distinguish because a following flag appended without
+ an intervening " -" is considered the arg for the first. */
+ if (flags->arglen > 0)
{
- /* A flag that takes an optional argument which in this case
- is omitted is specified by ARG being "" and ARGLEN being 0.
- We must distinguish because a following flag appended without
- an intervening " -" is considered the arg for the first. */
- if (flags->arglen > 0)
- {
- /* Add its argument too. */
- *p++ = !isalnum (flags->cs->c) ? '=' : ' ';
- bcopy (flags->arg, p, flags->arglen);
- p += flags->arglen;
- }
- /* Write a following space and dash, for the next flag. */
- *p++ = ' ';
- *p++ = '-';
+ /* Add its argument too. */
+ *p++ = !isalnum (flags->cs->c) ? '=' : ' ';
+ bcopy (flags->arg, p, flags->arglen);
+ p += flags->arglen;
}
- else if (!isalnum (flags->cs->c))
+ ++words;
+ /* Write a following space and dash, for the next flag. */
+ *p++ = ' ';
+ *p++ = '-';
+ }
+ else if (!isalnum (flags->cs->c))
+ {
+ ++words;
+ /* Long options must each go in their own word,
+ so we write the following space and dash. */
+ *p++ = ' ';
+ *p++ = '-';
+ }
+ flags = flags->next;
+ }
+
+ if (all && command_variables != 0)
+ {
+ /* Now write all the command-line variable definitions. */
+ if (p == &flagstring[1])
+ /* No flags written, so elide the leading dash already written. */
+ p = flagstring;
+ else
+ {
+ /* Separate the variables from the switches with a "--" arg. */
+ if (p[-1] != '-')
{
- /* Long options must each go in their own word,
- so we write the following space and dash. */
+ /* We did not already write a trailing " -". */
*p++ = ' ';
*p++ = '-';
}
- flags = flags->next;
- } while (flags != 0);
-
- if (p[-1] == '-')
- /* Kill the final space and dash. */
- p -= 2;
-
- /* Terminate the string. */
- *p = '\0';
+ /* There is a trailing " -"; fill it out to " -- ". */
+ *p++ = '-';
+ *p++ = ' ';
+ }
+ for (cv = command_variables; cv != 0; cv = cv->next)
+ {
+ /* XXX Quoting? */
+ unsigned int len;
+ v = cv->variable;
+ len = strlen (v->name);
+ bcopy (v->name, p, len);
+ p += len;
+ if (! v->recursive)
+ *p++ = ':';
+ len = strlen (v->value);
+ bcopy (v->value, p, len);
+ p += len;
+ *p++ = ' ';
+ ++words;
+ }
+ --p; /* Kill the final space. */
}
+ else if (p[-1] == '-')
+ /* Kill the final space and dash. */
+ p -= 2;
+
+ /* Terminate the string. */
+ *p = '\0';
v = define_variable ("MAKEFLAGS", 9,
- /* On Sun, the value of MFLAGS starts with a `-' but
- the value of MAKEFLAGS lacks the `-'.
- Be compatible with this unless FLAGSTRING starts
- with a long option `--foo', since removing the
- first dash would result in the bogus `-foo'. */
- flagstring[1] == '-' ? flagstring : &flagstring[1],
+ /* If there is just a single word of switches,
+ omit the leading dash unless it is a single
+ long option with two leading dashes. */
+ &flagstring[(words == 1 && command_variables == 0
+ && flagstring[1] != '-')
+ ? 1 : 0],
/* This used to use o_env, but that lost when a
makefile defined MAKEFLAGS. Makefiles set
MAKEFLAGS to add switches, but we still want