+/* Sort the args so we can find the most important ones
+ at the beginning of argv. */
+
+/* First, here's a table of all the standard options. */
+
+struct standard_args
+{
+ char *name;
+ char *longname;
+ int priority;
+ int nargs;
+};
+
+struct standard_args standard_args[] =
+{
+ { "-version", "--version", 110, 0 },
+ { "-help", "--help", 110, 0 },
+ { "-nl", "--no-shared-memory", 100, 0 },
+#ifdef VMS
+ { "-map", "--map-data", 100, 0 },
+#endif
+ { "-t", "--terminal", 90, 1 },
+ { "-d", "--display", 80, 1 },
+ { "-display", 0, 80, 1 },
+ { "-nw", "--no-windows", 70, 0 },
+ { "-batch", "--batch", 60, 0 },
+ { "-q", "--no-init-file", 50, 0 },
+ { "-no-init-file", 0, 50, 0 },
+ { "-no-site-file", "--no-site-file", 40, 0 },
+ { "-u", "--user", 30, 1 },
+ { "-user", 0, 30, 1 },
+ { "-debug-init", "--debug-init", 20, 0 },
+ { "-i", "--icon-type", 15, 0 },
+ { "-itype", 0, 15, 0 },
+ { "-iconic", "--iconic", 15, 0 },
+ { "-bg", "--background-color", 10, 1 },
+ { "-background", 0, 10, 1 },
+ { "-fg", "--foreground-color", 10, 1 },
+ { "-foreground", 0, 10, 1 },
+ { "-bd", "--border-color", 10, 1 },
+ { "-bw", "--border-width", 10, 1 },
+ { "-ib", "--internal-border", 10, 1 },
+ { "-ms", "--mouse-color", 10, 1 },
+ { "-cr", "--cursor-color", 10, 1 },
+ { "-fn", "--font", 10, 1 },
+ { "-font", 0, 10, 1 },
+ { "-g", "--geometry", 10, 1 },
+ { "-geometry", 0, 10, 1 },
+ { "-T", "--title", 10, 1 },
+ { "-title", 0, 10, 1 },
+ { "-name", "--name", 10, 1 },
+ { "-xrm", "--xrm", 10, 1 },
+ { "-r", "--reverse-video", 5, 0 },
+ { "-rv", 0, 5, 0 },
+ { "-reverse", 0, 5, 0 },
+ { "-hb", "--horizontal-scroll-bars", 5, 0 },
+ { "-vb", "--vertical-scroll-bars", 5, 0 },
+ /* These have the same priority as ordinary file name args,
+ so they are not reordered with respect to those. */
+ { "-L", "--directory", 0, 1 },
+ { "-directory", 0, 0, 1 },
+ { "-l", "--load", 0, 1 },
+ { "-load", 0, 0, 1 },
+ { "-f", "--funcall", 0, 1 },
+ { "-funcall", 0, 0, 1 },
+ { "-eval", "--eval", 0, 1 },
+ { "-find-file", "--find-file", 0, 1 },
+ { "-visit", "--visit", 0, 1 },
+ { "-insert", "--insert", 0, 1 },
+ /* This should be processed after ordinary file name args and the like. */
+ { "-kill", "--kill", -10, 0 },
+};
+
+/* Reorder the elements of ARGV (assumed to have ARGC elements)
+ so that the highest priority ones come first.
+ Do not change the order of elements of equal priority.
+ If an option takes an argument, keep it and its argument together. */
+
+static void
+sort_args (argc, argv)
+ int argc;
+ char **argv;
+{
+ char **new = (char **) xmalloc (sizeof (char *) * argc);
+ /* For each element of argv,
+ the corresponding element of options is:
+ 0 for an option that takes no arguments,
+ 1 for an option that takes one argument, etc.
+ -1 for an ordinary non-option argument. */
+ int *options = (int *) xmalloc (sizeof (int) * argc);
+ int *priority = (int *) xmalloc (sizeof (int) * argc);
+ int to = 1;
+ int from;
+ int i;
+ int end_of_options = argc;
+
+ /* Categorize all the options,
+ and figure out which argv elts are option arguments. */
+ for (from = 1; from < argc; from++)
+ {
+ options[from] = -1;
+ priority[from] = 0;
+ if (argv[from][0] == '-')
+ {
+ int match, thislen;
+ char *equals;
+
+ /* If we have found "--", don't consider
+ any more arguments as options. */
+ if (argv[from][1] == '-')
+ {
+ /* Leave the "--", and everything following it, at the end. */
+ for (; from < argc; from++)
+ {
+ priority[from] = -100;
+ options[from] = -1;
+ }
+ break;
+ }
+
+ /* Look for a match with a known old-fashioned option. */
+ for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+ if (!strcmp (argv[from], standard_args[i].name))
+ {
+ options[from] = standard_args[i].nargs;
+ priority[from] = standard_args[i].priority;
+ if (from + standard_args[i].nargs >= argc)
+ fatal ("Option `%s' requires an argument\n", argv[from]);
+ from += standard_args[i].nargs;
+ goto done;
+ }
+
+ /* Look for a match with a known long option.
+ MATCH is -1 if no match so far, -2 if two or more matches so far,
+ >= 0 (the table index of the match) if just one match so far. */
+ if (argv[from][1] == '-')
+ {
+ match = -1;
+ thislen = strlen (argv[from]);
+ equals = index (argv[from], '=');
+ if (equals != 0)
+ thislen = equals - argv[from];
+
+ for (i = 0;
+ i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+ if (standard_args[i].longname
+ && !strncmp (argv[from], standard_args[i].longname,
+ thislen))
+ {
+ if (match == -1)
+ match = i;
+ else
+ match = -2;
+ }
+
+ /* If we found exactly one match, use that. */
+ if (match >= 0)
+ {
+ options[from] = standard_args[match].nargs;
+ priority[from] = standard_args[match].priority;
+ /* If --OPTION=VALUE syntax is used,
+ this option uses just one argv element. */
+ if (equals != 0)
+ options[from] = 0;
+ if (from + options[from] >= argc)
+ fatal ("Option `%s' requires an argument\n", argv[from]);
+ from += options[from];
+ }
+ }
+ done: ;
+ }
+ }
+
+ /* Copy the arguments, in order of decreasing priority, to NEW. */
+ new[0] = argv[0];
+ while (to < argc)
+ {
+ int best = -1;
+ int best_priority = -9999;
+
+ /* Find the highest priority remaining option.
+ If several have equal priority, take the first of them. */
+ for (from = 1; from < argc; from++)
+ {
+ if (argv[from] != 0 && priority[from] > best_priority)
+ {
+ best_priority = priority[from];
+ best = from;
+ }
+ /* Skip option arguments--they are tied to the options. */
+ if (options[from] > 0)
+ from += options[from];
+ }
+
+ if (best < 0)
+ abort ();
+
+ /* Copy the highest priority remaining option, with its args, to NEW. */
+ new[to++] = argv[best];
+ for (i = 0; i < options[best]; i++)
+ new[to++] = argv[best + i + 1];
+
+ /* Clear out this option in ARGV. */
+ argv[best] = 0;
+ for (i = 0; i < options[best]; i++)
+ argv[best + i + 1] = 0;
+ }
+
+ bcopy (new, argv, sizeof (char *) * argc);
+
+ free (options);
+ free (new);
+ free (priority);
+}
+\f