Added Nitfol and Frotz source code.
[projects/chimara/chimara.git] / interpreters / frotz / err.c
diff --git a/interpreters/frotz/err.c b/interpreters/frotz/err.c
new file mode 100644 (file)
index 0000000..61ca78c
--- /dev/null
@@ -0,0 +1,154 @@
+/* err.c - Runtime error reporting functions
+ *     Written by Jim Dunleavy <jim.dunleavy@erha.ie>
+ *
+ * This file is part of Frotz.
+ *
+ * Frotz is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Frotz 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "frotz.h"
+
+/* Define stuff for stricter Z-code error checking, for the generic
+   Unix/DOS/etc terminal-window interface. Feel free to change the way
+   player prefs are specified, or replace report_zstrict_error() 
+   completely if you want to change the way errors are reported. */
+
+/* int err_report_mode = ERR_DEFAULT_REPORT_MODE; */
+
+static int error_count[ERR_NUM_ERRORS];
+
+static char *err_messages[] = {
+    "Text buffer overflow",
+    "Store out of dynamic memory",
+    "Division by zero",
+    "Illegal object",
+    "Illegal attribute",
+    "No such property",
+    "Stack overflow",
+    "Call to illegal address",
+    "Call to non-routine",
+    "Stack underflow",
+    "Illegal opcode",
+    "Bad stack frame",
+    "Jump to illegal address",
+    "Can't save while in interrupt",
+    "Nesting stream #3 too deep",
+    "Illegal window",
+    "Illegal window property",
+    "Print at illegal address",
+    "@jin called with object 0",
+    "@get_child called with object 0",
+    "@get_parent called with object 0",
+    "@get_sibling called with object 0",
+    "@get_prop_addr called with object 0",
+    "@get_prop called with object 0",
+    "@put_prop called with object 0",
+    "@clear_attr called with object 0",
+    "@set_attr called with object 0",
+    "@test_attr called with object 0",
+    "@move_object called moving object 0",
+    "@move_object called moving into object 0",
+    "@remove_object called with object 0",
+    "@get_next_prop called with object 0"
+};
+
+static void print_long (unsigned long value, int base);
+
+/*
+ * init_err
+ *
+ * Initialise error reporting.
+ *
+ */
+
+void init_err (void)
+{
+    int i;
+
+    /* Initialize the counters. */
+    
+    for (i = 0; i < ERR_NUM_ERRORS; i++)
+        error_count[i] = 0;
+}
+
+/*
+ * runtime_error
+ *
+ * An error has occurred. Ignore it, pass it to os_fatal or report
+ * it according to err_report_mode.
+ *
+ * errnum : Numeric code for error (1 to ERR_NUM_ERRORS)
+ *
+ */
+
+void runtime_error (int errnum)
+{
+    int wasfirst;
+    
+    if (errnum <= 0 || errnum > ERR_NUM_ERRORS)
+       return;
+
+    if (f_setup.err_report_mode == ERR_REPORT_FATAL
+       || (!f_setup.ignore_errors && errnum <= ERR_MAX_FATAL)) {
+       flush_buffer ();
+       os_fatal (err_messages[errnum - 1]);
+       return;
+    }
+
+    wasfirst = (error_count[errnum - 1] == 0);
+    error_count[errnum - 1]++;
+    
+    if ((f_setup.err_report_mode == ERR_REPORT_ALWAYS)
+       || (f_setup.err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
+       long pc;
+
+       GET_PC (pc);
+       print_string ("Warning: ");
+       print_string (err_messages[errnum - 1]);
+       print_string (" (PC = ");
+       print_long (pc, 16);
+       print_char (')');
+        
+       if (f_setup.err_report_mode == ERR_REPORT_ONCE) {
+           print_string (" (will ignore further occurrences)");
+       } else {
+           print_string (" (occurence ");
+           print_long (error_count[errnum - 1], 10);
+           print_char (')');
+       }
+       new_line ();
+    }
+
+} /* report_error */
+
+/*
+ * print_long
+ *
+ * Print an unsigned 32bit number in decimal or hex.
+ *
+ */
+
+static void print_long (unsigned long value, int base)
+{
+    unsigned long i;
+    char c;
+
+    for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
+       if (value >= i || i == 1) {
+           c = (value / i) % base;
+           print_char (c + (c <= 9 ? '0' : 'a' - 10));
+       }
+
+}/* print_long */