From ea3d4b37122a48ae28e648590b1ddb06665f88c6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 9 May 1992 04:28:28 +0000 Subject: Formerly main.c.~40~ --- main.c | 416 ++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 241 insertions(+), 175 deletions(-) diff --git a/main.c b/main.c index d9ddd82..17c865a 100644 --- a/main.c +++ b/main.c @@ -22,6 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "variable.h" #include "job.h" #include +#include "getopt.h" extern char *version_string; @@ -81,15 +82,15 @@ flags () {} struct command_switch { - char c; /* The switch character. */ - enum /* Type of the value. */ + char c; /* The switch character. */ + enum /* Type of the value. */ { - flag, /* Turn int flag on. */ - flag_off, /* Turn int flag off. */ - string, /* One string per switch, may be in the same word. */ - 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 switch. */ + positive_int, /* A positive integer. */ + floating, /* A floating-point number (double). */ + ignore /* Ignored. */ } type; char *value_ptr; /* Pointer to the value-holding variable. */ @@ -100,6 +101,10 @@ struct command_switch char *noarg_value; /* Pointer to value used if no argument is given. */ char *default_value;/* Pointer to default value. */ + + char *long_name; /* Long option name. */ + char *argdesc; /* Descriptive word for argument. */ + char *description; /* Description for usage message. */ }; @@ -213,33 +218,80 @@ static struct stringlist *new_files = 0; static struct command_switch switches[] = { - { 'b', ignore, 0, 0, 0, 0, 0, 0 }, - { 'C', string, (char *) &directories, 0, 0, 0, 0, 0 }, - { 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0 }, - { 'e', flag, (char *) &env_overrides, 1, 1, 0, 0, 0 }, - { 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0 }, - { 'i', flag, (char *) &ignore_errors_flag, 1, 1, 0, 0, 0 }, - { 'I', string, (char *) &include_directories, 0, 0, 0, 0, 0 }, + { 'b', ignore, 0, 0, 0, 0, 0, 0, + 0, 0, + "Ignored for compatibility" }, + { 'C', string, (char *) &directories, 0, 0, 0, 0, 0, + "directory", "DIRECTORY", + "Change to DIRECTORY before doing anything" }, + { 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0, + "debug", 0, + "Print lots of debugging information" }, + { 'e', flag, (char *) &env_overrides, 1, 1, 0, 0, 0, + "environment-overrides", 0, + "Environment variables override makefiles" }, + { 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0, + "file", "FILE", + "Read FILE as a makefile" }, + { '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, + "include-path", "DIRECTORY", + "Search DIRECTORY for included makefiles" }, { 'j', positive_int, (char *) &job_slots, 1, 1, 0, - (char *) &inf_jobs, (char *) &default_job_slots }, + (char *) &inf_jobs, (char *) &default_job_slots, + "jobs", "N", + "Allow N jobs at once; infinite jobs with no arg" }, { 'k', flag, (char *) &keep_going_flag, 1, 1, 0, - 0, (char *) &default_keep_going_flag }, + 0, (char *) &default_keep_going_flag, + "keep-going", 0, + "Keep going when some targets can't be made" }, { 'l', floating, (char *) &max_load_average, 1, 1, 0, - (char *) &default_load_average, (char *) &default_load_average }, - { 'm', ignore, 0, 0, 0, 0, 0, 0 }, - { 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0 }, - { 'o', string, (char *) &old_files, 0, 0, 0, 0, 0 }, - { 'p', flag, (char *) &print_data_base_flag, 1, 1, 0, 0, 0 }, - { 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0 }, - { 'r', flag, (char *) &no_builtin_rules_flag, 1, 1, 0, 0, 0 }, - { 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0 }, + (char *) &default_load_average, (char *) &default_load_average, + "load-average", "N", + "Don't start multiple jobs unless load is below N" }, + { 'm', ignore, 0, 0, 0, 0, 0, 0, + 0, 0, + "Ignored for compatibility" }, + { 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0, + "just-print", 0, + "Don't actually run any commands; just print them" }, + { 'o', string, (char *) &old_files, 0, 0, 0, 0, 0, + "old-file", "FILE", + "Consider FILE to be very old and don't remake it" }, + { 'p', flag, (char *) &print_data_base_flag, 1, 1, 0, 0, 0, + "print-data-base", 0, + "Print make's internal database" }, + { 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0, + "question", 0, + "Run no commands; exit status says if up to date" }, + { 'r', flag, (char *) &no_builtin_rules_flag, 1, 1, 0, 0, 0, + "no-builtin-rules", 0, + "Disable the built-in implicit rules" }, + { 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0, + "silent", 0, + "Don't echo commands" }, + { 'q', flag, (char *) &silent_flag, 1, 1, 0, 0, 0, + "quiet", 0, + "Same as -s" }, { 'S', flag_off, (char *) &keep_going_flag, 1, 1, 0, - 0, (char *) &default_keep_going_flag }, - { 't', flag, (char *) &touch_flag, 1, 1, 1, 0, 0 }, - { 'v', flag, (char *) &print_version_flag, 0, 0, 0, 0, 0 }, - { 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0 }, - { 'W', string, (char *) &new_files, 0, 0, 0, 0, 0 }, - { '\0', ignore, 0, 0, 0, 0, 0 } + 0, (char *) &default_keep_going_flag, + "dont-keep-going", 0, + "Turns off -k" }, + { '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, + "version", 0, + "Print the version number of make" }, + { 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0, + "print-directory", 0, + "Print the current directory" }, + { 'W', string, (char *) &new_files, 0, 0, 0, 0, 0, + "what-if", "FILE", + "Consider FILE to be infinitely new" }, + { '\0', } }; /* List of non-switch arguments. */ @@ -952,10 +1004,12 @@ decode_switches (argc, argv) { char bad = 0; register unsigned int i; - register char *sw; register struct command_switch *cs; register struct stringlist *sl; - char *arg; + char *p; + char options[sizeof (switches) / sizeof (switches[0]) * 3]; + struct option long_options[sizeof (switches) / sizeof (switches[0])]; + register int c; decode_env_switches ("MAKEFLAGS", 9); decode_env_switches ("MFLAGS", 6); @@ -966,165 +1020,177 @@ decode_switches (argc, argv) other_args->idx = 1; other_args->list[0] = savestring (argv[0], strlen (argv[0])); - for (i = 1; i < argc; i++) + /* Fill in the string and vector for getopt. */ + p = options; + *p++ = '-'; /* Non-option args are returned in order. */ + for (i = 0; switches[i].c != '\0'; ++i) + { + long_options[i].name = switches[i].long_name; + *p++ = switches[i].c; + switch (switches[i].type) + { + case flag: + case flag_off: + case ignore: + long_options[i].has_arg = no_argument; + break; + + case string: + case positive_int: + case floating: + *p++ = ':'; + if (switches[i].noarg_value != 0) + { + *p++ = ':'; + long_options[i].has_arg = optional_argument; + } + else + long_options[i].has_arg = required_argument; + break; + } + } + *p = '\0'; + long_options[i].name = 0; + + /* getopt does most of the parsing for us. */ + while ((c = getopt_long (argc, argv, + options, long_options, (int *) 0)) != EOF) { - sw = argv[i]; - if (*sw++ == '-') - while (*sw != '\0') + if (c == '?') + /* Bad option. We will print a usage message and die later. + But continue to parse the other options so the user can + see all he did wrong. */ + bad = 1; + else if (c == 1) + { + /* This is a non-option argument. */ + if (other_args->idx == other_args->max - 1) + { + other_args->max += 5; + other_args->list = (char **) + xrealloc ((char *) other_args->list, + other_args->max * sizeof (char *)); + } + other_args->list[other_args->idx++] = optarg; + } + else + for (cs = switches; cs->c != '\0'; ++cs) { - for (cs = switches; cs->c != '\0'; ++cs) - if (cs->c == *sw) + if (cs->c == c) + switch (cs->type) { - ++sw; - switch (cs->type) - { - default: - abort (); - case ignore: - break; - case flag: - case flag_off: - *(int *) cs->value_ptr = cs->type == flag; - break; - case string: - if (*sw == '\0') - { - arg = argv[++i]; - if (arg == 0) - { - arg = cs->noarg_value; - if (arg == 0) - { - error ("argument required for `-%c' option", - cs->c); - bad = 1; - break; - } - } - } - else - arg = sw; + default: + abort (); - sl = *(struct stringlist **) cs->value_ptr; - if (sl == 0) - { - sl = (struct stringlist *) - xmalloc (sizeof (struct stringlist)); - sl->max = 5; - sl->idx = 0; - sl->list = (char **) xmalloc (5 * sizeof (char *)); - *(struct stringlist **) cs->value_ptr = sl; - } - else if (sl->idx == sl->max - 1) - { - sl->max += 5; - sl->list = (char **) - xrealloc ((char *) sl->list, - sl->max * sizeof (char *)); - } - sl->list[sl->idx++] = savestring (arg, strlen (arg)); - sl->list[sl->idx] = 0; - sw = ""; - break; + case ignore: + break; - case positive_int: - if (*sw == '\0') - arg = argv[++i]; - else - arg = sw; - if (arg != 0 && isdigit (*arg)) - { - int i = atoi (arg); - if (arg == sw) - while (isdigit (*sw)) - ++sw; - if (i < 1) - { - error ("the `-%c' option requires a \ -positive integral argument", - cs->c); - bad = 1; - } - else - *(unsigned int *) cs->value_ptr = i; - } - else - { - if (cs->noarg_value != 0) - *(unsigned int *) cs->value_ptr - = *(unsigned int *) cs->noarg_value; - else - { - error ("the `-%c' option requires an argument", - cs->c); - bad = 1; - } - - if (arg == argv[i]) - /* We moved to the next arg, so move back. */ - --i; - } - break; + case flag: + case flag_off: + *(int *) cs->value_ptr = cs->type == flag; + break; - case floating: - if (*sw == '\0') - arg = argv[++i]; - else - arg = sw; - if (arg != 0 && (*arg == '.' || isdigit (*arg))) + case string: + if (optarg == 0) + optarg = cs->noarg_value; + + sl = *(struct stringlist **) cs->value_ptr; + if (sl == 0) + { + sl = (struct stringlist *) + xmalloc (sizeof (struct stringlist)); + sl->max = 5; + sl->idx = 0; + sl->list = (char **) xmalloc (5 * sizeof (char *)); + *(struct stringlist **) cs->value_ptr = sl; + } + else if (sl->idx == sl->max - 1) + { + sl->max += 5; + sl->list = (char **) + xrealloc ((char *) sl->list, + sl->max * sizeof (char *)); + } + sl->list[sl->idx++] = savestring (optarg, strlen (optarg)); + sl->list[sl->idx] = 0; + break; + + case positive_int: + if (optarg != 0) + { + int i = atoi (optarg); + if (i < 1) { - *(double *) cs->value_ptr = atof (arg); - if (arg == sw) - while (*sw == '.' || isdigit (*sw)) - ++sw; + error ("the `-%c' option requires a \ +positive integral argument", + cs->c); + bad = 1; } else - { - if (cs->noarg_value != 0) - *(double *) cs->value_ptr - = *(double *) cs->noarg_value; - else - { - error ("the `-%c' option requires an argument", - cs->c); - bad = 1; - } - - if (arg == argv[i]) - /* We moved to the next arg, so move back. */ - --i; - } - break; + *(unsigned int *) cs->value_ptr = i; } + else + *(unsigned int *) cs->value_ptr + = *(unsigned int *) cs->noarg_value; + break; - /* We've found the switch. Stop looking. */ + case floating: + if (optarg != 0) + *(double *) cs->value_ptr = atof (optarg); + else + *(double *) cs->value_ptr = *(double *) cs->noarg_value; break; } - - if (cs->c == '\0') - { - error ("unknown option `-%c'", *sw++); - bad = 1; - } + + /* We've found the switch. Stop looking. */ + break; } - else - { - if (other_args->idx == other_args->max - 1) - { - other_args->max += 5; - other_args->list = (char **) - xrealloc ((char *) other_args->list, - other_args->max * sizeof (char *)); - } - other_args->list[other_args->idx++] = argv[i]; - } } if (other_args != 0) other_args->list[other_args->idx] = 0; if (bad) - die (1); + { + /* Print a nice usage message. */ + fprintf (stderr, "Usage: %s [options] [target] ...\n", program); + fputs ("Options:\n", stderr); + for (cs = switches; cs->c != '\0'; ++cs) + { + char buf[100], arg[50]; + + switch (long_options[cs - switches].has_arg) + { + case no_argument: + arg[0] = '\0'; + break; + case required_argument: + sprintf (arg, " %s", cs->argdesc); + break; + case optional_argument: + sprintf (arg, " [%s]", cs->argdesc); + break; + } + + if (cs->long_name == 0) + sprintf (buf, " -%c%s", + cs->c, arg); + else + sprintf (buf, " -%c%s, --%s%s", + cs->c, arg, + cs->long_name, arg); + + if (strlen (buf) >= 30) + { + fprintf (stderr, "%s\n", buf); + buf[0] = '\0'; + } + + fprintf (stderr, "%-30s%s.\n", buf, cs->description); + } + + die (1); + } } static void @@ -1366,12 +1432,12 @@ log_working_directory (entering) PATH_VAR (pwdbuf); char *message = entering ? "Entering" : "Leaving"; - if (entered && entering) + if (entering) + entered = 1; + else if (!entered) /* Don't print the leaving message if we haven't printed the entering message. */ return; - else - entered = 1; if (print_data_base_flag) fputs ("# ", stdout); -- cgit v1.2.3