consolidate some arg processing
Unix and Windows had diverged significantly for command line
options handling.
This:
1. uses the the Unix processing as a baseline.
2. consolidates the code in earlyarg.c, where it can
be a common copy to be shared.
3. start converting the Windows command line argument
processing to the Unix code that now resides in earlyarg.c.
This commit is contained in:
+6
-2
@@ -922,6 +922,10 @@ extern const char *endgamelevelname(char *, int);
|
|||||||
/* ### earlyarg.c ### */
|
/* ### earlyarg.c ### */
|
||||||
|
|
||||||
extern int argcheck(int, char **, enum earlyarg);
|
extern int argcheck(int, char **, enum earlyarg);
|
||||||
|
extern void early_options(int *argc_p, char ***argv_p, char **hackdir_p);
|
||||||
|
#ifdef WIN32
|
||||||
|
int windows_early_options(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ### eat.c ### */
|
/* ### eat.c ### */
|
||||||
|
|
||||||
@@ -2344,9 +2348,9 @@ extern int dohistory(void);
|
|||||||
|
|
||||||
/* ### xxmain.c ### */
|
/* ### xxmain.c ### */
|
||||||
|
|
||||||
#if defined(MICRO) || defined(WIN32)
|
#if defined(UNIX) || defined(MICRO) || defined(WIN32)
|
||||||
#ifdef CHDIR
|
#ifdef CHDIR
|
||||||
extern void chdirx(char *, boolean);
|
extern void chdirx(const char *, boolean);
|
||||||
#endif /* CHDIR */
|
#endif /* CHDIR */
|
||||||
extern boolean authorize_wizard_mode(void);
|
extern boolean authorize_wizard_mode(void);
|
||||||
extern boolean authorize_explore_mode(void);
|
extern boolean authorize_explore_mode(void);
|
||||||
|
|||||||
@@ -817,6 +817,7 @@ struct sinfo {
|
|||||||
interface to suppress menu commands in similar conditions;
|
interface to suppress menu commands in similar conditions;
|
||||||
readchar() always resets it to 'otherInp' prior to returning */
|
readchar() always resets it to 'otherInp' prior to returning */
|
||||||
int input_state; /* whether next key pressed will be entering a command */
|
int input_state; /* whether next key pressed will be entering a command */
|
||||||
|
int early_options; /* inside early_options processing */
|
||||||
#ifdef TTY_GRAPHICS
|
#ifdef TTY_GRAPHICS
|
||||||
/* resize_pending only matters when handling a SIGWINCH signal for tty;
|
/* resize_pending only matters when handling a SIGWINCH signal for tty;
|
||||||
getting_char is used along with that and also separately for UNIX;
|
getting_char is used along with that and also separately for UNIX;
|
||||||
|
|||||||
+2
-2
@@ -1907,9 +1907,9 @@ assure_syscf_file(void)
|
|||||||
#else
|
#else
|
||||||
fd = open(SYSCF_FILE, O_RDONLY);
|
fd = open(SYSCF_FILE, O_RDONLY);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else /* VMS */
|
||||||
fd = open(SYSCF_FILE, O_RDONLY, 0);
|
fd = open(SYSCF_FILE, O_RDONLY, 0);
|
||||||
#endif
|
#endif /* VMS */
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
/* readable */
|
/* readable */
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|||||||
+387
-2
@@ -3,11 +3,22 @@
|
|||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
#include "hack.h"
|
#include "hack.h"
|
||||||
|
#include "dlb.h"
|
||||||
|
|
||||||
staticfn void debug_fields(char *);
|
staticfn void debug_fields(char *);
|
||||||
#ifndef NODUMPENUMS
|
#ifndef NODUMPENUMS
|
||||||
staticfn void dump_enums(void);
|
staticfn void dump_enums(void);
|
||||||
#endif
|
#endif
|
||||||
|
ATTRNORETURN staticfn void opt_terminate(void) NORETURN;
|
||||||
|
ATTRNORETURN staticfn void opt_usage(const char *) NORETURN;
|
||||||
|
ATTRNORETURN staticfn void scores_only(int, char **, const char *) NORETURN;
|
||||||
|
staticfn char *lopt(char *, int, const char *, const char *, int *, char ***);
|
||||||
|
staticfn void consume_arg(int, int *, char ***);
|
||||||
|
staticfn void consume_two_args(int, int *, char ***);
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
extern boolean whoami(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Argument processing helpers - for xxmain() to share
|
* Argument processing helpers - for xxmain() to share
|
||||||
@@ -40,9 +51,383 @@ static const struct early_opt earlyopts[] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WIN32
|
static char ArgVal_novalue[] = "[nothing]"; /* note: not 'const' */
|
||||||
extern int windows_early_options(const char *);
|
|
||||||
|
enum cmdlinearg {
|
||||||
|
ArgValRequired = 0,
|
||||||
|
ArgValOptional = 1,
|
||||||
|
ArgValDisallowed = 2,
|
||||||
|
ArgVal_mask = (1 | 2),
|
||||||
|
ArgNamOneLetter = 4,
|
||||||
|
ArgNam_mask = 4,
|
||||||
|
ArgErrSilent = 0,
|
||||||
|
ArgErrComplain = 8,
|
||||||
|
ArgErr_mask = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
/* approximate 'getopt_long()' for one option; all the comments refer to
|
||||||
|
"-windowtype" but the code isn't specific to that */
|
||||||
|
staticfn char *
|
||||||
|
lopt(char *arg, /* command line token; beginning matches 'optname' */
|
||||||
|
int lflags, /* cmdlinearg | errorhandling */
|
||||||
|
const char *optname, /* option's name; "-windowtype" in examples below */
|
||||||
|
const char *origarg, /* 'arg' might have had a dash prefix removed */
|
||||||
|
int *argc_p, /* argc that can have changes passed to caller */
|
||||||
|
char ***argv_p) /* argv[] ditto */
|
||||||
|
{
|
||||||
|
int argc = *argc_p;
|
||||||
|
char **argv = *argv_p;
|
||||||
|
char *p, *nextarg = (argc > 1 && argv[1][0] != '-') ? argv[1] : 0;
|
||||||
|
int l, opttype = (lflags & ArgVal_mask);
|
||||||
|
boolean oneletterok = ((lflags & ArgNam_mask) == ArgNamOneLetter),
|
||||||
|
complain = ((lflags & ArgErr_mask) == ArgErrComplain);
|
||||||
|
|
||||||
|
/* first letter must match */
|
||||||
|
if (arg[1] != optname[1]) {
|
||||||
|
loptbail:
|
||||||
|
if (complain)
|
||||||
|
config_error_add("Unknown option: %.60s", origarg);
|
||||||
|
return (char *) 0;
|
||||||
|
loptnotallowed:
|
||||||
|
if (complain)
|
||||||
|
config_error_add("Value not allowed: %.60s", origarg);
|
||||||
|
return (char *) 0;
|
||||||
|
loptrequired:
|
||||||
|
if (complain)
|
||||||
|
config_error_add("Missing required value: %.60s", origarg);
|
||||||
|
return (char *) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p = strchr(arg, '=')) == 0)
|
||||||
|
p = strchr(arg, ':');
|
||||||
|
if (p && opttype == ArgValDisallowed)
|
||||||
|
goto loptnotallowed;
|
||||||
|
|
||||||
|
l = (int) (p ? (long) (p - arg) : (long) strlen(arg));
|
||||||
|
if ((l > 2 || oneletterok) && !strncmp(arg, optname, l)) {
|
||||||
|
/* "-windowtype[=foo]" */
|
||||||
|
if (p)
|
||||||
|
++p; /* past '=' or ':' */
|
||||||
|
else if (opttype == ArgValRequired)
|
||||||
|
p = eos(arg); /* we have "-w[indowtype]" w/o "=foo"
|
||||||
|
* so we'll take foo from next element */
|
||||||
|
else
|
||||||
|
return ArgVal_novalue;
|
||||||
|
} else if (oneletterok) {
|
||||||
|
/* "-w..." but not "-w[indowtype[=foo]]" */
|
||||||
|
if (!p) {
|
||||||
|
p = &arg[2]; /* past 'w' of "-wfoo" */
|
||||||
|
#if 0 /* -x:value could work but is not supported (callers don't expect it) \
|
||||||
|
*/
|
||||||
|
} else if (p == arg + 2) {
|
||||||
|
++p; /* past ':' of "-w:foo" */
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
/* "-w...=foo" but not "-w[indowtype]=foo" */
|
||||||
|
goto loptbail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
goto loptbail;
|
||||||
|
}
|
||||||
|
if (!p || !*p) {
|
||||||
|
/* "-w[indowtype]" w/o '='/':' if there is a next element, use
|
||||||
|
it for "foo"; if not, supply a non-Null bogus value */
|
||||||
|
if (nextarg
|
||||||
|
&& (opttype == ArgValRequired || opttype == ArgValOptional))
|
||||||
|
p = nextarg, --(*argc_p), ++(*argv_p);
|
||||||
|
else if (opttype == ArgValRequired)
|
||||||
|
goto loptrequired;
|
||||||
|
else
|
||||||
|
p = ArgVal_novalue; /* there is no next element */
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
/* move argv[ndx] to end of argv[] array, then reduce argc to hide it;
|
||||||
|
prevents process_options() from encountering it after early_options()
|
||||||
|
has processed it; elements get reordered but all remain intact */
|
||||||
|
staticfn void
|
||||||
|
consume_arg(int ndx, int *ac_p, char ***av_p)
|
||||||
|
{
|
||||||
|
char *gone, **av = *av_p;
|
||||||
|
int i, ac = *ac_p;
|
||||||
|
|
||||||
|
/* "-one -two -three -four" -> "-two -three -four -one" */
|
||||||
|
if (ac > 2) {
|
||||||
|
gone = av[ndx];
|
||||||
|
for (i = ndx + 1; i < ac; ++i)
|
||||||
|
av[i - 1] = av[i];
|
||||||
|
av[ac - 1] = gone;
|
||||||
|
}
|
||||||
|
--(*ac_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* consume two tokens for '-argname value' w/o '=' or ':' */
|
||||||
|
staticfn void
|
||||||
|
consume_two_args(int ndx, int *ac_p, char ***av_p)
|
||||||
|
{
|
||||||
|
/* when consuming "-two arg" from "-two arg -three -four",
|
||||||
|
the *ac_p manipulation results in "-three -four -two arg"
|
||||||
|
rather than the "-three -four arg -two" that would happen
|
||||||
|
with just two ordinary consume_arg() calls */
|
||||||
|
consume_arg(ndx, ac_p, av_p);
|
||||||
|
++(*ac_p); /* bring the final slot back into view */
|
||||||
|
consume_arg(ndx, ac_p, av_p);
|
||||||
|
--(*ac_p); /* take away restored slot */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process some command line arguments before loading options */
|
||||||
|
void
|
||||||
|
early_options(int *argc_p, char ***argv_p, char **hackdir_p)
|
||||||
|
{
|
||||||
|
char **argv, *arg, *origarg;
|
||||||
|
int argc, oldargc, ndx = 0, consumed = 0;
|
||||||
|
|
||||||
|
config_error_init(FALSE, "command line", FALSE);
|
||||||
|
|
||||||
|
/* treat "nethack ?" as a request for usage info; due to shell
|
||||||
|
processing, player likely has to use "nethack \?" or "nethack '?'"
|
||||||
|
[won't work if used as "nethack -dpath ?" or "nethack -d path ?"] */
|
||||||
|
if (*argc_p > 1 && !strcmp((*argv_p)[1], "?"))
|
||||||
|
opt_usage(*hackdir_p); /* doesn't return */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Both *argc_p and *argv_p account for the program name as (*argv_p)[0];
|
||||||
|
* local argc and argv implicitly discard that (by starting 'ndx' at 1).
|
||||||
|
* argcheck() doesn't mind, prscore() (via scores_only()) does (for the
|
||||||
|
* number of args it gets passed, not for the value of argv[0]).
|
||||||
|
*/
|
||||||
|
for (ndx = 1; ndx < *argc_p; ndx += (consumed ? 0 : 1)) {
|
||||||
|
consumed = 0;
|
||||||
|
argc = *argc_p - ndx;
|
||||||
|
argv = *argv_p + ndx;
|
||||||
|
|
||||||
|
arg = origarg = argv[0];
|
||||||
|
/* skip any args intended for deferred options */
|
||||||
|
if (*arg != '-')
|
||||||
|
continue;
|
||||||
|
/* allow second dash if arg name is longer than one character */
|
||||||
|
if (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0'
|
||||||
|
&& (arg[3] != '\0' && arg[3] != '=' && arg[3] != ':'))
|
||||||
|
++arg;
|
||||||
|
|
||||||
|
switch (arg[1]) { /* char after leading dash */
|
||||||
|
case 'b':
|
||||||
|
#ifdef CRASHREPORT
|
||||||
|
// --bidshow
|
||||||
|
if (argcheck(argc, argv, ARG_BIDSHOW) == 2) {
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
|
||||||
|
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
||||||
|
#ifndef NODUMPENUMS
|
||||||
|
} else if (argcheck(argc, argv, ARG_DUMPENUMS) == 2) {
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
#endif
|
||||||
|
} else if (argcheck(argc, argv, ARG_DUMPMONGEN) == 2) {
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
} else if (argcheck(argc, argv, ARG_DUMPWEIGHTS) == 2) {
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
} else {
|
||||||
|
#ifdef CHDIR
|
||||||
|
oldargc = argc;
|
||||||
|
arg = lopt(arg,
|
||||||
|
(ArgValRequired | ArgNamOneLetter | ArgErrSilent),
|
||||||
|
"-directory", origarg, &argc, &argv);
|
||||||
|
if (!arg)
|
||||||
|
error("Flag -d must be followed by a directory name.");
|
||||||
|
if (*arg != 'e') { /* avoid matching -decgraphics or -debug */
|
||||||
|
*hackdir_p = arg;
|
||||||
|
if (oldargc == argc)
|
||||||
|
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
||||||
|
else
|
||||||
|
consume_two_args(ndx, argc_p, argv_p), consumed = 2;
|
||||||
|
}
|
||||||
|
#endif /* CHDIR */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
if (lopt(arg, ArgValDisallowed, "-help", origarg, &argc, &argv)
|
||||||
|
|| lopt(arg, ArgValDisallowed | ArgNamOneLetter, "-?",
|
||||||
|
origarg, &argc, &argv))
|
||||||
|
opt_usage(*hackdir_p); /* doesn't return */
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
oldargc = argc;
|
||||||
|
if (!strcmp(arg, "-no-nethackrc")) /* no abbreviation allowed */
|
||||||
|
arg = nhStr("/dev/null");
|
||||||
|
else
|
||||||
|
arg = lopt(arg, (ArgValRequired | ArgErrComplain),
|
||||||
|
"-nethackrc", origarg, &argc, &argv);
|
||||||
|
if (arg) {
|
||||||
|
gc.cmdline_rcfile = dupstr(arg);
|
||||||
|
if (oldargc == argc)
|
||||||
|
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
||||||
|
else
|
||||||
|
consume_two_args(ndx, argc_p, argv_p), consumed = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) {
|
||||||
|
gd.deferred_showpaths = TRUE;
|
||||||
|
gd.deferred_showpaths_dir = *hackdir_p;
|
||||||
|
config_error_done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* check for "-s" request to show scores */
|
||||||
|
if (lopt(arg,
|
||||||
|
((ArgValDisallowed | ArgErrComplain)
|
||||||
|
/* only accept one-letter if there is just one
|
||||||
|
dash; reject "--s" because prscore() via
|
||||||
|
scores_only() doesn't understand it */
|
||||||
|
| ((origarg[1] != '-') ? ArgNamOneLetter : 0)),
|
||||||
|
/* [ought to omit val-disallowed and accept
|
||||||
|
--scores=foo since -s foo and -sfoo are
|
||||||
|
allowed, but -s form can take more than one
|
||||||
|
space-separated argument and --scores=foo
|
||||||
|
isn't suited for that] */
|
||||||
|
"-scores", origarg, &argc, &argv)) {
|
||||||
|
/* at this point, argv[0] contains "-scores" or a leading
|
||||||
|
substring of it; prscore() (via scores_only()) expects
|
||||||
|
that to be in argv[1] so we adjust the pointer to make
|
||||||
|
that be the case; if there are any non-early args waiting
|
||||||
|
to be passed along to process_options(), the resulting
|
||||||
|
argv[0] will be one of those rather than the program
|
||||||
|
name but prscore() doesn't care */
|
||||||
|
scores_only(argc + 1, argv - 1, *hackdir_p);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
#if defined(UNIX)
|
||||||
|
if (lopt(arg, ArgValDisallowed, "-usage", origarg, &argc, &argv))
|
||||||
|
opt_usage(*hackdir_p);
|
||||||
|
#elif defined(WIN32) || defined(MSDOS) || defined(AMIGA)
|
||||||
|
if (arg[2]) {
|
||||||
|
(void) strncpy(svp.plname, arg + 2, sizeof(svp.plname) - 1);
|
||||||
|
} else if (ndx + 1 < *argc_p) {
|
||||||
|
const char *nextarg = (*argv_p)[ndx + 1];
|
||||||
|
|
||||||
|
if (nextarg[0] != '-') {
|
||||||
|
(void) strncpy(svp.plname, nextarg, sizeof(svp.plname) - 1);
|
||||||
|
} else {
|
||||||
|
raw_print("Player name expected after -u\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
if (argcheck(argc, argv, ARG_VERSION) == 2) {
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'w': /* windowtype: "-wfoo" or "-w[indowtype]=foo"
|
||||||
|
* or "-w[indowtype]:foo" or "-w[indowtype] foo" */
|
||||||
|
arg =
|
||||||
|
lopt(arg, (ArgValRequired | ArgNamOneLetter | ArgErrComplain),
|
||||||
|
"-windowtype", origarg, &argc, &argv);
|
||||||
|
if (gc.cmdline_windowsys)
|
||||||
|
free((genericptr_t) gc.cmdline_windowsys);
|
||||||
|
gc.cmdline_windowsys = arg ? dupstr(arg) : NULL;
|
||||||
|
break;
|
||||||
|
#if !defined(UNIX) && !defined(VMS)
|
||||||
|
case 'D':
|
||||||
|
wizard = TRUE, discover = FALSE;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
discover = TRUE, wizard = FALSE;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* empty or "N errors on command line" */
|
||||||
|
config_error_done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* for command-line options that perform some immediate action and then
|
||||||
|
terminate the program without starting play, like 'nethack --version'
|
||||||
|
or 'nethack -s Zelda'; do some cleanup before that termination */
|
||||||
|
ATTRNORETURN staticfn void
|
||||||
|
opt_terminate(void)
|
||||||
|
{
|
||||||
|
program_state.early_options = 0;
|
||||||
|
config_error_done(); /* free memory allocated by config_error_init() */
|
||||||
|
|
||||||
|
nh_terminate(EXIT_SUCCESS);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
ATTRNORETURN staticfn void
|
||||||
|
opt_usage(const char *hackdir)
|
||||||
|
{
|
||||||
|
#ifdef CHDIR
|
||||||
|
chdirx(hackdir, TRUE);
|
||||||
|
#else
|
||||||
|
nhUse(hackdir);
|
||||||
|
#endif
|
||||||
|
dlb_init();
|
||||||
|
|
||||||
|
genl_display_file(USAGEHELP, TRUE);
|
||||||
|
opt_terminate();
|
||||||
|
}
|
||||||
|
/* show the sysconf file name, playground directory, run-time configuration
|
||||||
|
file name, dumplog file name if applicable, and some other things */
|
||||||
|
ATTRNORETURN void
|
||||||
|
after_opt_showpaths(const char *dir)
|
||||||
|
{
|
||||||
|
#ifdef CHDIR
|
||||||
|
chdirx(dir, FALSE);
|
||||||
|
#else
|
||||||
|
nhUse(dir);
|
||||||
|
#endif
|
||||||
|
opt_terminate();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle "-s <score options> [character-names]" to show all the entries
|
||||||
|
in the high scores file ('record') belonging to particular characters;
|
||||||
|
nethack will end after doing so without starting play */
|
||||||
|
ATTRNORETURN staticfn void
|
||||||
|
scores_only(int argc, char **argv, const char *dir)
|
||||||
|
{
|
||||||
|
/* do this now rather than waiting for final termination, in case there
|
||||||
|
is an error summary coming */
|
||||||
|
config_error_done();
|
||||||
|
|
||||||
|
#ifdef CHDIR
|
||||||
|
chdirx(dir, FALSE);
|
||||||
|
#else
|
||||||
|
nhUse(dir);
|
||||||
|
#endif
|
||||||
|
#ifdef SYSCF
|
||||||
|
iflags.initoptions_noterminate = TRUE;
|
||||||
|
initoptions(); /* sysconf options affect whether panictrace is enabled */
|
||||||
|
iflags.initoptions_noterminate = FALSE;
|
||||||
|
#endif
|
||||||
|
#ifdef PANICTRACE
|
||||||
|
ARGV0 = gh.hname; /* save for possible stack trace */
|
||||||
|
#ifndef NO_SIGNAL
|
||||||
|
panictrace_setsignals(TRUE);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef UNIX
|
||||||
|
(void) whoami(); /* set up default plname[] */
|
||||||
|
#endif
|
||||||
|
prscore(argc, argv);
|
||||||
|
|
||||||
|
nh_terminate(EXIT_SUCCESS); /* bypass opt_terminate() */
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns:
|
* Returns:
|
||||||
|
|||||||
+1
-1
@@ -671,7 +671,7 @@ nhusage(void)
|
|||||||
|
|
||||||
#ifdef CHDIR
|
#ifdef CHDIR
|
||||||
void
|
void
|
||||||
chdirx(char *dir, boolean wr)
|
chdirx(const char *dir, boolean wr)
|
||||||
{
|
{
|
||||||
#ifdef AMIGA
|
#ifdef AMIGA
|
||||||
static char thisdir[] = "";
|
static char thisdir[] = "";
|
||||||
|
|||||||
+7
-362
@@ -26,17 +26,11 @@ extern struct passwd *getpwuid(int);
|
|||||||
#endif
|
#endif
|
||||||
extern struct passwd *getpwnam(const char *);
|
extern struct passwd *getpwnam(const char *);
|
||||||
#ifdef CHDIR
|
#ifdef CHDIR
|
||||||
static void chdirx(const char *, boolean);
|
void chdirx(const char *, boolean);
|
||||||
#endif /* CHDIR */
|
#endif /* CHDIR */
|
||||||
static boolean whoami(void);
|
boolean whoami(void);
|
||||||
static char *lopt(char *, int, const char *, const char *, int *, char ***);
|
|
||||||
static void process_options(int, char **);
|
static void process_options(int, char **);
|
||||||
static void consume_arg(int, int *, char ***);
|
|
||||||
static void consume_two_args(int, int *, char ***);
|
|
||||||
static void early_options(int *, char ***, char **);
|
|
||||||
ATTRNORETURN static void opt_terminate(void) NORETURN;
|
|
||||||
ATTRNORETURN static void opt_usage(const char *) NORETURN;
|
|
||||||
ATTRNORETURN static void scores_only(int, char **, const char *) NORETURN;
|
|
||||||
#ifdef SND_LIB_INTEGRATED
|
#ifdef SND_LIB_INTEGRATED
|
||||||
uint32_t soundlibchoice = soundlib_nosound;
|
uint32_t soundlibchoice = soundlib_nosound;
|
||||||
#endif
|
#endif
|
||||||
@@ -128,12 +122,14 @@ main(int argc, char *argv[])
|
|||||||
if (!dir)
|
if (!dir)
|
||||||
dir = nh_getenv("HACKDIR");
|
dir = nh_getenv("HACKDIR");
|
||||||
#endif /* CHDIR */
|
#endif /* CHDIR */
|
||||||
|
program_state.early_options = 1;
|
||||||
#ifdef ENHANCED_SYMBOLS
|
#ifdef ENHANCED_SYMBOLS
|
||||||
if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2)
|
if (argcheck(argc, argv, ARG_DUMPGLYPHIDS) == 2)
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
/* handle -dalthackdir, -s <score stuff>, --version, --showpaths */
|
/* handle -dalthackdir, -s <score stuff>, --version, --showpaths */
|
||||||
early_options(&argc, &argv, &dir);
|
early_options(&argc, &argv, &dir);
|
||||||
|
program_state.early_options = 0;
|
||||||
#ifdef CHDIR
|
#ifdef CHDIR
|
||||||
/*
|
/*
|
||||||
* Change directories before we initialize the window system so
|
* Change directories before we initialize the window system so
|
||||||
@@ -325,93 +321,6 @@ main(int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char ArgVal_novalue[] = "[nothing]"; /* note: not 'const' */
|
|
||||||
|
|
||||||
enum cmdlinearg {
|
|
||||||
ArgValRequired = 0, ArgValOptional = 1,
|
|
||||||
ArgValDisallowed = 2, ArgVal_mask = (1 | 2),
|
|
||||||
ArgNamOneLetter = 4, ArgNam_mask = 4,
|
|
||||||
ArgErrSilent = 0, ArgErrComplain = 8, ArgErr_mask = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
/* approximate 'getopt_long()' for one option; all the comments refer to
|
|
||||||
"-windowtype" but the code isn't specific to that */
|
|
||||||
static char *
|
|
||||||
lopt(
|
|
||||||
char *arg, /* command line token; beginning matches 'optname' */
|
|
||||||
int lflags, /* cmdlinearg | errorhandling */
|
|
||||||
const char *optname, /* option's name; "-windowtype" in examples below */
|
|
||||||
const char *origarg, /* 'arg' might have had a dash prefix removed */
|
|
||||||
int *argc_p, /* argc that can have changes passed to caller */
|
|
||||||
char ***argv_p) /* argv[] ditto */
|
|
||||||
{
|
|
||||||
int argc = *argc_p;
|
|
||||||
char **argv = *argv_p;
|
|
||||||
char *p, *nextarg = (argc > 1 && argv[1][0] != '-') ? argv[1] : 0;
|
|
||||||
int l, opttype = (lflags & ArgVal_mask);
|
|
||||||
boolean oneletterok = ((lflags & ArgNam_mask) == ArgNamOneLetter),
|
|
||||||
complain = ((lflags & ArgErr_mask) == ArgErrComplain);
|
|
||||||
|
|
||||||
/* first letter must match */
|
|
||||||
if (arg[1] != optname[1]) {
|
|
||||||
loptbail:
|
|
||||||
if (complain)
|
|
||||||
config_error_add("Unknown option: %.60s", origarg);
|
|
||||||
return (char *) 0;
|
|
||||||
loptnotallowed:
|
|
||||||
if (complain)
|
|
||||||
config_error_add("Value not allowed: %.60s", origarg);
|
|
||||||
return (char *) 0;
|
|
||||||
loptrequired:
|
|
||||||
if (complain)
|
|
||||||
config_error_add("Missing required value: %.60s", origarg);
|
|
||||||
return (char *) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((p = strchr(arg, '=')) == 0)
|
|
||||||
p = strchr(arg, ':');
|
|
||||||
if (p && opttype == ArgValDisallowed)
|
|
||||||
goto loptnotallowed;
|
|
||||||
|
|
||||||
l = (int) (p ? (long) (p - arg) : (long) strlen(arg));
|
|
||||||
if ((l > 2 || oneletterok) && !strncmp(arg, optname, l)) {
|
|
||||||
/* "-windowtype[=foo]" */
|
|
||||||
if (p)
|
|
||||||
++p; /* past '=' or ':' */
|
|
||||||
else if (opttype == ArgValRequired)
|
|
||||||
p = eos(arg); /* we have "-w[indowtype]" w/o "=foo"
|
|
||||||
* so we'll take foo from next element */
|
|
||||||
else
|
|
||||||
return ArgVal_novalue;
|
|
||||||
} else if (oneletterok) {
|
|
||||||
/* "-w..." but not "-w[indowtype[=foo]]" */
|
|
||||||
if (!p) {
|
|
||||||
p = &arg[2]; /* past 'w' of "-wfoo" */
|
|
||||||
#if 0 /* -x:value could work but is not supported (callers don't expect it) */
|
|
||||||
} else if (p == arg + 2) {
|
|
||||||
++p; /* past ':' of "-w:foo" */
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* "-w...=foo" but not "-w[indowtype]=foo" */
|
|
||||||
goto loptbail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto loptbail;
|
|
||||||
}
|
|
||||||
if (!p || !*p) {
|
|
||||||
/* "-w[indowtype]" w/o '='/':' if there is a next element, use
|
|
||||||
it for "foo"; if not, supply a non-Null bogus value */
|
|
||||||
if (nextarg && (opttype == ArgValRequired
|
|
||||||
|| opttype == ArgValOptional))
|
|
||||||
p = nextarg, --(*argc_p), ++(*argv_p);
|
|
||||||
else if (opttype == ArgValRequired)
|
|
||||||
goto loptrequired;
|
|
||||||
else
|
|
||||||
p = ArgVal_novalue; /* there is no next element */
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* caveat: argv elements might be arbitrarily long */
|
/* caveat: argv elements might be arbitrarily long */
|
||||||
static void
|
static void
|
||||||
process_options(int argc, char *argv[])
|
process_options(int argc, char *argv[])
|
||||||
@@ -573,272 +482,8 @@ process_options(int argc, char *argv[])
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* move argv[ndx] to end of argv[] array, then reduce argc to hide it;
|
|
||||||
prevents process_options() from encountering it after early_options()
|
|
||||||
has processed it; elements get reordered but all remain intact */
|
|
||||||
static void
|
|
||||||
consume_arg(int ndx, int *ac_p, char ***av_p)
|
|
||||||
{
|
|
||||||
char *gone, **av = *av_p;
|
|
||||||
int i, ac = *ac_p;
|
|
||||||
|
|
||||||
/* "-one -two -three -four" -> "-two -three -four -one" */
|
|
||||||
if (ac > 2) {
|
|
||||||
gone = av[ndx];
|
|
||||||
for (i = ndx + 1; i < ac; ++i)
|
|
||||||
av[i - 1] = av[i];
|
|
||||||
av[ac - 1] = gone;
|
|
||||||
}
|
|
||||||
--(*ac_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* consume two tokens for '-argname value' w/o '=' or ':' */
|
|
||||||
static void
|
|
||||||
consume_two_args(int ndx, int *ac_p, char ***av_p)
|
|
||||||
{
|
|
||||||
/* when consuming "-two arg" from "-two arg -three -four",
|
|
||||||
the *ac_p manipulation results in "-three -four -two arg"
|
|
||||||
rather than the "-three -four arg -two" that would happen
|
|
||||||
with just two ordinary consume_arg() calls */
|
|
||||||
consume_arg(ndx, ac_p, av_p);
|
|
||||||
++(*ac_p); /* bring the final slot back into view */
|
|
||||||
consume_arg(ndx, ac_p, av_p);
|
|
||||||
--(*ac_p); /* take away restored slot */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* process some command line arguments before loading options */
|
|
||||||
static void
|
|
||||||
early_options(int *argc_p, char ***argv_p, char **hackdir_p)
|
|
||||||
{
|
|
||||||
char **argv, *arg, *origarg;
|
|
||||||
int argc, oldargc, ndx = 0, consumed = 0;
|
|
||||||
|
|
||||||
config_error_init(FALSE, "command line", FALSE);
|
|
||||||
|
|
||||||
/* treat "nethack ?" as a request for usage info; due to shell
|
|
||||||
processing, player likely has to use "nethack \?" or "nethack '?'"
|
|
||||||
[won't work if used as "nethack -dpath ?" or "nethack -d path ?"] */
|
|
||||||
if (*argc_p > 1 && !strcmp((*argv_p)[1], "?"))
|
|
||||||
opt_usage(*hackdir_p); /* doesn't return */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Both *argc_p and *argv_p account for the program name as (*argv_p)[0];
|
|
||||||
* local argc and argv implicitly discard that (by starting 'ndx' at 1).
|
|
||||||
* argcheck() doesn't mind, prscore() (via scores_only()) does (for the
|
|
||||||
* number of args it gets passed, not for the value of argv[0]).
|
|
||||||
*/
|
|
||||||
for (ndx = 1; ndx < *argc_p; ndx += (consumed ? 0 : 1)) {
|
|
||||||
consumed = 0;
|
|
||||||
argc = *argc_p - ndx;
|
|
||||||
argv = *argv_p + ndx;
|
|
||||||
|
|
||||||
arg = origarg = argv[0];
|
|
||||||
/* skip any args intended for deferred options */
|
|
||||||
if (*arg != '-')
|
|
||||||
continue;
|
|
||||||
/* allow second dash if arg name is longer than one character */
|
|
||||||
if (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0'
|
|
||||||
&& (arg[3] != '\0' && arg[3] != '=' && arg[3] != ':'))
|
|
||||||
++arg;
|
|
||||||
|
|
||||||
switch (arg[1]) { /* char after leading dash */
|
|
||||||
case 'b':
|
|
||||||
#ifdef CRASHREPORT
|
|
||||||
// --bidshow
|
|
||||||
if (argcheck(argc, argv, ARG_BIDSHOW) == 2){
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
|
|
||||||
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
|
||||||
#ifndef NODUMPENUMS
|
|
||||||
} else if (argcheck(argc, argv, ARG_DUMPENUMS) == 2) {
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
#endif
|
|
||||||
} else if (argcheck(argc, argv, ARG_DUMPMONGEN) == 2) {
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
} else if (argcheck(argc, argv, ARG_DUMPWEIGHTS) == 2) {
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
} else {
|
|
||||||
#ifdef CHDIR
|
#ifdef CHDIR
|
||||||
oldargc = argc;
|
void
|
||||||
arg = lopt(arg,
|
|
||||||
(ArgValRequired | ArgNamOneLetter | ArgErrSilent),
|
|
||||||
"-directory", origarg, &argc, &argv);
|
|
||||||
if (!arg)
|
|
||||||
error("Flag -d must be followed by a directory name.");
|
|
||||||
if (*arg != 'e') { /* avoid matching -decgraphics or -debug */
|
|
||||||
*hackdir_p = arg;
|
|
||||||
if (oldargc == argc)
|
|
||||||
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
|
||||||
else
|
|
||||||
consume_two_args(ndx, argc_p, argv_p), consumed = 2;
|
|
||||||
}
|
|
||||||
#endif /* CHDIR */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
if (lopt(arg, ArgValDisallowed, "-help", origarg, &argc, &argv)
|
|
||||||
|| lopt(arg, ArgValDisallowed | ArgNamOneLetter, "-?",
|
|
||||||
origarg, &argc, &argv))
|
|
||||||
opt_usage(*hackdir_p); /* doesn't return */
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
oldargc = argc;
|
|
||||||
if (!strcmp(arg, "-no-nethackrc")) /* no abbreviation allowed */
|
|
||||||
arg = nhStr("/dev/null");
|
|
||||||
else
|
|
||||||
arg = lopt(arg, (ArgValRequired | ArgErrComplain),
|
|
||||||
"-nethackrc", origarg, &argc, &argv);
|
|
||||||
if (arg) {
|
|
||||||
gc.cmdline_rcfile = dupstr(arg);
|
|
||||||
if (oldargc == argc)
|
|
||||||
consume_arg(ndx, argc_p, argv_p), consumed = 1;
|
|
||||||
else
|
|
||||||
consume_two_args(ndx, argc_p, argv_p), consumed = 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) {
|
|
||||||
gd.deferred_showpaths = TRUE;
|
|
||||||
gd.deferred_showpaths_dir = *hackdir_p;
|
|
||||||
config_error_done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* check for "-s" request to show scores */
|
|
||||||
if (lopt(arg, ((ArgValDisallowed | ArgErrComplain)
|
|
||||||
/* only accept one-letter if there is just one
|
|
||||||
dash; reject "--s" because prscore() via
|
|
||||||
scores_only() doesn't understand it */
|
|
||||||
| ((origarg[1] != '-') ? ArgNamOneLetter : 0)),
|
|
||||||
/* [ought to omit val-disallowed and accept
|
|
||||||
--scores=foo since -s foo and -sfoo are
|
|
||||||
allowed, but -s form can take more than one
|
|
||||||
space-separated argument and --scores=foo
|
|
||||||
isn't suited for that] */
|
|
||||||
"-scores", origarg, &argc, &argv)) {
|
|
||||||
/* at this point, argv[0] contains "-scores" or a leading
|
|
||||||
substring of it; prscore() (via scores_only()) expects
|
|
||||||
that to be in argv[1] so we adjust the pointer to make
|
|
||||||
that be the case; if there are any non-early args waiting
|
|
||||||
to be passed along to process_options(), the resulting
|
|
||||||
argv[0] will be one of those rather than the program
|
|
||||||
name but prscore() doesn't care */
|
|
||||||
scores_only(argc + 1, argv - 1, *hackdir_p);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
if (lopt(arg, ArgValDisallowed, "-usage", origarg, &argc, &argv))
|
|
||||||
opt_usage(*hackdir_p);
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
if (argcheck(argc, argv, ARG_VERSION) == 2) {
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'w': /* windowtype: "-wfoo" or "-w[indowtype]=foo"
|
|
||||||
* or "-w[indowtype]:foo" or "-w[indowtype] foo" */
|
|
||||||
arg = lopt(arg,
|
|
||||||
(ArgValRequired | ArgNamOneLetter | ArgErrComplain),
|
|
||||||
"-windowtype", origarg, &argc, &argv);
|
|
||||||
if (gc.cmdline_windowsys)
|
|
||||||
free((genericptr_t) gc.cmdline_windowsys);
|
|
||||||
gc.cmdline_windowsys = arg ? dupstr(arg) : NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* empty or "N errors on command line" */
|
|
||||||
config_error_done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for command-line options that perform some immediate action and then
|
|
||||||
terminate the program without starting play, like 'nethack --version'
|
|
||||||
or 'nethack -s Zelda'; do some cleanup before that termination */
|
|
||||||
ATTRNORETURN static void
|
|
||||||
opt_terminate(void)
|
|
||||||
{
|
|
||||||
config_error_done(); /* free memory allocated by config_error_init() */
|
|
||||||
|
|
||||||
nh_terminate(EXIT_SUCCESS);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
ATTRNORETURN static void
|
|
||||||
opt_usage(const char *hackdir)
|
|
||||||
{
|
|
||||||
#ifdef CHDIR
|
|
||||||
chdirx(hackdir, TRUE);
|
|
||||||
#else
|
|
||||||
nhUse(hackdir);
|
|
||||||
#endif
|
|
||||||
dlb_init();
|
|
||||||
|
|
||||||
genl_display_file(USAGEHELP, TRUE);
|
|
||||||
opt_terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* show the sysconf file name, playground directory, run-time configuration
|
|
||||||
file name, dumplog file name if applicable, and some other things */
|
|
||||||
ATTRNORETURN void
|
|
||||||
after_opt_showpaths(const char *dir)
|
|
||||||
{
|
|
||||||
#ifdef CHDIR
|
|
||||||
chdirx(dir, FALSE);
|
|
||||||
#else
|
|
||||||
nhUse(dir);
|
|
||||||
#endif
|
|
||||||
opt_terminate();
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* handle "-s <score options> [character-names]" to show all the entries
|
|
||||||
in the high scores file ('record') belonging to particular characters;
|
|
||||||
nethack will end after doing so without starting play */
|
|
||||||
ATTRNORETURN static void
|
|
||||||
scores_only(int argc, char **argv, const char *dir)
|
|
||||||
{
|
|
||||||
/* do this now rather than waiting for final termination, in case there
|
|
||||||
is an error summary coming */
|
|
||||||
config_error_done();
|
|
||||||
|
|
||||||
#ifdef CHDIR
|
|
||||||
chdirx(dir, FALSE);
|
|
||||||
#else
|
|
||||||
nhUse(dir);
|
|
||||||
#endif
|
|
||||||
#ifdef SYSCF
|
|
||||||
iflags.initoptions_noterminate = TRUE;
|
|
||||||
initoptions(); /* sysconf options affect whether panictrace is enabled */
|
|
||||||
iflags.initoptions_noterminate = FALSE;
|
|
||||||
#endif
|
|
||||||
#ifdef PANICTRACE
|
|
||||||
ARGV0 = gh.hname; /* save for possible stack trace */
|
|
||||||
#ifndef NO_SIGNAL
|
|
||||||
panictrace_setsignals(TRUE);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
(void) whoami(); /* set up default plname[] */
|
|
||||||
|
|
||||||
prscore(argc, argv);
|
|
||||||
|
|
||||||
nh_terminate(EXIT_SUCCESS); /* bypass opt_terminate() */
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CHDIR
|
|
||||||
static void
|
|
||||||
chdirx(const char *dir, boolean wr)
|
chdirx(const char *dir, boolean wr)
|
||||||
{
|
{
|
||||||
if (dir /* User specified directory? */
|
if (dir /* User specified directory? */
|
||||||
@@ -905,7 +550,7 @@ chdirx(const char *dir, boolean wr)
|
|||||||
#endif /* CHDIR */
|
#endif /* CHDIR */
|
||||||
|
|
||||||
/* returns True iff we set plname[] to username which contains a hyphen */
|
/* returns True iff we set plname[] to username which contains a hyphen */
|
||||||
static boolean
|
boolean
|
||||||
whoami(void)
|
whoami(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|||||||
+12
-12
@@ -2590,19 +2590,19 @@ void nethack_enter_consoletty(void)
|
|||||||
|
|
||||||
|
|
||||||
/* clear the entire console buffer */
|
/* clear the entire console buffer */
|
||||||
int size = console.orig_csbi.dwSize.X * console.orig_csbi.dwSize.Y;
|
//int size = console.orig_csbi.dwSize.X * console.orig_csbi.dwSize.Y;
|
||||||
DWORD unused;
|
//DWORD unused;
|
||||||
set_console_cursor(0, 0);
|
//set_console_cursor(0, 0);
|
||||||
FillConsoleOutputAttribute(
|
// FillConsoleOutputAttribute(
|
||||||
console.hConOut, CONSOLE_CLEAR_ATTRIBUTE,
|
// console.hConOut, CONSOLE_CLEAR_ATTRIBUTE,
|
||||||
size, console.cursor, &unused);
|
// size, console.cursor, &unused);
|
||||||
|
|
||||||
FillConsoleOutputCharacter(
|
// FillConsoleOutputCharacter(
|
||||||
console.hConOut, CONSOLE_CLEAR_CHARACTER,
|
// console.hConOut, CONSOLE_CLEAR_CHARACTER,
|
||||||
size, console.cursor, &unused);
|
// size, console.cursor, &unused);
|
||||||
|
|
||||||
set_console_cursor(1, 0);
|
//set_console_cursor(1, 0);
|
||||||
SetConsoleCursorPosition(console.hConOut, console.cursor);
|
//SetConsoleCursorPosition(console.hConOut, console.cursor);
|
||||||
|
|
||||||
/* At this point early_raw_print will work */
|
/* At this point early_raw_print will work */
|
||||||
|
|
||||||
@@ -2757,7 +2757,7 @@ VA_DECL(const char *, fmt)
|
|||||||
VA_START(fmt);
|
VA_START(fmt);
|
||||||
VA_INIT(fmt, const char *);
|
VA_INIT(fmt, const char *);
|
||||||
(void) vsnprintf(buf, sizeof buf, fmt, VA_ARGS);
|
(void) vsnprintf(buf, sizeof buf, fmt, VA_ARGS);
|
||||||
if (redirect_stdout)
|
if (redirect_stdout || program_state.early_options)
|
||||||
fprintf(stdout, "%s", buf);
|
fprintf(stdout, "%s", buf);
|
||||||
else {
|
else {
|
||||||
#ifdef TTY_GRAPHICS
|
#ifdef TTY_GRAPHICS
|
||||||
|
|||||||
+64
-21
@@ -19,7 +19,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void nhusage(void);
|
static void nhusage(void);
|
||||||
static void early_options(int argc, char **argv);
|
|
||||||
char *exename(void);
|
char *exename(void);
|
||||||
boolean fakeconsole(void);
|
boolean fakeconsole(void);
|
||||||
void freefakeconsole(void);
|
void freefakeconsole(void);
|
||||||
@@ -157,6 +156,7 @@ MAIN(int argc, char *argv[])
|
|||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
int bpp;
|
int bpp;
|
||||||
|
char *dir = NULL;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||||
@@ -167,12 +167,10 @@ MAIN(int argc, char *argv[])
|
|||||||
* Get a set of valid safe windowport function
|
* Get a set of valid safe windowport function
|
||||||
* pointers during early startup initialization.
|
* pointers during early startup initialization.
|
||||||
*/
|
*/
|
||||||
safe_routines();
|
// safe_routines();
|
||||||
#endif /* WIN32CON */
|
#endif /* WIN32CON */
|
||||||
|
|
||||||
#ifndef MSWIN_GRAPHICS
|
|
||||||
early_init(argc, argv); /* already in WinMain for MSWIN_GRAPHICS */
|
|
||||||
#endif
|
|
||||||
/* setting iflags.colorcount has to be after early_init()
|
/* setting iflags.colorcount has to be after early_init()
|
||||||
* because it zeros out all of iflags */
|
* because it zeros out all of iflags */
|
||||||
hwnd = GetDesktopWindow();
|
hwnd = GetDesktopWindow();
|
||||||
@@ -207,6 +205,35 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
gh.hname = "NetHack"; /* used for syntax messages */
|
gh.hname = "NetHack"; /* used for syntax messages */
|
||||||
|
#ifndef MSWIN_GRAPHICS
|
||||||
|
early_init(argc, argv); /* already in WinMain for MSWIN_GRAPHICS */
|
||||||
|
#endif
|
||||||
|
set_default_prefix_locations(argv[0]); /* must be re-done after initoptions_init()
|
||||||
|
* which clears out gp.fqn_prefix[] */
|
||||||
|
copy_sysconf_content();
|
||||||
|
copy_symbols_content();
|
||||||
|
/* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't
|
||||||
|
allow it to be changed from here on out. */
|
||||||
|
fqn_prefix_locked[TROUBLEPREFIX] = TRUE;
|
||||||
|
copy_config_content();
|
||||||
|
|
||||||
|
// if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
|
||||||
|
// windowtype = gc.chosen_windowtype;
|
||||||
|
// windowtype = gc.chosen_windowtype;
|
||||||
|
|
||||||
|
#if !defined(MSWIN_GRAPHICS)
|
||||||
|
consoletty_open(1);
|
||||||
|
nethack_enter_consoletty();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!windowtype) {
|
||||||
|
#ifdef MSWIN_GRAPHICS
|
||||||
|
windowtype = "mswin";
|
||||||
|
#else
|
||||||
|
windowtype = "tty";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
choose_windows(windowtype); /* sets all the window port function pointers */
|
||||||
|
|
||||||
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
|
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
|
||||||
/* Save current directory and make sure it gets restored when
|
/* Save current directory and make sure it gets restored when
|
||||||
@@ -216,7 +243,14 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
|||||||
error("NetHack: current directory path too long");
|
error("NetHack: current directory path too long");
|
||||||
#endif
|
#endif
|
||||||
initoptions_init(); // This allows OPTIONS in syscf on Windows.
|
initoptions_init(); // This allows OPTIONS in syscf on Windows.
|
||||||
set_default_prefix_locations(argv[0]);
|
set_default_prefix_locations(argv[0]); /* must be re-done after initoptions_init()
|
||||||
|
* which clears out gp.fqn_prefix[] */
|
||||||
|
iflags.windowtype_deferred = TRUE;
|
||||||
|
|
||||||
|
program_state.early_options = 1;
|
||||||
|
early_options(&argc, &argv, &dir);
|
||||||
|
program_state.early_options = 0;
|
||||||
|
initoptions();
|
||||||
|
|
||||||
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
|
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
|
||||||
chdir(gf.fqn_prefix[HACKPREFIX]);
|
chdir(gf.fqn_prefix[HACKPREFIX]);
|
||||||
@@ -226,18 +260,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
|||||||
getreturn_enabled = TRUE;
|
getreturn_enabled = TRUE;
|
||||||
|
|
||||||
check_recordfile((char *) 0);
|
check_recordfile((char *) 0);
|
||||||
iflags.windowtype_deferred = TRUE;
|
|
||||||
copy_sysconf_content();
|
|
||||||
copy_symbols_content();
|
|
||||||
early_options(argc, argv);
|
|
||||||
initoptions();
|
|
||||||
|
|
||||||
/* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't
|
|
||||||
allow it to be changed from here on out. */
|
|
||||||
fqn_prefix_locked[TROUBLEPREFIX] = TRUE;
|
|
||||||
|
|
||||||
copy_config_content();
|
|
||||||
|
|
||||||
/* did something earlier flag a need to exit without starting a game? */
|
/* did something earlier flag a need to exit without starting a game? */
|
||||||
if (windows_startup_state > 0) {
|
if (windows_startup_state > 0) {
|
||||||
raw_printf("Exiting.");
|
raw_printf("Exiting.");
|
||||||
@@ -287,10 +309,10 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
|||||||
Strcpy(default_window_sys, "curses");
|
Strcpy(default_window_sys, "curses");
|
||||||
#endif /* CURSES */
|
#endif /* CURSES */
|
||||||
#endif /* TTY */
|
#endif /* TTY */
|
||||||
if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
|
// if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
|
||||||
windowtype = gc.chosen_windowtype;
|
// windowtype = gc.chosen_windowtype;
|
||||||
}
|
}
|
||||||
choose_windows(windowtype);
|
// choose_windows(windowtype);
|
||||||
#if defined(SND_LIB_FMOD)
|
#if defined(SND_LIB_FMOD)
|
||||||
assign_soundlib(soundlib_fmod);
|
assign_soundlib(soundlib_fmod);
|
||||||
#elif defined(SND_LIB_WINDSOUND)
|
#elif defined(SND_LIB_WINDSOUND)
|
||||||
@@ -451,6 +473,7 @@ attempt_restore:
|
|||||||
|
|
||||||
RESTORE_WARNING_UNREACHABLE_CODE
|
RESTORE_WARNING_UNREACHABLE_CODE
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
early_options(int argc, char *argv[])
|
early_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -671,6 +694,7 @@ nhusage(void)
|
|||||||
(void) printf("%s\n", buf1);
|
(void) printf("%s\n", buf1);
|
||||||
#undef ADD_USAGE
|
#undef ADD_USAGE
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
/* copy file if destination does not exist */
|
/* copy file if destination does not exist */
|
||||||
void
|
void
|
||||||
@@ -1297,4 +1321,23 @@ other_self_recover_prompt(void)
|
|||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CHDIR
|
||||||
|
void
|
||||||
|
chdirx(const char *dir, boolean wr)
|
||||||
|
{
|
||||||
|
static char thisdir[] = ".";
|
||||||
|
|
||||||
|
if (dir && chdir(dir) < 0) {
|
||||||
|
error("Cannot chdir to %s.", dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* warn the player if we can't write the record file */
|
||||||
|
/* perhaps we should also test whether . is writable */
|
||||||
|
/* unfortunately the access system-call is worthless */
|
||||||
|
if (wr)
|
||||||
|
check_recordfile(dir ? dir : thisdir);
|
||||||
|
}
|
||||||
|
#endif /* CHDIR */
|
||||||
|
|
||||||
/*windmain.c*/
|
/*windmain.c*/
|
||||||
|
|||||||
Reference in New Issue
Block a user