7f28c94eda
The interpreter more or less passes all the tests in the z-machine test suite. It should build for every target except Archos (for which it is disabled). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24267 a1c6a512-1295-4272-9138-f99709370657
154 lines
4 KiB
C
154 lines
4 KiB
C
/* 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 */
|