--- /dev/null
+/*-
+ * Copyright 2010-2012 Chris Spiegel.
+ *
+ * This file is part of Bocfel.
+ *
+ * Bocfel is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version
+ * 2 or 3, as published by the Free Software Foundation.
+ *
+ * Bocfel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Bocfel. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "util.h"
+#include "screen.h"
+#include "unicode.h"
+#include "zterp.h"
+
+#ifdef ZTERP_GLK
+#include <glk.h>
+#include <libchimara/garglk.h>
+#endif
+
+#ifndef ZTERP_NO_SAFETY_CHECKS
+unsigned long zassert_pc;
+
+void assert_fail(const char *fmt, ...)
+{
+ va_list ap;
+ char str[1024];
+
+ va_start(ap, fmt);
+ vsnprintf(str, sizeof str, fmt, ap);
+ va_end(ap);
+
+ snprintf(str + strlen(str), sizeof str - strlen(str), " (pc = 0x%lx)", zassert_pc);
+
+ die("%s", str);
+}
+#endif
+
+void warning(const char *fmt, ...)
+{
+ va_list ap;
+ char str[1024];
+
+ va_start(ap, fmt);
+ vsnprintf(str, sizeof str, fmt, ap);
+ va_end(ap);
+
+ show_message("WARNING: %s", str);
+}
+
+void die(const char *fmt, ...)
+{
+ va_list ap;
+ char str[1024];
+
+ va_start(ap, fmt);
+ vsnprintf(str, sizeof str, fmt, ap);
+ va_end(ap);
+
+ show_message("fatal error: %s", str);
+
+#ifdef ZTERP_GLK
+#ifdef GARGLK
+ fprintf(stderr, "%s\n", str);
+#endif
+ glk_exit();
+#endif
+
+ exit(EXIT_FAILURE);
+}
+
+/* This is not POSIX compliant, but it gets the job done.
+ * It should not be called more than once.
+ */
+static int zoptind = 0;
+static const char *zoptarg;
+static int zgetopt(int argc, char **argv, const char *optstring)
+{
+ static const char *p = "";
+ const char *optp;
+ int c;
+
+ if(*p == 0)
+ {
+ /* No more arguments. */
+ if(++zoptind >= argc) return -1;
+
+ p = argv[zoptind];
+
+ /* No more options. */
+ if(p[0] != '-' || p[1] == 0) return -1;
+
+ /* Handle “--” */
+ if(*++p == '-')
+ {
+ zoptind++;
+ return -1;
+ }
+ }
+
+ c = *p++;
+
+ optp = strchr(optstring, c);
+ if(optp == NULL) return '?';
+
+ if(optp[1] == ':')
+ {
+ if(*p != 0) zoptarg = p;
+ else zoptarg = argv[++zoptind];
+
+ p = "";
+ if(zoptarg == NULL) return '?';
+ }
+
+ return c;
+}
+
+char *xstrdup(const char *s)
+{
+ size_t n;
+ char *r;
+
+ n = strlen(s) + 1;
+
+ r = malloc(n);
+ if(r != NULL) memcpy(r, s, n);
+
+ return r;
+}
+
+int process_arguments(int argc, char **argv)
+{
+ int c;
+
+ while( (c = zgetopt(argc, argv, "a:A:cCdDeE:fFgGiklLmn:N:rR:sS:tT:u:UvxXyz:Z:")) != -1 )
+ {
+ switch(c)
+ {
+ case 'a':
+ options.eval_stack_size = strtol(zoptarg, NULL, 10);
+ break;
+ case 'A':
+ options.call_stack_size = strtol(zoptarg, NULL, 10);
+ break;
+ case 'c':
+ options.disable_color = 1;
+ break;
+ case 'C':
+ options.disable_config = 1;
+ break;
+ case 'd':
+ options.disable_timed = 1;
+ break;
+ case 'D':
+ options.disable_sound = 1;
+ break;
+ case 'e':
+ options.enable_escape = 1;
+ break;
+ case 'E':
+ options.escape_string = xstrdup(zoptarg);
+ break;
+ case 'f':
+ options.disable_fixed = 1;
+ break;
+ case 'F':
+ options.assume_fixed = 1;
+ break;
+ case 'g':
+ options.disable_graphics_font = 1;
+ break;
+ case 'G':
+ options.enable_alt_graphics = 1;
+ break;
+ case 'i':
+ options.show_id = 1;
+ break;
+ case 'k':
+ options.disable_term_keys = 1;
+ break;
+ case 'l':
+ options.disable_utf8 = 1;
+ break;
+ case 'L':
+ options.force_utf8 = 1;
+ break;
+ case 'm':
+ options.disable_meta_commands = 1;
+ break;
+ case 'n':
+ options.int_number = strtol(zoptarg, NULL, 10);
+ break;
+ case 'N':
+ options.int_version = zoptarg[0];
+ break;
+ case 'r':
+ options.replay_on = 1;
+ break;
+ case 'R':
+ options.replay_name = xstrdup(zoptarg);
+ break;
+ case 's':
+ options.record_on = 1;
+ break;
+ case 'S':
+ options.record_name = xstrdup(zoptarg);
+ break;
+ case 't':
+ options.transcript_on = 1;
+ break;
+ case 'T':
+ options.transcript_name = xstrdup(zoptarg);
+ break;
+ case 'u':
+ options.max_saves = strtol(zoptarg, NULL, 10);
+ break;
+ case 'U':
+ options.disable_undo_compression = 1;
+ break;
+ case 'v':
+ options.show_version = 1;
+ break;
+ case 'x':
+ options.disable_abbreviations = 1;
+ break;
+ case 'X':
+ options.enable_censorship = 1;
+ break;
+ case 'y':
+ options.overwrite_transcript = 1;
+ break;
+ case 'z':
+ options.random_seed = strtol(zoptarg, NULL, 10);
+ break;
+ case 'Z':
+ options.random_device = xstrdup(zoptarg);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* Just ignore excess stories for now. */
+ if(zoptind < argc) game_file = argv[zoptind];
+
+ return 1;
+}