From: Pasi Kallinen Date: Sat, 9 Sep 2017 10:04:03 +0000 (+0300) Subject: Improve config file error reporting X-Git-Tag: NetHack-3.6.1_RC01~391 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f8211f69f2008609b59fe4c9ba341ff1fa520825;p=nethack Improve config file error reporting Show the original line from the config file, followed by the line number and a specific error message. Also show all errors from the config file before waiting for key press. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 85c517573..4032a9dc2 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -420,6 +420,7 @@ surviving a gas spore's explosion would leave that explosion as a stale reason add database entry for "martial arts" starting inventory for rogues specified +9 lock pick, where +/-N is meaningless fix pile mark when picking up all-but-one items while invisible +improve config file error reporting Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 18c3dabbc..4af9fd272 100644 --- a/include/extern.h +++ b/include/extern.h @@ -198,7 +198,7 @@ E int NDECL(enter_explore_mode); E void FDECL(enlightenment, (int, int)); E void FDECL(youhiding, (BOOLEAN_P, int)); E void FDECL(show_conduct, (int)); -E void FDECL(bind_key, (UCHAR_P, const char *)); +E boolean FDECL(bind_key, (UCHAR_P, const char *)); E void NDECL(dokeylist); E int FDECL(xytod, (SCHAR_P, SCHAR_P)); E void FDECL(dtoxy, (coord *, int)); @@ -767,6 +767,9 @@ E void FDECL(unlock_file, (const char *)); #ifdef USER_SOUNDS E boolean FDECL(can_read_file, (const char *)); #endif +E void FDECL(config_error_init, (BOOLEAN_P, const char *)); +E void FDECL(config_error_add, (const char *, ...)) PRINTF_F(1, 2); +E int NDECL(config_error_done); E boolean FDECL(read_config_file, (const char *, int)); E void FDECL(check_recordfile, (const char *)); E void NDECL(read_wizkit); @@ -1679,7 +1682,7 @@ E boolean FDECL(match_optname, (const char *, const char *, int, BOOLEAN_P)); E void NDECL(initoptions); E void NDECL(initoptions_init); E void NDECL(initoptions_finish); -E void FDECL(parseoptions, (char *, BOOLEAN_P, BOOLEAN_P)); +E boolean FDECL(parseoptions, (char *, BOOLEAN_P, BOOLEAN_P)); E int NDECL(doset); E int NDECL(dotogglepickup); E void NDECL(option_help); @@ -1687,7 +1690,7 @@ E void FDECL(next_opt, (winid, const char *)); E int FDECL(fruitadd, (char *, struct fruit *)); E int FDECL(choose_classes_menu, (const char *, int, BOOLEAN_P, char *, char *)); -E void FDECL(parsebindings, (char *)); +E boolean FDECL(parsebindings, (char *)); E void FDECL(add_menu_cmd_alias, (CHAR_P, CHAR_P)); E char FDECL(get_menu_cmd_key, (CHAR_P)); E char FDECL(map_menu_cmd, (CHAR_P)); diff --git a/src/cmd.c b/src/cmd.c index 7437242dd..a6f4a3fcb 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -3056,7 +3056,7 @@ uchar key; return (char *) 0; } -void +boolean bind_key(key, command) uchar key; const char *command; @@ -3066,19 +3066,17 @@ const char *command; /* special case: "nothing" is reserved for unbinding */ if (!strcmp(command, "nothing")) { Cmd.commands[key] = (struct ext_func_tab *) 0; - return; + return TRUE; } for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) { if (strcmp(command, extcmd->ef_txt)) continue; Cmd.commands[key] = extcmd; - return; + return TRUE; } - pline( - "Bad command %s matched with key %c (ASCII %i). Ignoring command.\n", - command, key, key); + return FALSE; } /* initialize all keyboard commands */ @@ -3091,27 +3089,27 @@ commands_init() if (extcmd->key) Cmd.commands[extcmd->key] = extcmd; - bind_key(C('l'), "redraw"); /* if number_pad is set */ + (void) bind_key(C('l'), "redraw"); /* if number_pad is set */ /* 'b', 'B' : go sw */ /* 'F' : fight (one time) */ /* 'g', 'G' : multiple go */ /* 'h', 'H' : go west */ - bind_key('h', "help"); /* if number_pad is set */ - bind_key('j', "jump"); /* if number_pad is on */ + (void) bind_key('h', "help"); /* if number_pad is set */ + (void) bind_key('j', "jump"); /* if number_pad is on */ /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' move commands */ - bind_key('k', "kick"); /* if number_pad is on */ - bind_key('l', "loot"); /* if number_pad is on */ - bind_key(C('n'), "annotate"); /* if number_pad is on */ - bind_key(M('n'), "name"); - bind_key(M('N'), "name"); - bind_key('u', "untrap"); /* if number_pad is on */ + (void) bind_key('k', "kick"); /* if number_pad is on */ + (void) bind_key('l', "loot"); /* if number_pad is on */ + (void) bind_key(C('n'), "annotate"); /* if number_pad is on */ + (void) bind_key(M('n'), "name"); + (void) bind_key(M('N'), "name"); + (void) bind_key('u', "untrap"); /* if number_pad is on */ /* alt keys: */ - bind_key(M('O'), "overview"); - bind_key(M('2'), "twoweapon"); + (void) bind_key(M('O'), "overview"); + (void) bind_key(M('2'), "twoweapon"); /* wait_on_space */ - bind_key(' ', "wait"); + (void) bind_key(' ', "wait"); } int @@ -4007,7 +4005,7 @@ boolean initial; } backed_dir_cmd = TRUE; for (i = 0; i < 8; i++) - bind_key(Cmd.dirchars[i], "nothing"); + (void) bind_key(Cmd.dirchars[i], "nothing"); } } diff --git a/src/files.c b/src/files.c index 7f285b21c..bba7f0e06 100644 --- a/src/files.c +++ b/src/files.c @@ -2,6 +2,8 @@ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ +#define NEED_VARARGS + #include "hack.h" #include "dlb.h" @@ -198,6 +200,7 @@ STATIC_DCL void FDECL(set_symhandling, (char *, int)); #ifdef NOCWD_ASSUMPTIONS STATIC_DCL void FDECL(adjust_prefix, (char *, int)); #endif +STATIC_DCL void FDECL(config_error_nextline, (const char *)); STATIC_DCL void NDECL(free_config_sections); STATIC_DCL char *FDECL(choose_random_part, (char *, CHAR_P)); STATIC_DCL boolean FDECL(is_config_section, (const char *)); @@ -2240,6 +2243,7 @@ int src; char *bufp, *altp, buf[4 * BUFSZ]; uchar translate[MAXPCHARS]; int len; + int retval = 1; /* convert any tab to space, condense consecutive spaces into one, remove leading and trailing spaces (exception: if there is nothing @@ -2257,8 +2261,10 @@ int src; altp = index(buf, ':'); if (!bufp || (altp && altp < bufp)) bufp = altp; - if (!bufp) + if (!bufp) { + config_error_add("Not a config statement, missing '='"); return 0; + } /* skip past '=', then space between it and value, if any */ ++bufp; if (*bufp == ' ') @@ -2278,7 +2284,8 @@ int src; bufp = altp; ++bufp; /* skip '='; parseoptions() handles spaces */ - parseoptions(bufp, TRUE, TRUE); + if (!parseoptions(bufp, TRUE, TRUE)) + retval = 0; } else if (match_varname(buf, "CHOOSE", 6)) { char *section; if (config_section_chosen) @@ -2289,11 +2296,13 @@ int src; } else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) { add_autopickup_exception(bufp); } else if (match_varname(buf, "BINDINGS", 4)) { - parsebindings(bufp); + if (!parsebindings(bufp)) + retval = 0; } else if (match_varname(buf, "AUTOCOMPLETE", 5)) { parseautocomplete(bufp, TRUE); } else if (match_varname(buf, "MSGTYPE", 7)) { - (void) msgtype_parse_add(bufp); + if (!msgtype_parse_add(bufp)) + retval = 0; #ifdef NOCWD_ASSUMPTIONS } else if (match_varname(buf, "HACKDIR", 4)) { adjust_prefix(bufp, HACKPREFIX); @@ -2539,7 +2548,8 @@ int src; (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE, 1, "BOULDER"); } else if (match_varname(buf, "MENUCOLOR", 9)) { - (void) add_menu_coloring(bufp); + if (!add_menu_coloring(bufp)) + retval = 0; } else if (match_varname(buf, "WARNINGS", 5)) { (void) get_uchars(fp, buf, bufp, translate, FALSE, WARNCOUNT, "WARNINGS"); @@ -2719,7 +2729,7 @@ int src; #endif } else return 0; - return 1; + return retval; } #ifdef USER_SOUNDS @@ -2731,6 +2741,81 @@ const char *filename; } #endif /* USER_SOUNDS */ +static int config_err_line_num = 0; +static int config_err_num_errors = 0; +static boolean config_err_origline_shown = FALSE; +static boolean config_err_fromfile = FALSE; +static char config_err_origline[4 * BUFSZ]; +static char config_err_source[BUFSZ]; + +void +config_error_init(from_file, sourcename) +boolean from_file; +const char *sourcename; +{ + config_err_line_num = 0; + config_err_num_errors = 0; + config_err_origline_shown = FALSE; + config_err_fromfile = from_file; + config_err_origline[0] = '\0'; + if (sourcename && sourcename[0]) + Strcpy(config_err_source, sourcename); + else + config_err_source[0] = '\0'; +} + +STATIC_OVL void +config_error_nextline(line) +const char *line; +{ + config_err_line_num++; + config_err_origline_shown = FALSE; + if (line && line[0]) + Strcpy(config_err_origline, line); + else + config_err_origline[0] = '\0'; +} + +/*VARARGS1*/ +void config_error_add +VA_DECL(const char *, str) +/*const char *errmsg;*/ +{ + VA_START(str); + VA_INIT(str, char *); + char buf[BUFSZ]; + char lineno[QBUFSZ]; + + Vsprintf(buf, str, VA_ARGS); + + config_err_num_errors++; + if (!config_err_origline_shown) { + pline("\n%s", config_err_origline); + config_err_origline_shown = TRUE; + } + if (config_err_line_num > 0) { + Sprintf(lineno, "Line %i: ", config_err_line_num); + } else + lineno[0] = '\0'; + pline(" * %s%s.", lineno, (buf && buf[0]) ? buf : "Unknown error"); + + VA_END(); +} + +int +config_error_done() +{ + int n = config_err_num_errors; + if (n) { + pline("\n%i error%s in %s.\n", n, + (n > 1) ? "s" : "", + *config_err_source ? config_err_source : configfile); + wait_synch(); + } + config_error_init(FALSE, ""); + return n; +} + boolean read_config_file(filename, src) const char *filename; @@ -2748,6 +2833,8 @@ int src; free_config_sections(); while (fgets(buf, sizeof buf, fp)) { + strip_newline(buf); + config_error_nextline(buf); #ifdef notyet /* XXX Don't call read() in parse_config_line, read as callback or reassemble @@ -2755,17 +2842,8 @@ line at this level. OR: Forbid multiline stuff for alternate config sources. */ #endif - if (!parse_config_line(fp, strip_newline(buf), src)) { - static const char badoptionline[] = "Bad option line: \"%s\""; - - /* truncate buffer if it's long; this is actually conservative */ - if (strlen(buf) > BUFSZ - sizeof badoptionline) - buf[BUFSZ - sizeof badoptionline] = '\0'; - - raw_printf(badoptionline, buf); - wait_synch(); + if (!parse_config_line(fp, buf, src)) rv = FALSE; - } } (void) fclose(fp); diff --git a/src/options.c b/src/options.c index f0de0cab0..f7a79493d 100644 --- a/src/options.c +++ b/src/options.c @@ -506,8 +506,6 @@ static boolean initial, from_file; STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); STATIC_DCL void FDECL(escapes, (const char *, char *)); STATIC_DCL void FDECL(rejectoption, (const char *)); -STATIC_DCL void FDECL(badoptmsg, (const char *, const char *)); -STATIC_DCL void FDECL(badoption, (const char *)); STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P)); STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P)); STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P)); @@ -517,6 +515,7 @@ STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *)); STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int)); STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int)); +STATIC_DCL int FDECL(match_str2attr, (const char *)); STATIC_DCL const char *FDECL(attr2attrname, (int)); STATIC_DCL int NDECL(query_color); STATIC_DCL int FDECL(query_attr, (const char *)); @@ -638,11 +637,14 @@ initoptions() #ifdef SYSCF_FILE /* If SYSCF_FILE is specified, it _must_ exist... */ assure_syscf_file(); + config_error_init(TRUE, SYSCF_FILE); + /* ... and _must_ parse correctly. */ if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) { - raw_printf("Error(s) found in SYSCF_FILE, quitting."); - nh_terminate(EXIT_FAILURE); + if (config_error_done()) + nh_terminate(EXIT_FAILURE); } + config_error_done(); /* * TODO [maybe]: parse the sysopt entries which are space-separated * lists of usernames into arrays with one name per element. @@ -788,18 +790,29 @@ initoptions_finish() if (*opts == '@') opts++; /* @filename */ /* looks like a filename */ - if (strlen(opts) < BUFSZ / 2) + if (strlen(opts) < BUFSZ / 2) { + config_error_init(TRUE, opts); read_config_file(opts, SET_IN_FILE); + config_error_done(); + } } else { + config_error_init(TRUE, (char *) 0); read_config_file((char *) 0, SET_IN_FILE); + config_error_done(); /* let the total length of options be long; * parseoptions() will check each individually */ - parseoptions(opts, TRUE, FALSE); + config_error_init(FALSE, "NETHACKOPTIONS"); + (void) parseoptions(opts, TRUE, FALSE); + config_error_done(); } } else #endif - read_config_file((char *) 0, SET_IN_FILE); + { + config_error_init(TRUE, (char *) 0); + read_config_file((char *) 0, SET_IN_FILE); + config_error_done(); + } (void) fruitadd(pl_fruit, (struct fruit *) 0); /* @@ -937,43 +950,24 @@ const char *optname; #endif } -STATIC_OVL void -badoptmsg(opts, reason) -const char *opts; -const char *reason; /* "Bad syntax" or "Missing value" */ -{ - const char *linesplit = ""; - - if (!initial) { - if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) - option_help(); - else - pline("%s: %s. Enter \"?g\" for help.", reason, opts); - return; -#ifdef MAC - } else { - return; -#endif - } - -#ifdef WIN32 - linesplit = "\n"; -#endif - if (from_file) - raw_printf("%s in OPTIONS in %s: %s%s.\n", - reason, configfile, linesplit, opts); - else - raw_printf("%s in NETHACKOPTIONS: %s%s.\n", - reason, linesplit, opts); - wait_synch(); -} +/* -STATIC_OVL void -badoption(opts) -const char *opts; -{ - badoptmsg(opts, "Bad syntax"); -} +# errors: +OPTIONS=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +OPTIONS +OPTIONS= +MSGTYPE=stop"You swap places with " +MSGTYPE=st.op "You swap places with " +MSGTYPE=stop "You swap places with \" +MENUCOLOR=" blessed "green&none +MENUCOLOR=" holy " = green&reverse +MENUCOLOR=" cursed " = red&uline +MENUCOLOR=" unholy " = reed +OPTIONS=!legacy:true,fooo +OPTIONS=align:!pin +OPTIONS=gender + +*/ STATIC_OVL char * string_for_opt(opts, val_optional) @@ -989,7 +983,7 @@ boolean val_optional; if (!colon || !*++colon) { if (!val_optional) - badoptmsg(opts, "Missing value"); + config_error_add("Missing parameter for '%s'", opts); return (char *) 0; } return colon; @@ -1115,7 +1109,7 @@ const char *optn; Sprintf(buf, "\n%s=%s Invalid reference to a future version ignored", optn, op); - badoption(buf); + config_error_add(buf); } return 0; } @@ -1324,6 +1318,10 @@ char *str; } if (i == SIZE(colornames) && (*str >= '0' && *str <= '9')) c = atoi(str); + + if (c == CLR_MAX) + config_error_add("Unknown color '%s'", str); + return c; } @@ -1339,6 +1337,25 @@ int attr; return (char *) 0; } +STATIC_OVL int +match_str2attr(str) +const char *str; +{ + int i, a = -1; + + for (i = 0; i < SIZE(attrnames); i++) + if (attrnames[i].name + && fuzzymatch(str, attrnames[i].name, " -_", TRUE)) { + a = attrnames[i].attr; + break; + } + + if (a == -1) + config_error_add("Unknown text attribute '%s'", str); + + return a; +} + STATIC_OVL int query_color() { @@ -1381,6 +1398,8 @@ const char *prompt; start_menu(tmpwin); any = zeroany; for (i = 0; i < SIZE(attrnames); i++) { + if (!attrnames[i].name) + break; any.a_int = i + 1; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr, attrnames[i].name, MENU_UNSELECTED); @@ -1465,10 +1484,11 @@ char *pattern; static const char *re_error = "MSGTYPE regex error"; if (!iflags.window_inited) - raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->regex)); - else + config_error_add("%s: %s", re_error, regex_error_desc(tmp->regex)); + else { pline("%s: %s", re_error, regex_error_desc(tmp->regex)); - wait_synch(); + wait_synch(); + } regex_free(tmp->regex); free((genericptr_t) tmp); return FALSE; @@ -1587,6 +1607,10 @@ char *str; } if (typ != -1) return msgtype_add(typ, pattern); + else + config_error_add("Unknown message type '%s'", msgtype); + } else { + config_error_add("Malformed MSGTYPE"); } return FALSE; } @@ -1624,14 +1648,19 @@ int c, a; /* parse '"regex_string"=color&attr' and add it to menucoloring */ boolean -add_menu_coloring(str) -char *str; +add_menu_coloring(tmpstr) +char *tmpstr; { int i, c = NO_COLOR, a = ATR_NONE; char *tmps, *cs, *amp; + char str[BUFSZ]; + + Sprintf(str, "%s", tmpstr); - if (!str || (cs = index(str, '=')) == 0) + if (!tmpstr || (cs = index(str, '=')) == 0) { + config_error_add("Malformed MENUCOLOR"); return FALSE; + } tmps = cs + 1; /* advance past '=' */ mungspaces(tmps); @@ -1644,17 +1673,9 @@ char *str; if (amp) { tmps = amp + 1; /* advance past '&' */ - /* unlike colors, none of he attribute names has any embedded spaces, - but use of fuzzymatch() allows us ignore the presence of leading - and/or trailing (and also embedded) spaces in the user's string; - dash and underscore skipping could be omitted but does no harm */ - for (i = 0; i < SIZE(attrnames); i++) - if (fuzzymatch(tmps, attrnames[i].name, " -_", TRUE)) { - a = attrnames[i].attr; - break; - } - if (i == SIZE(attrnames) && (*tmps >= '0' && *tmps <= '9')) - a = atoi(tmps); + a = match_str2attr(tmps); + if (a == -1) + return FALSE; } /* the regexp portion here has not been condensed by mungspaces() */ @@ -1766,8 +1787,10 @@ char **opp; val_negated = !val_negated; } if (val_negated) { - if (!setrolefilter(op)) - badoption(opts); + if (!setrolefilter(op)) { + config_error_add("Unknown negated parameter '%s'", op); + return FALSE; + } } else { if (duplicate_opt_detection(opts, 1)) complain_about_duplicate(opts, 1); @@ -1795,7 +1818,7 @@ char c; return FALSE; } -void +boolean parseoptions(opts, tinitial, tfrom_file) register char *opts; boolean tinitial, tfrom_file; @@ -1805,16 +1828,19 @@ boolean tinitial, tfrom_file; boolean negated, duplicate; int i; const char *fullname; + boolean retval = TRUE; initial = tinitial; from_file = tfrom_file; if ((op = index(opts, ',')) != 0) { *op++ = 0; - parseoptions(op, initial, from_file); + if (!parseoptions(op, initial, from_file)) + retval = FALSE; } if (strlen(opts) > BUFSZ / 2) { - badoption("option too long"); - return; + config_error_add("Option too long, max length is %i characters", + (BUFSZ / 2)); + return FALSE; } /* strip leading and trailing white space */ @@ -1824,8 +1850,10 @@ boolean tinitial, tfrom_file; while (--op >= opts && isspace((uchar) *op)) *op = '\0'; - if (!*opts) - return; + if (!*opts) { + config_error_add("Empty statement"); + return FALSE; + } negated = FALSE; while ((*opts == '!') || !strncmpi(opts, "no", 2)) { if (*opts == '!') @@ -1849,7 +1877,7 @@ boolean tinitial, tfrom_file; pline("That is not anatomically possible."); else flags.initgend = flags.female = !negated; - return; + return FALSE; } if (match_optname(opts, "male", 4, FALSE)) { @@ -1859,14 +1887,14 @@ boolean tinitial, tfrom_file; pline("That is not anatomically possible."); else flags.initgend = flags.female = negated; - return; + return FALSE; } #if defined(MICRO) && !defined(AMIGA) /* included for compatibility with old NetHack.cnf files */ if (match_optname(opts, "IBM_", 4, FALSE)) { iflags.BIOS = !negated; - return; + return retval; } #endif /* MICRO */ @@ -1878,10 +1906,12 @@ boolean tinitial, tfrom_file; fullname = "align"; if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initalign = str2align(op)) == ROLE_NONE) - badoption(opts); + if ((flags.initalign = str2align(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } } - return; + return retval; } /* role:string or character:string */ @@ -1889,36 +1919,39 @@ boolean tinitial, tfrom_file; if (match_optname(opts, fullname, 4, TRUE) || match_optname(opts, (fullname = "character"), 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initrole = str2role(op)) == ROLE_NONE) - badoption(opts); - else /* Backwards compatibility */ + if ((flags.initrole = str2role(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } else /* Backwards compatibility */ nmcpy(pl_character, op, PL_NSIZ); } - return; + return retval; } /* race:string */ fullname = "race"; if (match_optname(opts, fullname, 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initrace = str2race(op)) == ROLE_NONE) - badoption(opts); - else /* Backwards compatibility */ + if ((flags.initrace = str2race(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } else /* Backwards compatibility */ pl_race = *op; } - return; + return retval; } /* gender:string */ fullname = "gender"; if (match_optname(opts, fullname, 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initgend = str2gend(op)) == ROLE_NONE) - badoption(opts); - else + if ((flags.initgend = str2gend(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } else flags.female = flags.initgend; } - return; + return retval; } /* We always check for duplicates on the remaining compound options, @@ -1956,48 +1989,52 @@ boolean tinitial, tfrom_file; preferred_pet = '\0'; break; default: - pline("Unrecognized pet type '%s'.", op); + config_error_add("Unrecognized pet type '%s'.", op); + return FALSE; break; } } else if (negated) preferred_pet = 'n'; - return; + return retval; } fullname = "catname"; if (match_optname(opts, fullname, 3, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) + return FALSE; + } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) nmcpy(catname, op, PL_PSIZ); sanitize_name(catname); - return; + return retval; } fullname = "dogname"; if (match_optname(opts, fullname, 3, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) + return FALSE; + } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) nmcpy(dogname, op, PL_PSIZ); sanitize_name(dogname); - return; + return retval; } fullname = "horsename"; if (match_optname(opts, fullname, 5, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) + return FALSE; + } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) nmcpy(horsename, op, PL_PSIZ); sanitize_name(horsename); - return; + return retval; } fullname = "number_pad"; @@ -2016,13 +2053,13 @@ boolean tinitial, tfrom_file; } } else if (negated) { bad_negation("number_pad", TRUE); - return; + return FALSE; } else { int mode = atoi(op); if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) { - badoption(opts); - return; + config_error_add("Illegal %s parameter '%s'", fullname, op); + return FALSE; } else if (mode <= 0) { iflags.num_pad = FALSE; /* German keyboard; y and z keys swapped */ @@ -2040,7 +2077,7 @@ boolean tinitial, tfrom_file; } reset_commands(FALSE); number_pad(iflags.num_pad ? 1 : 0); - return; + return retval; } fullname = "roguesymset"; @@ -2049,6 +2086,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); + return FALSE; } else if ((op = string_for_opt(opts, FALSE)) != 0) { symset[ROGUESET].name = dupstr(op); if (!read_sym_file(ROGUESET)) { @@ -2062,7 +2100,7 @@ boolean tinitial, tfrom_file; need_redraw = TRUE; } } - return; + return retval; } fullname = "symset"; @@ -2071,6 +2109,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); + return FALSE; } else if ((op = string_for_opt(opts, FALSE)) != 0) { symset[PRIMARY].name = dupstr(op); if (!read_sym_file(PRIMARY)) { @@ -2083,7 +2122,7 @@ boolean tinitial, tfrom_file; need_redraw = TRUE; } } - return; + return retval; } fullname = "runmode"; @@ -2101,10 +2140,12 @@ boolean tinitial, tfrom_file; flags.runmode = RUN_STEP; else if (!strncmpi(op, "crawl", strlen(op))) flags.runmode = RUN_CRAWL; - else - badoption(opts); + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } - return; + return retval; } /* menucolor:"regex_string"=color */ @@ -2114,8 +2155,8 @@ boolean tinitial, tfrom_file; bad_negation(fullname, FALSE); else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) if (!add_menu_coloring(op)) - badoption(opts); - return; + return FALSE; + return retval; } fullname = "msghistory"; @@ -2125,9 +2166,11 @@ boolean tinitial, tfrom_file; op = string_for_env_opt(fullname, opts, negated); if ((negated && !op) || (!negated && op)) { iflags.msg_history = negated ? 0 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } fullname = "msg_window"; @@ -2144,7 +2187,7 @@ boolean tinitial, tfrom_file; } else { if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; } tmp = lowc(*op); } @@ -2161,11 +2204,13 @@ boolean tinitial, tfrom_file; case 'r': /* full page (reversed) */ iflags.prevmsg_window = 'r'; break; - default: - badoption(opts); + default: { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } #endif - return; + return retval; } /* WINCAP @@ -2201,8 +2246,8 @@ boolean tinitial, tfrom_file; else if (!strncmpi(fontopts, "_size_status", 11)) opttype = STATUS_OPTION; else { - badoption(opts); - return; + config_error_add("Unknown %s parameter '%s'", fullname, opts); + return FALSE; } if (duplicate) complain_about_duplicate(opts, 1); @@ -2226,19 +2271,22 @@ boolean tinitial, tfrom_file; break; } } - return; + return retval; } else { - badoption(opts); + config_error_add("Unknown %s parameter '%s'", fullname, opts); + return FALSE; } if (opttype > 0 && (op = string_for_opt(opts, FALSE)) != 0) { wc_set_font_name(opttype, op); #ifdef MAC set_font_name(opttype, op); #endif - return; - } else if (negated) + return retval; + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } #ifdef CHANGE_COLOR @@ -2257,7 +2305,7 @@ boolean tinitial, tfrom_file; if (match_optname(opts, "hicolor", 3, TRUE)) { if (negated) { bad_negation("hicolor", FALSE); - return; + return FALSE; } color_number = CLR_MAX + 4; /* HARDCODED inverse number */ color_incr = -1; @@ -2266,15 +2314,17 @@ boolean tinitial, tfrom_file; { if (negated) { bad_negation("palette", FALSE); - return; + return FALSE; } color_number = 0; color_incr = 1; } #ifdef WIN32 op = string_for_opt(opts, TRUE); - if (!alternative_palette(op)) - badoption(opts); + if (!alternative_palette(op)) { + config_error_add("Error in palette parameter '%s'", op); + return FALSE; + } #else if ((op = string_for_opt(opts, FALSE)) != (char *) 0) { char *pt = op; @@ -2320,7 +2370,7 @@ boolean tinitial, tfrom_file; if (!initial) { need_redraw = TRUE; } - return; + return retval; } #endif /* CHANGE_COLOR */ @@ -2334,13 +2384,13 @@ boolean tinitial, tfrom_file; if (negated) { if (op) { bad_negation("fruit", TRUE); - return; + return FALSE; } op = &empty_str; goto goodfruit; } if (!op) - return; + return FALSE; if (!initial) { struct fruit *f; int fnum = 0; @@ -2353,8 +2403,8 @@ boolean tinitial, tfrom_file; forig = fruit_from_name(pl_fruit, FALSE, (int *) 0); if (!forig && fnum >= 100) { - pline("Doing that so many times isn't very fruitful."); - return; + config_error_add("Doing that so many times isn't very fruitful."); + return retval; } } } @@ -2377,7 +2427,7 @@ boolean tinitial, tfrom_file; * no fruit option at all. Also, we don't want people * setting multiple fruits in their options.) */ - return; + return retval; } fullname = "whatis_coord"; @@ -2386,7 +2436,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { iflags.getpos_coords = GPCOORDS_NONE; - return; + return retval; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { static char gpcoords[] = { GPCOORDS_NONE, GPCOORDS_COMPASS, GPCOORDS_COMFULL, GPCOORDS_MAP, @@ -2395,10 +2445,12 @@ boolean tinitial, tfrom_file; if (c && index(gpcoords, c)) iflags.getpos_coords = c; - else - badoption(opts); + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } - return; + return retval; } fullname = "whatis_filter"; @@ -2407,7 +2459,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { iflags.getloc_filter = GFILTER_NONE; - return; + return retval; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char c = lowc(*op); @@ -2421,22 +2473,25 @@ boolean tinitial, tfrom_file; case 'a': iflags.getloc_filter = GFILTER_AREA; break; - default: - badoption(opts); + default: { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } } - return; + return retval; } fullname = "warnings"; if (match_optname(opts, fullname, 5, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else + return FALSE; + } else warning_opts(opts, fullname); - return; + return retval; } #ifdef BACKWARD_COMPAT @@ -2448,12 +2503,12 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } /* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */ if (!(opts = string_for_opt(opts, FALSE))) - return; + return FALSE; escapes(opts, opts); if (def_char_to_monclass(opts[0]) != MAXMCLASSES) clash = 1; @@ -2462,7 +2517,7 @@ boolean tinitial, tfrom_file; if (clash) { /* symbol chosen matches a used monster or warning symbol which is not good - reject it*/ - pline( + config_error_add( "Badoption - boulder symbol '%c' conflicts with a %s symbol.", opts[0], (clash == 1) ? "monster" : "warning"); } else { @@ -2477,7 +2532,7 @@ boolean tinitial, tfrom_file; update_bouldersym(); need_redraw = TRUE; } - return; + return retval; } #endif @@ -2486,11 +2541,12 @@ boolean tinitial, tfrom_file; if (match_optname(opts, fullname, 4, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) + return FALSE; + } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) nmcpy(plname, op, PL_NSIZ); - return; + return retval; } /* altkeyhandler:string */ @@ -2500,13 +2556,14 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); + return FALSE; } else if ((op = string_for_opt(opts, negated)) != 0) { #ifdef WIN32 (void) strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5); load_keyboard_handler(); #endif } - return; + return retval; } /* WINCAP @@ -2523,11 +2580,13 @@ boolean tinitial, tfrom_file; iflags.wc_align_status = ALIGN_RIGHT; else if (!strncmpi(op, "bottom", sizeof("bottom") - 1)) iflags.wc_align_status = ALIGN_BOTTOM; - else - badoption(opts); + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } else if (negated) bad_negation(fullname, TRUE); - return; + return retval; } /* WINCAP * align_message:[left|top|right|bottom] */ @@ -2545,11 +2604,13 @@ boolean tinitial, tfrom_file; iflags.wc_align_message = ALIGN_RIGHT; else if (!strncmpi(op, "bottom", sizeof("bottom") - 1)) iflags.wc_align_message = ALIGN_BOTTOM; - else - badoption(opts); + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } } else if (negated) bad_negation(fullname, TRUE); - return; + return retval; } /* the order to list the pack */ fullname = "packorder"; @@ -2558,13 +2619,13 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(op = string_for_opt(opts, FALSE))) - return; + return FALSE; if (!change_inv_order(op)) - badoption(opts); - return; + return FALSE; + return retval; } /* user can change required response for some prompts (quit, die, hit), @@ -2611,8 +2672,8 @@ boolean tinitial, tfrom_file; if (i == SIZE(paranoia)) { /* didn't match anything, so arg is bad; any flags already set will stay set */ - badoption(opts); - break; + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; } /* move on to next token */ if (pp) @@ -2621,7 +2682,7 @@ boolean tinitial, tfrom_file; break; /* no next token */ } /* for(;;) */ } - return; + return retval; } /* accept deprecated boolean; superseded by paranoid_confirm:pray */ @@ -2631,7 +2692,7 @@ boolean tinitial, tfrom_file; flags.paranoia_bits &= ~PARANOID_PRAY; else flags.paranoia_bits |= PARANOID_PRAY; - return; + return retval; } /* maximum burden picked up before prompt (Warren Cheung) */ @@ -2641,7 +2702,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { switch (lowc(*op)) { case 'u': /* Unencumbered */ @@ -2664,10 +2725,11 @@ boolean tinitial, tfrom_file; flags.pickup_burden = OVERLOADED; break; default: - badoption(opts); + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; } } - return; + return retval; } /* types of objects to pick up automatically */ @@ -2688,7 +2750,7 @@ boolean tinitial, tfrom_file; value is a synonym for autopickup of all types (and during initialization, we can't prompt yet) */ flags.pickup = !negated; - return; + return retval; } oc_to_str(flags.inv_order, ocl); use_menu = TRUE; @@ -2712,7 +2774,7 @@ boolean tinitial, tfrom_file; } if (negated) { bad_negation("pickup_types", TRUE); - return; + return FALSE; } while (*op == ' ') op++; @@ -2729,10 +2791,12 @@ boolean tinitial, tfrom_file; badopt = TRUE; op++; } - if (badopt) - badoption(opts); + if (badopt) { + config_error_add("Unknown %s parameter '%s'", "pickup_types", op); + return FALSE; + } } - return; + return retval; } /* pile limit: when walking over objects, number which triggers @@ -2751,7 +2815,7 @@ boolean tinitial, tfrom_file; /* sanity check */ if (flags.pile_limit < 0) flags.pile_limit = PILE_LIMIT_DFLT; - return; + return retval; } /* play mode: normal, explore/discovery, or debug/wizard */ @@ -2762,10 +2826,10 @@ boolean tinitial, tfrom_file; if (negated) bad_negation(fullname, FALSE); if (duplicate || negated) - return; + return FALSE; op = string_for_opt(opts, FALSE); if (!op) - return; + return FALSE; if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) { wizard = discover = FALSE; } else if (!strncmpi(op, "explore", 6) @@ -2774,9 +2838,10 @@ boolean tinitial, tfrom_file; } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) { wizard = TRUE, discover = FALSE; } else { - raw_printf("Invalid value for \"%s\":%s.", fullname, op); + config_error_add("Invalid value for \"%s\":%s.", fullname, op); + return FALSE; } - return; + return retval; } /* WINCAP @@ -2791,11 +2856,13 @@ boolean tinitial, tfrom_file; iflags.wc_player_selection = VIA_DIALOG; else if (!strncmpi(op, "prompt", sizeof("prompt") - 1)) iflags.wc_player_selection = VIA_PROMPTS; - else - badoption(opts); + else { + config_error_add("Unknown %s parameter '%s'", "pickup_types", op); + return FALSE; + } } else if (negated) bad_negation(fullname, TRUE); - return; + return retval; } /* things to disclose at end of game */ @@ -2829,7 +2896,7 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, TRUE); if (op && negated) { bad_negation("disclose", TRUE); - return; + return FALSE; } /* "disclose" without a value means "all with prompting" and negated means "none without prompting" */ @@ -2840,7 +2907,7 @@ boolean tinitial, tfrom_file; flags.end_disclose[num] = negated ? DISCLOSE_NO_WITHOUT_PROMPT : DISCLOSE_PROMPT_DEFAULT_YES; - return; + return retval; } num = 0; @@ -2885,9 +2952,11 @@ boolean tinitial, tfrom_file; badopt = TRUE; op++; } - if (badopt) - badoption(opts); - return; + if (badopt) { + config_error_add("Unknown %s parameter '%s'", "disclose", op); + return FALSE; + } + return retval; } /* scores:5t[op] 5a[round] o[wn] */ @@ -2896,10 +2965,10 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation("scores", FALSE); - return; + return FALSE; } if (!(op = string_for_opt(opts, FALSE))) - return; + return FALSE; while (*op) { int inum = 1; @@ -2929,15 +2998,15 @@ boolean tinitial, tfrom_file; flags.end_own = !negated; break; default: - badoption(opts); - return; + config_error_add("Unknown %s parameter '%s'", "scores", op); + return FALSE; } while (letter(*++op) || *op == ' ') continue; if (*op == '/') op++; } - return; + return retval; } fullname = "sortloot"; @@ -2953,11 +3022,11 @@ boolean tinitial, tfrom_file; flags.sortloot = c; break; default: - badoption(opts); - return; + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; } } - return; + return retval; } fullname = "suppress_alert"; @@ -2965,11 +3034,12 @@ boolean tinitial, tfrom_file; if (duplicate) complain_about_duplicate(opts, 1); op = string_for_opt(opts, negated); - if (negated) + if (negated) { bad_negation(fullname, FALSE); - else if (op) + return FALSE; + } else if (op) (void) feature_alert_opts(op, fullname); - return; + return retval; } #ifdef VIDEOSHADES @@ -2981,13 +3051,13 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { - return; + return FALSE; } - if (!assign_videocolors(opts)) - badoption(opts); - return; + if (!assign_videocolors(opts)) /* TODO: error msg */ + return FALSE; + return retval; } /* videoshades:string */ fullname = "videoshades"; @@ -2996,13 +3066,13 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { - return; + return FALSE; } - if (!assign_videoshades(opts)) - badoption(opts); - return; + if (!assign_videoshades(opts)) /* TODO: error msg */ + return FALSE; + return retval; } #endif /* VIDEOSHADES */ #ifdef MSDOS @@ -3014,13 +3084,13 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { - return; + return FALSE; } - if (!assign_video(opts)) - badoption(opts); - return; + if (!assign_video(opts)) /* TODO: error msg */ + return FALSE; + return retval; } #endif /* NO_TERMS */ /* soundcard:string -- careful not to match boolean 'sound' */ @@ -3030,13 +3100,13 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { - return; + return FALSE; } - if (!assign_soundcard(opts)) - badoption(opts); - return; + if (!assign_soundcard(opts)) /* TODO: error msg */ + return FALSE; + return retval; } #endif /* MSDOS */ @@ -3074,11 +3144,15 @@ boolean tinitial, tfrom_file; else if (!strncmpi(op, "fit_to_screen", sizeof("fit_to_screen") - 1)) iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN; - else - badoption(opts); - } else if (negated) + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } /* WINCAP * scroll_amount:nn */ @@ -3089,9 +3163,11 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, negated); if ((negated && !op) || (!negated && op)) { iflags.wc_scroll_amount = negated ? 1 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } /* WINCAP * scroll_margin:nn */ @@ -3102,22 +3178,25 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, negated); if ((negated && !op) || (!negated && op)) { iflags.wc_scroll_margin = negated ? 5 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } fullname = "subkeyvalue"; if (match_optname(opts, fullname, 5, TRUE)) { /* no duplicate complaint here */ if (negated) { bad_negation(fullname, FALSE); + return FALSE; } else { #if defined(WIN32) op = string_for_opt(opts, 0); map_subkeyvalue(op); #endif } - return; + return retval; } /* WINCAP * tile_width:nn */ @@ -3128,9 +3207,11 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, negated); if ((negated && !op) || (!negated && op)) { iflags.wc_tile_width = negated ? 0 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } /* WINCAP * tile_file:name */ @@ -3143,7 +3224,7 @@ boolean tinitial, tfrom_file; free(iflags.wc_tile_file); iflags.wc_tile_file = dupstr(op); } - return; + return retval; } /* WINCAP * tile_height:nn */ @@ -3154,9 +3235,11 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, negated); if ((negated && !op) || (!negated && op)) { iflags.wc_tile_height = negated ? 0 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } /* WINCAP * vary_msgcount:nn */ @@ -3167,9 +3250,11 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, negated); if ((negated && !op) || (!negated && op)) { iflags.wc_vary_msgcount = negated ? 0 : atoi(op); - } else if (negated) + } else if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; + } + return retval; } fullname = "windowtype"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -3177,26 +3262,26 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char buf[WINTYPELEN]; nmcpy(buf, op, WINTYPELEN); choose_windows(buf); } - return; + return retval; } #ifdef WINCHAIN fullname = "windowchain"; if (match_optname(opts, fullname, 3, TRUE)) { if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char buf[WINTYPELEN]; nmcpy(buf, op, WINTYPELEN); addto_windowchain(buf); } - return; + return retval; } #endif @@ -3209,11 +3294,11 @@ boolean tinitial, tfrom_file; if (duplicate) complain_about_duplicate(opts, 1); if ((op = string_for_opt(opts, FALSE)) != 0) { - if (!wc_set_window_colors(op)) - badoption(opts); + if (!wc_set_window_colors(op)) /* TODO: error msg*/ + return FALSE; } else if (negated) bad_negation(fullname, TRUE); - return; + return retval; } /* menustyle:traditional or combination or full or partial */ @@ -3225,7 +3310,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (!(op = string_for_opt(opts, !val_required))) { if (val_required) - return; /* string_for_opt gave feedback */ + return FALSE; /* string_for_opt gave feedback */ tmp = negated ? 'n' : 'f'; } else { tmp = lowc(*op); @@ -3249,28 +3334,29 @@ boolean tinitial, tfrom_file; flags.menu_style = MENU_PARTIAL; break; default: - badoption(opts); + config_error_add("Unknown %s parameter '%s'", "menustyle", op); + return FALSE; } - return; + return retval; } fullname = "menu_headings"; if (match_optname(opts, fullname, 12, TRUE)) { + int tmpattr; if (duplicate) complain_about_duplicate(opts, 1); if (negated) { bad_negation(fullname, FALSE); - return; + return FALSE; } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { - return; + return FALSE; } - for (i = 0; i < SIZE(attrnames); i++) - if (!strcmpi(opts, attrnames[i].name)) { - iflags.menu_headings = attrnames[i].attr; - return; - } - badoption(opts); - return; + tmpattr = match_str2attr(opts); + if (tmpattr == -1) + return FALSE; + else + iflags.menu_headings = tmpattr; + return retval; } /* check for menu command mapping */ @@ -3287,12 +3373,13 @@ boolean tinitial, tfrom_file; escapes(op, op_buf); c = *op_buf; - if (illegal_menu_cmd_key(c)) - badoption(opts); - else + if (illegal_menu_cmd_key(c)) { + /* TODO FIXME */ + return FALSE; + } else add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd); } - return; + return retval; } } #if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES) @@ -3303,15 +3390,14 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, TRUE); if (op && negated) { clear_status_hilites(tfrom_file); - return; + return retval; } else if (!op) { - /* a value is mandatory */ - badoption(opts); - return; + config_error_add("Value is mandatory for hilite_status"); + return FALSE; } - if (!set_status_hilites(op, tfrom_file)) - badoption(opts); - return; + if (!set_status_hilites(op, tfrom_file)) /* TODO: error msg? */ + return FALSE; + return retval; } #endif @@ -3339,7 +3425,7 @@ boolean tinitial, tfrom_file; wait_synch(); } } - return; + return retval; } fullname = "IBMgraphics"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -3372,7 +3458,7 @@ boolean tinitial, tfrom_file; assign_graphics(ROGUESET); } } - return; + return retval; } #endif #ifdef MAC_GRAPHICS_ENV @@ -3401,7 +3487,7 @@ boolean tinitial, tfrom_file; assign_graphics(ROGUESET); } } - return; + return retval; } #endif @@ -3415,28 +3501,28 @@ boolean tinitial, tfrom_file; if (!initial && !negated) pline_The("\"%s\" option is not available.", boolopt[i].name); - return; + return retval; } /* options that must come from config file */ if (!initial && (boolopt[i].optflags == SET_IN_FILE)) { rejectoption(boolopt[i].name); - return; + return retval; } op = string_for_opt(opts, TRUE); if (op) { if (negated) { - badoption(opts); - return; + config_error_add("Negated boolean '%s' should not have a parameter", boolopt[i].name); + return FALSE; } if (!strcmp(op, "true") || !strcmp(op, "yes")) { negated = FALSE; } else if (!strcmp(op, "false") || !strcmp(op, "no")) { negated = TRUE; } else { - badoption(opts); - return; + config_error_add("Illegal parameter for a boolean"); + return FALSE; } } @@ -3455,7 +3541,7 @@ boolean tinitial, tfrom_file; #endif /* only do processing below if setting with doset() */ if (initial) - return; + return retval; if (boolopt[i].addr == &flags.time #ifdef SCORE_ON_BOTL @@ -3501,69 +3587,73 @@ boolean tinitial, tfrom_file; #endif #endif /* TEXTCOLOR */ } - return; + return retval; } } /* Is it a symbol? */ if (strstr(opts, "S_") == opts && parsesymbols(opts)) { switch_symbols(TRUE); - return; + return retval; } /* out of valid options */ - badoption(opts); + config_error_add("Unknown option '%s'", opts); + return FALSE; } /* parse key:command */ -void +boolean parsebindings(bindings) char* bindings; { char *bind; char key; int i; + boolean ret = FALSE; /* break off first binding from the rest; parse the rest */ if ((bind = index(bindings, ',')) != 0) { *bind++ = 0; - parsebindings(bind); + ret |= parsebindings(bind); } /* parse a single binding: first split around : */ if (! (bind = index(bindings, ':'))) - return; /* it's not a binding */ + return FALSE; /* it's not a binding */ *bind++ = 0; /* read the key to be bound */ key = txt2key(bindings); if (!key) { - raw_printf("Bad binding %s.", bindings); - wait_synch(); - return; + config_error_add("Unknown key binding key '%s'", bindings); + return FALSE; } bind = trimspaces(bind); /* is it a special key? */ if (bind_specialkey(key, bind)) - return; + return TRUE; /* is it a menu command? */ for (i = 0; i < SIZE(default_menu_cmd_info); i++) { if (!strcmp(default_menu_cmd_info[i].name, bind)) { if (illegal_menu_cmd_key(key)) { - char tmp[BUFSZ]; - Sprintf(tmp, "Bad menu key %s:%s", visctrl(key), bind); - badoption(tmp); + config_error_add("Bad menu key %s:%s", visctrl(key), bind); + return FALSE; } else add_menu_cmd_alias(key, default_menu_cmd_info[i].cmd); - return; + return TRUE; } } /* extended command? */ - bind_key(key, bind); + if (!bind_key(key, bind)) { + config_error_add("Unknown key binding command '%s'", bind); + return FALSE; + } + return TRUE; } static NEARDATA const char *menutype[] = { "traditional", "combination",