Formerly main.c.~66~
authorRoland McGrath <roland@redhat.com>
Thu, 7 Jan 1993 00:34:28 +0000 (00:34 +0000)
committerRoland McGrath <roland@redhat.com>
Thu, 7 Jan 1993 00:34:28 +0000 (00:34 +0000)
main.c

diff --git a/main.c b/main.c
index 47a6758..63c1656 100644 (file)
--- a/main.c
+++ b/main.c
@@ -234,14 +234,13 @@ static struct command_switch switches[] =
     { 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0,
        "file", "FILE",
        "Read FILE as a makefile" },
-    { 'h', usage_and_exit, 
-       0, 0, 0, 0, 0, 0,
+    { 'h', usage_and_exit, 0, 0, 0, 0, 0, 0,
        "help", 0,
        "Print this message and exit" },
     { 'i', flag, (char *) &ignore_errors_flag, 1, 1, 0, 0, 0,
        "ignore-errors", 0,
        "Ignore errors from commands" },
-    { 'I', string, (char *) &include_directories, 0, 0, 0, 0, 0,
+    { 'I', string, (char *) &include_directories, 1, 0, 0, 0, 0,
        "include-dir", "DIRECTORY",
        "Search DIRECTORY for included makefiles" },
     { 'j', positive_int, (char *) &job_slots, 1, 1, 0,
@@ -284,7 +283,7 @@ static struct command_switch switches[] =
     { 't', flag, (char *) &touch_flag, 1, 1, 1, 0, 0,
        "touch", 0,
        "Touch targets instead of remaking them" },
-    { 'v', flag, (char *) &print_version_flag, 0, 0, 0, 0, 0,
+    { 'v', flag, (char *) &print_version_flag, 1, 0, 0, 0, 0,
        "version", 0,
        "Print the version number of make" },
     { 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
@@ -358,6 +357,7 @@ main (argc, argv, envp)
      char **argv;
      char **envp;
 {
+  extern void init_dir ();
   extern RETSIGTYPE fatal_error_signal (), child_handler ();
   register struct file *f;
   register unsigned int i;
@@ -473,7 +473,9 @@ main (argc, argv, envp)
 
   /* Decode the switches.  */
 
-  decode_switches (argc, argv);
+  decode_env_switches ("MAKEFLAGS", 9);
+  decode_env_switches ("MFLAGS", 6);
+  decode_switches (argc, argv, 0);
 
   /* Print version information.  */
 
@@ -545,7 +547,7 @@ main (argc, argv, envp)
   if (cmd_defs_idx > 0)
     {
       cmd_defs[cmd_defs_idx - 1] = '\0';
-      (void) define_variable ("MAKEOVERRIDES", 13, cmd_defs, o_override, 0);
+      (void) define_variable ("MAKEOVERRIDES", 13, cmd_defs, o_default, 0);
     }
   free (cmd_defs);
 
@@ -559,15 +561,15 @@ main (argc, argv, envp)
       && argv[0] != 0 && argv[0][0] != '/' && index (argv[0], '/') != 0)
     argv[0] = concat (current_directory, "/", argv[0]);
 
-  (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_env, 0);
+  (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_default, 0);
 
   /* Append the command-line variable definitions gathered above
      so sub-makes will get them as command-line definitions.  */
 
   (void) define_variable ("MAKE", 4,
-                         "$(MAKE_COMMAND) $(MAKEOVERRIDES)", o_env, 1);
+                         "$(MAKE_COMMAND) $(MAKEOVERRIDES)", o_default, 1);
 
-  /* If there were -c flags, move ourselves about.  */
+  /* If there were -C flags, move ourselves about.  */
 
   if (directories != 0)
     for (i = 0; directories->list[i] != 0; ++i)
@@ -683,6 +685,7 @@ main (argc, argv, envp)
   read_makefiles
     = read_all_makefiles (makefiles == 0 ? (char **) 0 : makefiles->list);
 
+  /* Decode switches again, in case the variables were set by the makefile.  */
   decode_env_switches ("MAKEFLAGS", 9);
   decode_env_switches ("MFLAGS", 6);
 
@@ -1009,32 +1012,25 @@ main (argc, argv, envp)
   return 0;
 }
 \f
+/* Parsing of arguments, decoding of switches.  */
+
+static char options[sizeof (switches) / sizeof (switches[0]) * 3];
+static struct option long_options[(sizeof (switches) / sizeof (switches[0])) +
+                                 (sizeof (long_option_aliases) /
+                                  sizeof (long_option_aliases[0]))];
+
+/* Fill in the string and vector for getopt.  */
 static void
-decode_switches (argc, argv)
-     int argc;
-     char **argv;
+init_switches ()
 {
-  char bad = 0;
-  register unsigned int i;
-  register struct command_switch *cs;
-  register struct stringlist *sl;
-  char *p;
-  char options[sizeof (switches) / sizeof (switches[0]) * 3];
-  struct option long_options[(sizeof (switches) / sizeof (switches[0])) +
-                            (sizeof (long_option_aliases) /
-                             sizeof (long_option_aliases[0]))];
+  register char *p;
   register int c;
+  register unsigned int i;
 
-  decode_env_switches ("MAKEFLAGS", 9);
-  decode_env_switches ("MFLAGS", 6);
-
-  other_args = (struct stringlist *) xmalloc (sizeof (struct stringlist));
-  other_args->max = argc + 1;
-  other_args->list = (char **) xmalloc ((argc + 1) * sizeof (char *));
-  other_args->idx = 1;
-  other_args->list[0] = savestring (argv[0], strlen (argv[0]));
+  if (options[0] != '\0')
+    /* Already done.  */
+    return;
 
-  /* Fill in the string and vector for getopt.  */
   p = options;
   for (i = 0; switches[i].c != '\0'; ++i)
     {
@@ -1071,8 +1067,42 @@ decode_switches (argc, argv)
        ++c)
     long_options[i++] = long_option_aliases[c];
   long_options[i].name = 0;
+}
+
+/* Decode switches from ARGC and ARGV.
+   They came from the environment if ENV is nonzero.  */
+
+static void
+decode_switches (argc, argv, env)
+     int argc;
+     char **argv;
+     int env;
+{
+  int bad = 0;
+  register struct command_switch *cs;
+  register struct stringlist *sl;
+  register int c;
+
+  if (!env)
+    {
+      other_args = (struct stringlist *) xmalloc (sizeof (struct stringlist));
+      other_args->max = argc + 1;
+      other_args->list = (char **) xmalloc ((argc + 1) * sizeof (char *));
+      other_args->idx = 1;
+      other_args->list[0] = savestring (argv[0], strlen (argv[0]));
+    }
+
+  /* getopt does most of the parsing for us.
+     First, get its vectors set up.  */
+
+  init_switches ();
+
+  /* Let getopt produce error messages for the command line,
+     but not for options from the environment.  */
+  opterr = !env;
+  /* Reset getopt's state.  */
+  optind = 0;
 
-  /* getopt does most of the parsing for us.  */
   while ((c = getopt_long (argc, argv,
                           options, long_options, (int *) 0)) != EOF)
     {
@@ -1085,6 +1115,12 @@ decode_switches (argc, argv)
        for (cs = switches; cs->c != '\0'; ++cs)
          if (cs->c == c)
            {
+             /* Whether or not we will actually do anything with
+                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 = !env || cs->env;
+
              switch (cs->type)
                {
                default:
@@ -1099,10 +1135,14 @@ decode_switches (argc, argv)
 
                case flag:
                case flag_off:
-                 *(int *) cs->value_ptr = cs->type == flag;
+                 if (doit)
+                   *(int *) cs->value_ptr = cs->type == flag;
                  break;
 
                case string:
+                 if (!doit)
+                   break;
+
                  if (optarg == 0)
                    optarg = cs->noarg_value;
 
@@ -1131,14 +1171,19 @@ decode_switches (argc, argv)
                  if (optarg == 0 && argc > optind
                      && isdigit (argv[optind][0]))
                    optarg = argv[optind++];
+
+                 if (!doit)
+                   break;
+
                  if (optarg != 0)
                    {
                      int i = atoi (optarg);
                      if (i < 1)
                        {
-                         error ("the `-%c' option requires a \
+                         if (doit)
+                           error ("the `-%c' option requires a \
 positive integral argument",
-                                cs->c);
+                                  cs->c);
                          bad = 1;
                        }
                      else
@@ -1150,12 +1195,15 @@ positive integral argument",
                  break;
 
                case floating:
-                 *(double *) cs->value_ptr
-                   = (optarg != 0 ? atof (optarg)
-                      : (optind < argc && (isdigit (argv[optind][0])
-                                           || argv[optind][0] == '.'))
-                      ? atof (argv[optind++])
-                      : *(double *) cs->noarg_value);
+                 if (optarg == 0 && optind < argc
+                     && (isdigit (argv[optind][0]) || argv[optind][0] == '.'))
+                   optarg = argv[optind++];
+
+                 if (doit)
+                   *(double *) cs->value_ptr               
+                     = (optarg != 0 ? atof (optarg)
+                        : *(double *) cs->noarg_value);
+
                  break;
                }
            
@@ -1164,15 +1212,20 @@ positive integral argument",
            }
     }
 
-  while (optind < argc)
+  if (!env)
     {
-      char *arg = argv[optind++];
-      if (arg[0] != '-' || arg[1] != '\0')
-       other_args->list[other_args->idx++] = arg;
+      /* Collect the remaining args in the `other_args' string list.  */
+
+      while (optind < argc)
+       {
+         char *arg = argv[optind++];
+         if (arg[0] != '-' || arg[1] != '\0')
+           other_args->list[other_args->idx++] = arg;
+       }
+      other_args->list[other_args->idx] = 0;
     }
-  other_args->list[other_args->idx] = 0;
 
-  if (bad)
+  if (bad && !env)
     {
       /* Print a nice usage message.  */
 
@@ -1184,7 +1237,7 @@ positive integral argument",
       fputs ("Options:\n", stderr);
       for (cs = switches; cs->c != '\0'; ++cs)
        {
-         char buf[1024], arg[50];
+         char buf[1024], arg[50], *p;
 
          if (cs->description[0] == '-')
            continue;
@@ -1207,6 +1260,7 @@ positive integral argument",
          p += strlen (p);
          if (cs->long_name != 0)
            {
+             unsigned int i;
              sprintf (p, ", --%s%s", cs->long_name, arg);
              p += strlen (p);
              for (i = 0; i < (sizeof (long_option_aliases) /
@@ -1255,66 +1309,63 @@ positive integral argument",
     }
 }
 
+/* Decode switches from environment variable ENVAR (which is LEN chars long).
+   We do this by chopping the value into a vector of words, prepending a
+   dash to the first word if it lacks one, and passing the vector to
+   decode_switches.  */
+
 static void
 decode_env_switches (envar, len)
      char *envar;
      unsigned int len;
 {
-  struct variable *v;
-  register char *args;
-  register struct command_switch *cs;
-
-  v = lookup_variable (envar, len);
-  if (v == 0 || *v->value == '\0')
+  char *varref = alloca (2 + len + 2);
+  char *value, *args;
+  int argc;
+  char **argv;
+
+  /* Get the variable's value.  */
+  varref[0] = '$';
+  varref[1] = '(';
+  bcopy (envar, &varref[2], len);
+  varref[2 + len] = ')';
+  varref[2 + len + 1] = '\0';
+  value = variable_expand (varref);
+
+  /* Skip whitespace, and check for an empty value.  */
+  value = next_token (value);
+  len = strlen (value);
+  if (len == 0)
     return;
 
-  for (args = v->value; *args != '\0'; ++args)
-    for (cs = switches; cs->c != '\0'; ++cs)
-      if (cs->c == *args)
-       if (cs->env)
-         switch (cs->type)
-           {
-           case string:
-             /* None of these allow environment changes.  */
-           default:
-             abort ();
-           case flag:
-           case flag_off:
-             *(int *) cs->value_ptr = cs->type == flag;
-             break;
-           case positive_int:
-             while (isspace (args[1]))
-               ++args;
-             if (isdigit(args[1]))
-               {
-                 int i = atoi (&args[1]);
-                 while (isdigit (args[1]))
-                   ++args;
-                 if (i >= 1)
-                   *(unsigned int *) cs->value_ptr = i;
-               }
-             else
-               *(unsigned int *) cs->value_ptr
-                 = *(unsigned int *) cs->noarg_value;
-             break;
-           case floating:
-             while (isspace (args[1]))
-               ++args;
-             if (args[1] == '.' || isdigit (args[1]))
-               {
-                 *(double *) cs->value_ptr = atof (&args[1]);
-                 while (args[1] == '.' || isdigit (args[1]))
-                   ++args;
-               }
-             else
-               *(double *) cs->value_ptr = *(double *) cs->noarg_value;
-             break;
-           }
+  /* Make a copy of the value in ARGS, where we will munge it.
+     If it does not begin with a dash, prepend one.  */
+  args = (char *) alloca (1 + len + 2);
+  if (value[0] != '-')
+    args[0] = '-';
+  bcopy (value, value[0] == '-' ? args : &args[1], len + 1);
+  /* Write an extra null terminator so our loop below will
+     never be in danger of looking past the end of the string.  */
+  args[(value[0] == '-' ? 0 : 1) + len + 1] = '\0';
+
+  /* Allocate a vector that is definitely big enough.  */
+  argv = (char **) alloca (len * sizeof (char *));
+  argc = 0;
+  do
+    {
+      argv[argc++] = args;
+      args = end_of_token (args);
+      *args++ = '\0';
+    } while (*args != '\0');
+  argv[argc] = 0;
+
+  /* Parse those words.  */
+  decode_switches (argc, argv, 1);
 }
 \f
 /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the
    command switches.  Include positive_int and floating options if PF.
-   Don't include options with the `no_makefile' flag is if MAKEFILE.  */
+   Don't include options with the `no_makefile' flag set if MAKEFILE.  */
 
 static void
 define_makeflags (pf, makefile)