diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 713d2cbaf..dfa15732b 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,4 +1,4 @@ -.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.393 $ $NHDT-Date: 1595731545 2020/07/26 02:45:45 $ +.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.394 $ $NHDT-Date: 1596754607 2020/08/06 22:56:47 $ .\" .\" This is an excerpt from the 'roff' man page from the 'groff' package. .\" Guidebook.mn currently does *not* fully adhere to these guidelines. @@ -35,7 +35,7 @@ .ds vr "NetHack 3.7 .ds f0 "\*(vr .ds f1 -.ds f2 "July 25, 2020 +.ds f2 "August 5, 2020 . .\" A note on some special characters: .\" \(lq = left double quote @@ -3138,16 +3138,16 @@ Any line beginning with \(oq[\(cq and ending in \(oq]\(cq is considered a section marker. The text between the square brackets is the section name. Lines after a section marker belong to that section, and are -ignored unless a CHOOSE statement was used to select that section. +ignored unless a CHOOSE directive was used to select that section. Section names are case insensitive. .pg -You can use different configuration statements in the file, some +You can use different configuration directives in the file, some of which can be used multiple times. -In general, the statements are +In general, the directives are written in capital letters, followed by an equals sign, followed by -settings particular to that statement. +settings particular to that directive. .pg -Here is a list of allowed statements: +Here is a list of allowed directives: .lp OPTIONS There are two types of options, boolean and compound options. Boolean options toggle a setting on or off, while compound options @@ -3155,8 +3155,8 @@ take more diverse values. Prefix a boolean option with \(lqno\(rq or \(oq!\(cq to turn it off. For compound options, the option name and value are separated by a colon. Some options are persistent, and apply only to new games. -You can specify multiple OPTIONS statements, and multiple options -separated by commas in a single OPTIONS statement. +You can specify multiple OPTIONS directives, and multiple options +separated by commas in a single OPTIONS directive. (Comma separated options are processed from right to left.) .lp "" Example: @@ -3220,7 +3220,8 @@ Example: .ed .lp CHOOSE Chooses at random one of the comma-separated parameters as an active -section name. Lines in other sections are ignored. +section name. +Lines in other sections are ignored. .lp "" Example: .sd @@ -3231,8 +3232,18 @@ CHOOSE=char A,char B OPTIONS=role:arc,race:dwa,align:law,gender:fem [char B] OPTIONS=role:wiz,race:elf,align:cha,gender:mal +END-CHOOSE +OPTIONS=!rest_on_space .ft \" revert to previous font .ed +.lp END-CHOOSE +An optional way to terminate CHOOSE. +.\" use of the \% prefix prevents END-CHOOSE from being hyphenated across +.\" line boundary despite its hyphen; needed for the plain text output to +.\" avoid splitting the directive name +You can place an \%END-CHOOSE directive after the last CHOOSE section in +order to follow that with other options which are common to all sections. +Otherwise the last section extends to the end of the options file. .lp MENUCOLOR Highlight menu lines with different colors. See the \(lqConfiguring Menu Colors\(rq section. @@ -3342,10 +3353,10 @@ to that shell), or the pair of commands in \fIsh\fP, \fIksh\fP, or \fIbash\fP. .pg The NETHACKOPTIONS value is effectively the same as a single OPTIONS -statement in a configuration file. +directive in a configuration file. The \(lqOPTIONS=\(rq prefix is implied and comma separated options are processed from right to left. -Other types of configuration statements such as BIND or MSGTYPE are +Other types of configuration directives such as BIND or MSGTYPE are not allowed. .pg Instead of a comma-separated list of options, @@ -4338,7 +4349,7 @@ May be used to alter the value of keystrokes that the operating system returns to NetHack to help compensate for international keyboard issues. OPTIONS=subkeyvalue:171/92 will return 92 to NetHack, if 171 was originally going to be returned. -You can use multiple subkeyvalue statements in the configuration file +You can use multiple subkeyvalue assignments in the configuration file if needed. Cannot be set with the \(oqO\(cq command. .lp video diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 47b79d3c4..14c3cd843 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -45,7 +45,7 @@ %.au \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.7 by Mike Stephenson and others)} -\date{July 25, 2020} +\date{August 5, 2020} \maketitle @@ -3359,18 +3359,18 @@ Any line in the configuration file starting with `{\tt \#}' is treated as a comm Empty lines are ignored. Any line beginning with `{\tt [}' and ending in `{\tt ]}' is considered a section marker. The text between the square brackets is the section name. Lines after a section marker belong to that section, and are -ignored unless a CHOOSE -statement was used to select that section. +ignored unless a CHOOSE -directive was used to select that section. Section names are case insensitive. %.pg -You can use different configuration statements in the file, some +You can use different configuration directives in the file, some of which can be used multiple times. -In general, the statements are +In general, the directives are written in capital letters, followed by an equals sign, followed by -settings particular to that statement. +settings particular to that directive. %.pg -Here is a list of allowed statements: +Here is a list of allowed directives: %.lp \blist{} @@ -3381,8 +3381,8 @@ take more diverse values. Prefix a boolean option with `no' or `!' to turn it off. For compound options, the option name and value are separated by a colon. Some options are persistent, and apply only to new games. -You can specify multiple OPTIONS statements, and multiple options -separated by commas in a single OPTIONS statement. +You can specify multiple OPTIONS directives, and multiple options +separated by commas in a single OPTIONS directive. (Comma separated options are processed from right to left.) %.lp "" @@ -3461,7 +3461,8 @@ Example: %.lp \item[\bb{CHOOSE}] Chooses at random one of the comma-separated parameters as an active -section name. Lines in other sections are ignored. +section name. +Lines in other sections are ignored. %.lp "" Example: @@ -3473,9 +3474,18 @@ Example: OPTIONS=role:arc,race:dwa,align:law,gender:fem [char B] OPTIONS=role:wiz,race:elf,align:cha,gender:mal + END-CHOOSE + OPTIONS=!rest_on_space \end{verbatim} %.ed +%.lp +\item[\bb{END-CHOOSE}] +An optional way to terminate CHOOSE. +You can place an END-CHOOSE directive after the last CHOOSE section in +order to follow that with other options which are common to all sections. +Otherwise the last section extends to the end of the options file. + %.lp \item[\bb{MENUCOLOR}] Highlight menu lines with different colors. @@ -3592,10 +3602,10 @@ to that shell), or the pair of commands %.pg The NETHACKOPTIONS value is effectively the same as a single OPTIONS -statement in a configuration file. +directive in a configuration file. The ``OPTIONS='' prefix is implied and comma separated options are processed from right to left. -Other types of configuration statements such as BIND or MSGTYPE are +Other types of configuration directives such as BIND or MSGTYPE are not allowed. %.pg @@ -4745,7 +4755,7 @@ returns to {\it NetHack\/} to help compensate for international keyboard issues. OPTIONS=subkeyvalue:171/92 will return 92 to {\it NetHack\/}, if 171 was originally going to be returned. -You can use multiple subkeyvalue statements in the configuration file +You can use multiple subkeyvalue assignments in the configuration file if needed. Cannot be set with the `{\tt O}' command. %.lp diff --git a/doc/fixes37.0 b/doc/fixes37.0 index d23b99349..35fb1fec0 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.274 $ $NHDT-Date: 1596656886 2020/08/05 19:48:06 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.275 $ $NHDT-Date: 1596754606 2020/08/06 22:56:46 $ General Fixes and Modified Features ----------------------------------- @@ -459,6 +459,11 @@ add 'Sokoban' conduct, tracking the number of times the special Sokoban rules reduce verbosity when a mind flayer attacks a headless monster; when a tentacle-to-head attack hits but fails to accomplish anything skip remaining attacks (mind flayer has 3, master mind flayer has 5) +add END-CHOOSE directive for run-time config file; CHOOSE section1,section2 + followed by [section1] ... [section2] ... forced all the rest of the + file to be part of the last section; that still works the same but + END-CHOOSE can be used to terminate the last section and revert to + common options for the remainder of the file Platform- and/or Interface-Specific New Features diff --git a/src/files.c b/src/files.c index 690f88580..b79c2a913 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 files.c $NHDT-Date: 1595006057 2020/07/17 17:14:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.316 $ */ +/* NetHack 3.7 files.c $NHDT-Date: 1596754598 2020/08/06 22:56:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.317 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -163,7 +163,8 @@ static void FDECL(adjust_prefix, (char *, int)); static boolean FDECL(config_error_nextline, (const char *)); static void NDECL(free_config_sections); static char *FDECL(choose_random_part, (char *, CHAR_P)); -static boolean FDECL(is_config_section, (const char *)); +static char *FDECL(is_config_section, (char *)); +static boolean FDECL(is_end_of_sections, (const char *)); static boolean FDECL(handle_config_section, (char *)); static char *FDECL(find_optparam, (const char *)); static void FDECL(parseformat, (int *, char *)); @@ -2258,7 +2259,7 @@ int prefixid; /* Choose at random one of the sep separated parts from str. Mangles str. */ static char * -choose_random_part(str,sep) +choose_random_part(str, sep) char *str; char sep; { @@ -2310,29 +2311,78 @@ free_config_sections() } } -static boolean +/* check for " [ anything-except-bracket-or-empty ] # arbitrary-comment" + with spaces optional; returns pointer to "anything-except..." (with + trailing " ] #..." stripped) if ok, otherwise Null */ +static char * is_config_section(str) -const char *str; +char *str; /* trailing spaces will be stripped, ']' too iff result is good */ { - const char *a = rindex(str, ']'); + char *a, *c, *z; - return (a && *str == '[' && *(a+1) == '\0' && (int)(a - str) > 0); + /* remove any spaces at start and end; won't significantly interfere + with echoing the string in a config error message, if warranted */ + a = trimspaces(str); + /* first character should be open square bracket; set pointer past it */ + if (*a++ != '[') + return (char *) 0; + /* last character should be close bracket, ignoring any comment */ + z = index(a, ']'); + if (!z || z == a) + return (char *) 0; + for (c = z + 1; *c && *c != '#'; ++c) + continue; + if (*c && *c != '#') + return (char *) 0; + /* we now know that result is good; there won't be a config error + message so we can modify the input string */ + *z = '\0'; + /* 'a' points past '[' and the string ends where ']' was; remove any + spaces between '[' and choice-start and between choice-end and ']' */ + return trimspaces(a); +} + +static boolean +is_end_of_sections(buf) +const char *buf; +{ + /* "END-CHOOSE"; bypass match_optname()/match_varname(); + accepts "ENDCHOOSE", "END CHOOSE", "END-CHOOSE", "END_CHOOSE" */ + if (!strncmpi(buf, "END", 3) && buf[3]) { + boolean sep = index(" -_", buf[3]) != 0; + + if (!strcmpi(&buf[sep ? 4 : 3], "CHOOSE")) { + if (!g.config_section_current) + config_error_add("END-CHOOSE when not in a CHOOSE section"); + return TRUE; + } + } + return FALSE; } static boolean handle_config_section(buf) char *buf; { - if (is_config_section(buf)) { - char *send; - if (g.config_section_current) { + boolean was_in_section = (g.config_section_current != 0); + char *sect = is_config_section(buf); + + if (sect) { + if (g.config_section_current) free(g.config_section_current); + /* is_config_section() removed brackets from 'sect' */ + if (!g.config_section_chosen) { + config_error_add("Section \"[%s]\" without CHOOSE", sect); + return TRUE; } - g.config_section_current = dupstr(&buf[1]); - send = rindex(g.config_section_current, ']'); - *send = '\0'; + g.config_section_current = dupstr(sect); debugpline1("set config section: '%s'", g.config_section_current); return TRUE; + } else if (is_end_of_sections(buf)) { + if (was_in_section) + debugpline0("unset config section"); + free_config_sections(); + return TRUE; } if (g.config_section_current) { @@ -2386,6 +2436,12 @@ char *origbuf; but spaces, one of them will be kept even though it leads/trails) */ mungspaces(buf); + /* "END-CHOOSE" doesn't have a value so we need to check for it + before checking for that; if found here, is_end_of_sections() + will report a config_error */ + if (is_end_of_sections(buf)) + return FALSE; + /* find the '=' or ':' */ bufp = find_optparam(buf); if (!bufp) { @@ -2670,8 +2726,7 @@ char *origbuf; retval = FALSE; #endif } else if (match_varname(buf, "WARNINGS", 5)) { - (void) get_uchars(bufp, translate, FALSE, WARNCOUNT, - "WARNINGS"); + (void) get_uchars(bufp, translate, FALSE, WARNCOUNT, "WARNINGS"); assign_warnings(translate); } else if (match_varname(buf, "ROGUESYMBOLS", 4)) { if (!parsesymbols(bufp, ROGUESET)) {