diff -c -N frotz-2.32/Makefile frotz-2.32+sz/Makefile *** frotz-2.32/Makefile Fri Oct 17 22:11:10 1997 --- frotz-2.32+sz/Makefile Fri Nov 27 02:17:14 1998 *************** *** 33,38 **** --- 33,40 ---- # than curses.h. # # These defines add various cosmetic features to the interpreter: + # -DSTRICTZ: Do stricter error checking. Adapted from Andrew + # Plotkin's zip_zstrict_patch. # -DCOLOR_SUPPORT: If the terminal you're using has color support, frotz # will use the curses color routines...if your curses # library supports color. *************** *** 42,48 **** # to define it--it can't hurt anything--but you do # have that option. # ! #DEFS = -DUSE_GETOPT_H -DCOLOR_SUPPORT -DEMACS_EDITING DEFS = # This should point to the location of your curses or ncurses include file --- 44,50 ---- # to define it--it can't hurt anything--but you do # have that option. # ! #DEFS = -DUSE_GETOPT_H -DSTRICTZ -DCOLOR_SUPPORT -DEMACS_EDITING DEFS = # This should point to the location of your curses or ncurses include file *************** *** 62,70 **** # Nothing under this line should need to be changed. OBJECTS = buffer.o fastmem.o files.o hotkey.o input.o main.o math.o object.o \ ! process.o random.o redirect.o screen.o sound.o stream.o table.o \ ! text.o ux_init.o ux_input.o ux_pic.o ux_screen.o ux_sample.o \ ! ux_text.o variable.o CFLAGS = $(OPTS) $(DEFS) $(INCL) --- 64,72 ---- # Nothing under this line should need to be changed. OBJECTS = buffer.o fastmem.o files.o hotkey.o input.o main.o math.o object.o \ ! process.o random.o redirect.o screen.o sound.o stream.o strictz.o \ ! table.o text.o ux_init.o ux_input.o ux_pic.o ux_screen.o \ ! ux_sample.o ux_text.o variable.o CFLAGS = $(OPTS) $(DEFS) $(INCL) diff -c -N frotz-2.32/frotz.h frotz-2.32+sz/frotz.h *** frotz-2.32/frotz.h Fri Oct 3 22:04:52 1997 --- frotz-2.32+sz/frotz.h Fri Nov 27 01:24:38 1998 *************** *** 546,551 **** --- 546,597 ---- void z_window_size (void); void z_window_style (void); + #ifdef STRICTZ + + /* Definitions for STRICTZ functions and error codes. */ + + extern int strictz_report_mode; + + void init_strictz (void); + void report_strictz_error (int, const char *); + + /* Error codes */ + #define STRZERR_NO_ERROR (0) + #define STRZERR_JIN (1) + #define STRZERR_GET_CHILD (2) + #define STRZERR_GET_PARENT (3) + #define STRZERR_GET_SIBLING (4) + #define STRZERR_GET_PROP_ADDR (5) + #define STRZERR_GET_PROP (6) + #define STRZERR_PUT_PROP (7) + #define STRZERR_CLEAR_ATTR (8) + #define STRZERR_SET_ATTR (9) + #define STRZERR_TEST_ATTR (10) + #define STRZERR_MOVE_OBJECT (11) + #define STRZERR_MOVE_OBJECT_2 (12) + #define STRZERR_REMOVE_OBJECT (13) + #define STRZERR_GET_NEXT_PROP (14) + #define STRICTZ_NUM_ERRORS (15) + + /* There are four error reporting modes: never report errors; + report only the first time a given error type occurs; report + every time an error occurs; or treat all errors as fatal + errors, killing the interpreter. I strongly recommend + "report once" as the default. But you can compile in a + different default by changing the definition of + STRICTZ_DEFAULT_REPORT_MODE. In any case, the player can + specify a report mode on the command line by typing "-Z 0" + through "-Z 3". */ + + #define STRICTZ_REPORT_NEVER (0) + #define STRICTZ_REPORT_ONCE (1) + #define STRICTZ_REPORT_ALWAYS (2) + #define STRICTZ_REPORT_FATAL (3) + + #define STRICTZ_DEFAULT_REPORT_MODE STRICTZ_REPORT_ONCE + + #endif /* STRICTZ */ + /*** Various global functions ***/ zchar translate_from_zscii (zbyte); diff -c -N frotz-2.32/main.c frotz-2.32+sz/main.c *** frotz-2.32/main.c Wed Sep 10 15:07:58 1997 --- frotz-2.32+sz/main.c Fri Nov 27 01:26:34 1998 *************** *** 160,165 **** --- 160,169 ---- int cdecl main (int argc, char *argv[]) { + #ifdef STRICTZ + init_strictz (); + #endif + os_process_arguments (argc, argv); init_memory (); diff -c -N frotz-2.32/object.c frotz-2.32+sz/object.c *** frotz-2.32/object.c Thu Sep 18 14:44:44 1997 --- frotz-2.32+sz/object.c Fri Nov 27 01:54:25 1998 *************** *** 149,154 **** --- 149,162 ---- zword parent_addr; zword sibling_addr; + #ifdef STRICTZ + if (object == 0) { + report_strictz_error (STRZERR_REMOVE_OBJECT, + "@remove_object called with object 0"); + return; + } + #endif + obj_addr = object_address (object); if (h_version <= V3) { *************** *** 264,269 **** --- 272,285 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_CLEAR_ATTR, + "@clear_attr called with object 0"); + return; + } + #endif + /* Get attribute address */ obj_addr = object_address (zargs[0]) + zargs[1] / 8; *************** *** 299,304 **** --- 315,329 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_JIN, + "@jin called with object 0"); + branch (0 == zargs[1]); + return; + } + #endif + obj_addr = object_address (zargs[0]); if (h_version <= V3) { *************** *** 351,356 **** --- 376,391 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_CHILD, + "@get_child called with object 0"); + store (0); + branch (FALSE); + return; + } + #endif + obj_addr = object_address (zargs[0]); if (h_version <= V3) { *************** *** 399,404 **** --- 434,448 ---- zbyte value; zbyte mask; + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_NEXT_PROP, + "@get_next_prop called with object 0"); + store (0); + return; + } + #endif + /* Property id is in bottom five (six) bits */ mask = (h_version <= V3) ? 0x1f : 0x3f; *************** *** 450,455 **** --- 494,508 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_PARENT, + "@get_parent called with object 0"); + store (0); + return; + } + #endif + obj_addr = object_address (zargs[0]); if (h_version <= V3) { *************** *** 498,503 **** --- 551,565 ---- zbyte value; zbyte mask; + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_PROP, + "@get_prop called with object 0"); + store (0); + return; + } + #endif + /* Property id is in bottom five (six) bits */ mask = (h_version <= V3) ? 0x1f : 0x3f; *************** *** 557,562 **** --- 619,633 ---- zbyte value; zbyte mask; + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_PROP_ADDR, + "@get_prop_addr called with object 0"); + store (0); + return; + } + #endif + if (story_id == BEYOND_ZORK) if (zargs[0] > MAX_OBJECT) { store (0); return; } *************** *** 638,643 **** --- 709,724 ---- { zword obj_addr; + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_GET_SIBLING, + "@get_sibling called with object 0"); + store (0); + branch (FALSE); + return; + } + #endif + obj_addr = object_address (zargs[0]); if (h_version <= V3) { *************** *** 698,703 **** --- 779,798 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (obj1 == 0) { + report_strictz_error (STRZERR_MOVE_OBJECT, + "@move_object called moving object 0"); + return; + } + + if (obj2 == 0) { + report_strictz_error (STRZERR_MOVE_OBJECT_2, + "@move_object called moving into object 0"); + return; + } + #endif + /* Get addresses of both objects */ obj1_addr = object_address (obj1); *************** *** 752,757 **** --- 847,860 ---- zword value; zbyte mask; + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_PUT_PROP, + "@put_prop called with object 0"); + return; + } + #endif + /* Property id is in bottom five or six bits */ mask = (h_version <= V3) ? 0x1f : 0x3f; *************** *** 844,849 **** --- 947,960 ---- stream_mssg_off (); } + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_SET_ATTR, + "@set_attr called with object 0"); + return; + } + #endif + /* Get attribute address */ obj_addr = object_address (zargs[0]) + zargs[1] / 8; *************** *** 888,893 **** --- 999,1013 ---- print_num (zargs[1]); stream_mssg_off (); } + + #ifdef STRICTZ + if (zargs[0] == 0) { + report_strictz_error (STRZERR_TEST_ATTR, + "@test_attr called with object 0"); + branch (FALSE); + return; + } + #endif /* Get attribute address */ diff -c -N frotz-2.32/strictz.c frotz-2.32+sz/strictz.c *** frotz-2.32/strictz.c Thu Jan 1 01:00:00 1970 --- frotz-2.32+sz/strictz.c Fri Nov 27 01:39:36 1998 *************** *** 0 **** --- 1,86 ---- + /* + * strictz.c + * + * Strict Z error reporting functions + */ + + #include "frotz.h" + + #ifdef STRICTZ + + #include + + /* 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 strictz_report_mode; + static int strictz_error_count[STRICTZ_NUM_ERRORS]; + + /* + * report_strictz_error + * + * This handles Z-code error conditions which ought to be fatal errors, + * but which players might want to ignore for the sake of finishing the + * game. + * + * The error is provided as both a numeric code and a string. This allows + * us to print a warning the first time a particular error occurs, and + * ignore it thereafter. + * + * errnum : Numeric code for error (0 to STRICTZ_NUM_ERRORS-1) + * errstr : Text description of error + * + */ + + void init_strictz () + { + int i; + + /* Initialize the STRICTZ variables. */ + + strictz_report_mode = STRICTZ_DEFAULT_REPORT_MODE; + + for (i = 0; i < STRICTZ_NUM_ERRORS; i++) { + strictz_error_count[i] = 0; + } + } + + void report_strictz_error (int errnum, const char *errstr) + { + int wasfirst; + + if (errnum <= 0 || errnum >= STRICTZ_NUM_ERRORS) + return; + + if (strictz_report_mode == STRICTZ_REPORT_FATAL) { + flush_buffer (); + os_fatal (errstr); + return; + } + + wasfirst = (strictz_error_count[errnum] == 0); + strictz_error_count[errnum]++; + + if ((strictz_report_mode == STRICTZ_REPORT_ALWAYS) + || (strictz_report_mode == STRICTZ_REPORT_ONCE && wasfirst)) { + char buf[256]; + long pc; + + GET_PC (pc); + sprintf (buf, "Warning: %s (PC = %lx)", errstr, pc); + print_string (buf); + + if (strictz_report_mode == STRICTZ_REPORT_ONCE) { + print_string(" (will ignore further occurrences)"); + } else { + sprintf (buf, " (occurrence %d)", strictz_error_count[errnum]); + print_string(buf); + } + new_line (); + } + + } /* report_strictz_error */ + + #endif /* STRICTZ */ diff -c -N frotz-2.32/ux_init.c frotz-2.32+sz/ux_init.c *** frotz-2.32/ux_init.c Sat Oct 4 03:12:10 1997 --- frotz-2.32+sz/ux_init.c Fri Nov 27 01:56:17 1998 *************** *** 139,145 **** do { ! c = getopt(argc, argv, "aAb:c:df:h:il:oOpPr:s:S:tu:w:x"); switch(c) { case 'a': option_attribute_assignment = 1; break; --- 139,149 ---- do { ! c = getopt(argc, argv, "aAb:c:df:h:il:oOpPr:s:S:tu:w:x" ! #ifdef STRICTZ ! "Z:" ! #endif ! ); switch(c) { case 'a': option_attribute_assignment = 1; break; *************** *** 170,181 **** --- 174,200 ---- case 'u': option_undo_slots = atoi(optarg); break; case 'w': user_screen_width = atoi(optarg); break; case 'x': option_expand_abbreviations = 1; break; + #ifdef STRICTZ + case 'Z': strictz_report_mode = atoi(optarg); + if ((strictz_report_mode < STRICTZ_REPORT_NEVER) || + (strictz_report_mode > STRICTZ_REPORT_FATAL)) + strictz_report_mode = STRICTZ_DEFAULT_REPORT_MODE; + break; + #endif } } while (c != EOF); if (optind != argc - 1) { puts (INFORMATION); + #ifdef STRICTZ + printf (" -Z # stricter error checking (default = %d)\n" + "\t(%d: none; %d: report first error; %d: report all errors;\n" + "\t %d: exit after any error)\n", + STRICTZ_DEFAULT_REPORT_MODE, STRICTZ_REPORT_NEVER, + STRICTZ_REPORT_ONCE, STRICTZ_REPORT_ALWAYS, + STRICTZ_REPORT_FATAL); + #endif exit (1); }