summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>1992-05-09 04:28:28 +0000
committerRoland McGrath <roland@redhat.com>1992-05-09 04:28:28 +0000
commitea3d4b37122a48ae28e648590b1ddb06665f88c6 (patch)
tree15575301d1af619416c08f6f30702fafbd75f3b6 /main.c
parentcf561391a1dcdae6d5111f2f383e6e7acb31d265 (diff)
downloadgunmake-ea3d4b37122a48ae28e648590b1ddb06665f88c6.tar.gz
Formerly main.c.~40~
Diffstat (limited to 'main.c')
-rw-r--r--main.c416
1 files 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 <time.h>
+#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);