diff --git a/src/allmain.c b/src/allmain.c index 74260e859..7fcf18b19 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -851,7 +851,7 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg) { int i, idx; boolean match = FALSE; - char *userea = (char *)0; + char *userea = (char *) 0; const char *dashdash = ""; for (idx = 0; idx < SIZE(earlyopts); idx++) { @@ -859,7 +859,7 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg) break; } if ((idx >= SIZE(earlyopts)) || (argc <= 1)) - return FALSE; + return FALSE; for (i = 0; i < argc; ++i) { if (argv[i][0] != '-') @@ -873,7 +873,8 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg) match = match_optname(userea, earlyopts[idx].name, earlyopts[idx].minlength, earlyopts[idx].valallowed); - if (match) break; + if (match) + break; } if (match) { diff --git a/src/files.c b/src/files.c index cb47ad4f0..edbc7b1ec 100644 --- a/src/files.c +++ b/src/files.c @@ -2992,7 +2992,9 @@ config_error_done(void) } #endif if (n) { - pline("\n%d error%s in %s.\n", n, plur(n), + boolean cmdline = !strcmp(config_error_data->source, "command line"); + + pline("\n%d error%s %s %s.\n", n, plur(n), cmdline ? "on" : "in", *config_error_data->source ? config_error_data->source : configfile); wait_synch(); diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 59f41a737..ef27160c0 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -348,30 +348,43 @@ main(int argc, char *argv[]) static void process_options(int argc, char *argv[]) { + static char novalue[] = "[nothing]"; /* note: not 'const' */ + char *p, *arg, *origarg; int i, l; + config_error_init(FALSE, "command line", FALSE); /* * Process options. + * + * We don't support "-xyz" as shortcut for "-x -y -z" and we only + * simulate longopts by allowing "--foo" for "-foo" when the user + * specifies at least 2 characters of leading substring for "foo". + * If "foo" takes a value, both "--foo=value" and "--foo value" work. */ while (argc > 1 && argv[1][0] == '-') { argv++; argc--; - l = (int) strlen(*argv); + arg = origarg = argv[0]; + /* allow second dash if arg is longer than one character */ + if (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0' + /* "--a=b" violates the "--" ok when at least 2 chars long rule */ + && (arg[3] != '\0' && arg[3] != '=' && arg[3] != ':')) + ++arg; + l = (int) strlen(arg); /* must supply at least 4 chars to match "-XXXgraphics" */ if (l < 4) l = 4; - switch (argv[0][1]) { + switch (arg[1]) { case 'D': case 'd': - if ((argv[0][1] == 'D' && !argv[0][2]) - || !strcmpi(*argv, "-debug")) { + if ((arg[1] == 'D' && !arg[2]) || !strcmpi(arg, "-debug")) { wizard = TRUE, discover = FALSE; - } else if (!strncmpi(*argv, "-DECgraphics", l)) { + } else if (!strncmpi(arg, "-DECgraphics", l)) { load_symset("DECGraphics", PRIMARY); switch_symbols(TRUE); } else { - raw_printf("Unknown option: %.60s", *argv); + config_error_add("Unknown option: %.60s", origarg); } break; case 'X': @@ -383,8 +396,8 @@ process_options(int argc, char *argv[]) break; #endif case 'u': - if (argv[0][2]) { - (void) strncpy(g.plname, argv[0] + 2, sizeof g.plname - 1); + if (arg[2]) { + (void) strncpy(g.plname, arg + 2, sizeof g.plname - 1); g.plnamelen = 0; /* plname[] might have -role-race attached */ } else if (argc > 1) { argc--; @@ -392,22 +405,22 @@ process_options(int argc, char *argv[]) (void) strncpy(g.plname, argv[0], sizeof g.plname - 1); g.plnamelen = 0; } else { - raw_print("Player name expected after -u"); + config_error_add("Player name expected after -u"); } break; case 'I': case 'i': - if (!strncmpi(*argv, "-IBMgraphics", l)) { + if (!strncmpi(arg, "-IBMgraphics", l)) { load_symset("IBMGraphics", PRIMARY); load_symset("RogueIBM", ROGUESET); switch_symbols(TRUE); } else { - raw_printf("Unknown option: %.60s", *argv); + config_error_add("Unknown option: %.60s", origarg); } break; case 'p': /* profession (role) */ - if (argv[0][2]) { - if ((i = str2role(&argv[0][2])) >= 0) + if (arg[2]) { + if ((i = str2role(&arg[2])) >= 0) flags.initrole = i; } else if (argc > 1) { argc--; @@ -417,8 +430,8 @@ process_options(int argc, char *argv[]) } break; case 'r': /* race */ - if (argv[0][2]) { - if ((i = str2race(&argv[0][2])) >= 0) + if (arg[2]) { + if ((i = str2race(&arg[2])) >= 0) flags.initrace = i; } else if (argc > 1) { argc--; @@ -427,26 +440,59 @@ process_options(int argc, char *argv[]) flags.initrace = i; } break; - case 'w': /* windowtype */ - config_error_init(FALSE, "command line", FALSE); - choose_windows(&argv[0][2]); - config_error_done(); + case 'w': /* windowtype: "-wfoo" or "-w[indowtype]=foo" + * or "-w[indowtype]:foo" or "-w[indowtype] foo" */ + if ((p = index(arg, '=')) == 0) + p = index(arg, ':'); + l = (int) (p ? (p - arg) : strlen(arg)); + if (!strncmp(arg, "-windowtype", l)) { + /* "-windowtype[=foo]" */ + if (p) + ++p; /* past '=' or ':' */ + else + p = eos(arg); /* we have "-w[indowtype]" w/o "=foo" + * so we'll take foo from next element */ + } else { + /* "-w..." but not "-w[indowtype[=foo]]" */ + if (!p) { + p = &arg[2]; /* past 'w' of "-wfoo" */ + } else { + /* "-w...=foo" but not "-w[indowtype]=foo" */ + config_error_add("Unknown option: %.60s", origarg); + continue; + } + } + if (!*p) { + /* "-w[indowtype]" w/o '='/':' use next element for "foo" */ + if (argc > 1) + --argc, ++argv, p = argv[0]; + else + p = novalue; /* there is no next element */ + } + choose_windows(p); break; case '@': flags.randomall = 1; break; + case '-': + /* "--" or "--x" or "--x=y"; need at least 2 chars after the + dashes in order to accept "--x" as an alternative to "-x"; + don't just silently ignore it */ + config_error_add("Unknown option: %.60s", origarg); + break; default: + /* default for "-x" is to play as the role that starts with "x" */ if ((i = str2role(&argv[0][1])) >= 0) { flags.initrole = i; break; } - /* else raw_printf("Unknown option: %.60s", *argv); */ + /* else config_error_add("Unknown option: %.60s", origarg); */ } } #ifdef SYSCF if (argc > 1) - raw_printf("MAXPLAYERS are set in sysconf file.\n"); + config_error_add("MAXPLAYERS are set in sysconf file.\n"); #else /* XXX This is deprecated in favor of SYSCF with MAXPLAYERS */ if (argc > 1) @@ -462,6 +508,8 @@ process_options(int argc, char *argv[]) if (!g.locknum || (sysopt.maxplayers && g.locknum > sysopt.maxplayers)) g.locknum = sysopt.maxplayers; #endif + /* empty or "N errors on command line" */ + config_error_done(); } #ifdef CHDIR