aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/adrift/sxscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/adrift/sxscript.cpp')
-rw-r--r--engines/glk/adrift/sxscript.cpp714
1 files changed, 330 insertions, 384 deletions
diff --git a/engines/glk/adrift/sxscript.cpp b/engines/glk/adrift/sxscript.cpp
index 41be4c2b77..33c0501a3c 100644
--- a/engines/glk/adrift/sxscript.cpp
+++ b/engines/glk/adrift/sxscript.cpp
@@ -76,9 +76,8 @@ static sc_char *scr_game_output = NULL;
* Set error reporting for expectation errors detected in the script.
*/
void
-scr_set_verbose (sc_bool flag)
-{
- scr_is_verbose = flag;
+scr_set_verbose(sc_bool flag) {
+ scr_is_verbose = flag;
}
@@ -90,31 +89,27 @@ scr_set_verbose (sc_bool flag)
* is used by the serialization helper, so is not static.
*/
static void
-scr_test_message (const sc_char *format, const sc_char *string)
-{
- if (scr_is_verbose)
- {
- sx_trace ("--- ");
- sx_trace (format, string);
- sx_trace ("\n");
- }
+scr_test_message(const sc_char *format, const sc_char *string) {
+ if (scr_is_verbose) {
+ sx_trace("--- ");
+ sx_trace(format, string);
+ sx_trace("\n");
+ }
}
void
-scr_test_failed (const sc_char *format, const sc_char *string)
-{
- assert (format && string);
-
- if (scr_is_verbose)
- {
- if (scr_line_number > 0)
- sx_trace ("--- Near line %ld: ", scr_line_number);
- else
- sx_trace ("--- ");
- sx_trace (format, string);
- sx_trace ("\n");
- }
- scr_errors++;
+scr_test_failed(const sc_char *format, const sc_char *string) {
+ assert(format && string);
+
+ if (scr_is_verbose) {
+ if (scr_line_number > 0)
+ sx_trace("--- Near line %ld: ", scr_line_number);
+ else
+ sx_trace("--- ");
+ sx_trace(format, string);
+ sx_trace("\n");
+ }
+ scr_errors++;
}
@@ -129,47 +124,41 @@ scr_test_failed (const sc_char *format, const sc_char *string)
* Line classifiers, return TRUE if line has the given type.
*/
static sc_bool
-scr_is_line_type (const sc_char *line, sc_char type)
-{
- return line[0] == type;
+scr_is_line_type(const sc_char *line, sc_char type) {
+ return line[0] == type;
}
static sc_bool
-scr_is_line_comment_or_empty (const sc_char *line)
-{
- return scr_is_line_type (line, SCRIPT_COMMENT)
- || strspn (line, "\t\n\v\f\r ") == strlen (line);
+scr_is_line_comment_or_empty(const sc_char *line) {
+ return scr_is_line_type(line, SCRIPT_COMMENT)
+ || strspn(line, "\t\n\v\f\r ") == strlen(line);
}
static sc_bool
-scr_is_line_game_command (const sc_char *line)
-{
- return scr_is_line_type (line, GAME_COMMAND);
+scr_is_line_game_command(const sc_char *line) {
+ return scr_is_line_type(line, GAME_COMMAND);
}
static sc_bool
-scr_is_line_debug_command (const sc_char *line)
-{
- return scr_is_line_type (line, DEBUG_COMMAND);
+scr_is_line_debug_command(const sc_char *line) {
+ return scr_is_line_type(line, DEBUG_COMMAND);
}
static sc_bool
-scr_is_line_command (const sc_char *line)
-{
- return scr_is_line_game_command (line) || scr_is_line_debug_command (line);
+scr_is_line_command(const sc_char *line) {
+ return scr_is_line_game_command(line) || scr_is_line_debug_command(line);
}
static sc_bool
-scr_is_line_empty_debug_command (const sc_char *line)
-{
- return scr_is_line_type (line, DEBUG_COMMAND) && line[1] == NUL;
+scr_is_line_empty_debug_command(const sc_char *line) {
+ return scr_is_line_type(line, DEBUG_COMMAND) && line[1] == NUL;
}
/* Script location, a pair holding the file location and the line number. */
struct sx_scr_location_t {
- size_t position;
- sc_int line_number;
+ size_t position;
+ sc_int line_number;
};
typedef sx_scr_location_t *sx_scr_locationref_t;
@@ -180,12 +169,12 @@ typedef sx_scr_location_t *sx_scr_locationref_t;
* Save and restore the script location in the given structure.
*/
static void
-scr_save_location (sx_script script, sx_scr_locationref_t location) {
+scr_save_location(sx_script script, sx_scr_locationref_t location) {
location->position = script->pos();
location->line_number = scr_line_number;
}
-static void scr_restore_location (sx_script script, sx_scr_locationref_t location) {
+static void scr_restore_location(sx_script script, sx_scr_locationref_t location) {
script->seek(location->position);
scr_line_number = location->line_number;
}
@@ -198,28 +187,26 @@ static void scr_restore_location (sx_script script, sx_scr_locationref_t locatio
* line from the script. Returns NULL if no more lines, or on file error. The
* return string is allocated, and it's the caller's responsibility to free it.
*/
-static sc_char *scr_get_next_line (sx_script script) {
- sc_char *buffer, *line = NULL;
-
- /* Allocate a buffer for line reads. */
- buffer = (sc_char *)sx_malloc(LINE_BUFFER_SIZE);
-
- /* Read until a significant line is found, or end of file or error. */
- while (adrift_fgets(buffer, LINE_BUFFER_SIZE, script))
- {
- scr_line_number++;
- if (!scr_is_line_comment_or_empty (buffer))
- {
- line = buffer;
- break;
- }
- }
-
- /* If no significant line read, free the read buffer. */
- if (!line)
- sx_free (buffer);
-
- return line;
+static sc_char *scr_get_next_line(sx_script script) {
+ sc_char *buffer, *line = NULL;
+
+ /* Allocate a buffer for line reads. */
+ buffer = (sc_char *)sx_malloc(LINE_BUFFER_SIZE);
+
+ /* Read until a significant line is found, or end of file or error. */
+ while (adrift_fgets(buffer, LINE_BUFFER_SIZE, script)) {
+ scr_line_number++;
+ if (!scr_is_line_comment_or_empty(buffer)) {
+ line = buffer;
+ break;
+ }
+ }
+
+ /* If no significant line read, free the read buffer. */
+ if (!line)
+ sx_free(buffer);
+
+ return line;
}
@@ -231,23 +218,19 @@ static sc_char *scr_get_next_line (sx_script script) {
* instead.
*/
static sc_char *
-scr_concatenate (sc_char *string, const sc_char *buffer)
-{
- /* If string is not null, concatenate buffer, otherwise duplicate. */
- if (string)
- {
- string = (sc_char *)sx_realloc(string,
- strlen (string) + 1 + strlen (buffer) + 1);
- strcat (string, " ");
- strcat (string, buffer);
- }
- else
- {
- string = (sc_char *)sx_malloc(strlen (buffer) + 1);
- strcpy (string, buffer);
- }
-
- return string;
+scr_concatenate(sc_char *string, const sc_char *buffer) {
+ /* If string is not null, concatenate buffer, otherwise duplicate. */
+ if (string) {
+ string = (sc_char *)sx_realloc(string,
+ strlen(string) + 1 + strlen(buffer) + 1);
+ strcat(string, " ");
+ strcat(string, buffer);
+ } else {
+ string = (sc_char *)sx_malloc(strlen(buffer) + 1);
+ strcpy(string, buffer);
+ }
+
+ return string;
}
@@ -261,65 +244,57 @@ scr_concatenate (sc_char *string, const sc_char *buffer)
* free them.
*/
static sc_bool
-scr_get_next_section (sx_script script,
- sc_char **command, sc_char **expectation)
-{
- sc_char *line, *first_line, *other_lines;
- sx_scr_location_t location;
-
- /* Clear initial line accumulation. */
- first_line = other_lines = NULL;
-
- /* Read the next significant line from the script. */
- scr_save_location (script, &location);
- line = scr_get_next_line (script);
- while (line)
- {
- /* If already a first line, this is other lines or section end. */
- if (first_line)
- {
- /*
- * If we found the start of the next section, reset the script
- * location that saved on the line read, and we're done.
- */
- if (scr_is_line_command (line))
- {
- scr_restore_location (script, &location);
- sx_free (line);
- break;
- }
- else
- other_lines = scr_concatenate (other_lines, line);
- }
- else
- first_line = scr_concatenate (first_line, line);
-
- sx_free (line);
-
- /* Read the next significant line from the script. */
- scr_save_location (script, &location);
- line = scr_get_next_line (script);
- }
-
- /* Clean up and return nothing on file error. */
- if (script->err())
- {
- scr_test_failed ("Script error: Failed reading script input file", "");
- sx_free (first_line);
- sx_free (other_lines);
- return FALSE;
- }
-
- /* Return the command and the matching expectation string, if any. */
- if (first_line)
- {
- *command = sx_normalize_string (first_line);
- *expectation = other_lines ? sx_normalize_string (other_lines) : NULL;
- return TRUE;
- }
-
- /* End of file, no command section read. */
- return FALSE;
+scr_get_next_section(sx_script script,
+ sc_char **command, sc_char **expectation) {
+ sc_char *line, *first_line, *other_lines;
+ sx_scr_location_t location;
+
+ /* Clear initial line accumulation. */
+ first_line = other_lines = NULL;
+
+ /* Read the next significant line from the script. */
+ scr_save_location(script, &location);
+ line = scr_get_next_line(script);
+ while (line) {
+ /* If already a first line, this is other lines or section end. */
+ if (first_line) {
+ /*
+ * If we found the start of the next section, reset the script
+ * location that saved on the line read, and we're done.
+ */
+ if (scr_is_line_command(line)) {
+ scr_restore_location(script, &location);
+ sx_free(line);
+ break;
+ } else
+ other_lines = scr_concatenate(other_lines, line);
+ } else
+ first_line = scr_concatenate(first_line, line);
+
+ sx_free(line);
+
+ /* Read the next significant line from the script. */
+ scr_save_location(script, &location);
+ line = scr_get_next_line(script);
+ }
+
+ /* Clean up and return nothing on file error. */
+ if (script->err()) {
+ scr_test_failed("Script error: Failed reading script input file", "");
+ sx_free(first_line);
+ sx_free(other_lines);
+ return FALSE;
+ }
+
+ /* Return the command and the matching expectation string, if any. */
+ if (first_line) {
+ *command = sx_normalize_string(first_line);
+ *expectation = other_lines ? sx_normalize_string(other_lines) : NULL;
+ return TRUE;
+ }
+
+ /* End of file, no command section read. */
+ return FALSE;
}
@@ -334,48 +309,41 @@ scr_get_next_section (sx_script script,
* input.
*/
static void
-scr_expect (sc_char *expectation)
-{
- /*
- * Save the expectation, and set up collection of game output if needed.
- * And if not needed, ensure expectation and game output are cleared.
- */
- if (expectation)
- {
- scr_expectation = (sc_char *)sx_malloc(strlen (expectation) + 1);
- strcpy (scr_expectation, expectation);
- scr_game_output = (sc_char *)sx_malloc (1);
- strcpy (scr_game_output, "");
- }
- else
- {
- sx_free(scr_expectation);
- scr_expectation = NULL;
- sx_free(scr_game_output);
- scr_game_output = NULL;
- }
+scr_expect(sc_char *expectation) {
+ /*
+ * Save the expectation, and set up collection of game output if needed.
+ * And if not needed, ensure expectation and game output are cleared.
+ */
+ if (expectation) {
+ scr_expectation = (sc_char *)sx_malloc(strlen(expectation) + 1);
+ strcpy(scr_expectation, expectation);
+ scr_game_output = (sc_char *)sx_malloc(1);
+ strcpy(scr_game_output, "");
+ } else {
+ sx_free(scr_expectation);
+ scr_expectation = NULL;
+ sx_free(scr_game_output);
+ scr_game_output = NULL;
+ }
}
static void
-scr_verify_expectation (void)
-{
- /* Compare expected with actual, and handle any error detected. */
- if (scr_expectation && scr_game_output)
- {
- scr_game_output = sx_normalize_string (scr_game_output);
- if (!glob_match (scr_expectation, scr_game_output))
- {
- scr_test_failed ("Expectation error:", "");
- scr_test_message (" Expected: \"%s\"", scr_expectation);
- scr_test_message (" Received: \"%s\"", scr_game_output);
- }
- }
-
- /* Dispose of the expectation and accumulated game output. */
- sx_free (scr_expectation);
- scr_expectation = NULL;
- sx_free (scr_game_output);
- scr_game_output = NULL;
+scr_verify_expectation(void) {
+ /* Compare expected with actual, and handle any error detected. */
+ if (scr_expectation && scr_game_output) {
+ scr_game_output = sx_normalize_string(scr_game_output);
+ if (!glob_match(scr_expectation, scr_game_output)) {
+ scr_test_failed("Expectation error:", "");
+ scr_test_message(" Expected: \"%s\"", scr_expectation);
+ scr_test_message(" Received: \"%s\"", scr_game_output);
+ }
+ }
+
+ /* Dispose of the expectation and accumulated game output. */
+ sx_free(scr_expectation);
+ scr_expectation = NULL;
+ sx_free(scr_game_output);
+ scr_game_output = NULL;
}
@@ -390,28 +358,26 @@ scr_verify_expectation (void)
* to turn it off when it's no longer needed.
*/
static void
-scr_execute_debugger_command (const sc_char *command, sc_char *expectation)
-{
- sc_bool status;
-
- /* Set up the expectation. */
- scr_expect (expectation);
-
- /*
- * Execute the command via the debugger interface. The "+1" on command
- * skips the leading '~' read in from the game script.
- */
- sc_set_game_debugger_enabled (scr_game, TRUE);
- status = sc_run_game_debugger_command (scr_game, command + 1);
-
- if (!status)
- {
- scr_test_failed ("Script error:"
- " Debug command \"%s\" is not valid", command);
- }
-
- /* Check expectations immediately. */
- scr_verify_expectation ();
+scr_execute_debugger_command(const sc_char *command, sc_char *expectation) {
+ sc_bool status;
+
+ /* Set up the expectation. */
+ scr_expect(expectation);
+
+ /*
+ * Execute the command via the debugger interface. The "+1" on command
+ * skips the leading '~' read in from the game script.
+ */
+ sc_set_game_debugger_enabled(scr_game, TRUE);
+ status = sc_run_game_debugger_command(scr_game, command + 1);
+
+ if (!status) {
+ scr_test_failed("Script error:"
+ " Debug command \"%s\" is not valid", command);
+ }
+
+ /* Check expectations immediately. */
+ scr_verify_expectation();
}
@@ -425,65 +391,60 @@ scr_execute_debugger_command (const sc_char *command, sc_char *expectation)
* to the game.
*/
static sc_bool
-scr_read_line_callback (sc_char *buffer, sc_int length)
-{
- sc_char *command, *expectation;
- assert (buffer && length > 0);
-
- /* Check pending expectation, and clear settings for the next line. */
- scr_verify_expectation ();
-
- /* Get the next line-expectation pair from the script stream. */
- if (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- /* The debugger persists where debug commands are adjacent. */
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
-
- /*
- * Returning FALSE here causes the game to re-prompt. We could
- * loop (or tail recurse) ourselves, but returning is simpler.
- */
- return FALSE;
- }
- else
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- if (scr_is_line_game_command (command))
- {
- /* Set up the expectation. */
- scr_expect (expectation);
-
- /* Copy out the line to the return buffer, and free the line. */
- strncpy (buffer, command + 1, length);
- buffer[length - 1] = NUL;
- sx_free (command);
- sx_free (expectation);
- return TRUE;
- }
-
- /* Neither a '~' nor a '>' command. */
- scr_test_failed ("Script error:"
- " Command \"%s\" is not valid, ignored", command);
- sx_free (command);
- sx_free (expectation);
- return FALSE;
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- /*
- * We reached the end of the script without finding a "quit" command.
- * Supply one here, then. In the unlikely even that this does not quit
- * the game, we'll iterate on this.
- */
- assert (length > 4);
- strcpy (buffer, "quit");
- return TRUE;
+scr_read_line_callback(sc_char *buffer, sc_int length) {
+ sc_char *command, *expectation;
+ assert(buffer && length > 0);
+
+ /* Check pending expectation, and clear settings for the next line. */
+ scr_verify_expectation();
+
+ /* Get the next line-expectation pair from the script stream. */
+ if (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ /* The debugger persists where debug commands are adjacent. */
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+
+ /*
+ * Returning FALSE here causes the game to re-prompt. We could
+ * loop (or tail recurse) ourselves, but returning is simpler.
+ */
+ return FALSE;
+ } else
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ if (scr_is_line_game_command(command)) {
+ /* Set up the expectation. */
+ scr_expect(expectation);
+
+ /* Copy out the line to the return buffer, and free the line. */
+ strncpy(buffer, command + 1, length);
+ buffer[length - 1] = NUL;
+ sx_free(command);
+ sx_free(expectation);
+ return TRUE;
+ }
+
+ /* Neither a '~' nor a '>' command. */
+ scr_test_failed("Script error:"
+ " Command \"%s\" is not valid, ignored", command);
+ sx_free(command);
+ sx_free(expectation);
+ return FALSE;
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ /*
+ * We reached the end of the script without finding a "quit" command.
+ * Supply one here, then. In the unlikely even that this does not quit
+ * the game, we'll iterate on this.
+ */
+ assert(length > 4);
+ strcpy(buffer, "quit");
+ return TRUE;
}
@@ -495,17 +456,15 @@ scr_read_line_callback (sc_char *buffer, sc_int length)
* the current game output will be NULL, and we can simply save the effort.
*/
static void
-scr_print_string_callback (const sc_char *string)
-{
- assert (string);
-
- if (scr_game_output)
- {
- scr_game_output = (sc_char *)sx_realloc (scr_game_output,
- strlen (scr_game_output)
- + strlen (string) + 1);
- strcat (scr_game_output, string);
- }
+scr_print_string_callback(const sc_char *string) {
+ assert(string);
+
+ if (scr_game_output) {
+ scr_game_output = (sc_char *)sx_realloc(scr_game_output,
+ strlen(scr_game_output)
+ + strlen(string) + 1);
+ strcat(scr_game_output, string);
+ }
}
@@ -518,68 +477,60 @@ scr_print_string_callback (const sc_char *string)
* and match against the expectations on next request or on finalization.
*/
void
-scr_start_script (sc_game game, sx_script script)
-{
- sc_char *command, *expectation;
- sx_scr_location_t location;
- assert (game && script);
-
- /* Save the game and stream, and clear the line number and errors count. */
- assert (!scr_game && !scr_script);
- scr_game = game;
- scr_script = script;
- scr_line_number = 0;
- scr_errors = 0;
-
- /* Set up our callback functions to catch game i/o. */
- stub_attach_handlers (scr_read_line_callback, scr_print_string_callback,
- file_open_file_callback, file_read_file_callback,
- file_write_file_callback, file_close_file_callback);
-
- /*
- * Handle any initial debugging commands, terminating on either a non-
- * debugging one or an expectation for the game intro.
- */
- scr_script->seek(0);
- scr_save_location (scr_script, &location);
- while (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- if (scr_is_line_empty_debug_command (command))
- {
- /* It's an intro expectation - set and break loop. */
- scr_expect (expectation);
- sx_free (command);
- sx_free (expectation);
- break;
- }
- else
- {
- /* It's a full debug command - execute it as one. */
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
- }
- }
- else
- {
- /*
- * It's an ordinary section - rewind so that it's the first one
- * handled in the callback, and break loop.
- */
- scr_restore_location (scr_script, &location);
- sx_free (command);
- sx_free (expectation);
- break;
- }
-
- /* Note script position before reading the next section. */
- scr_save_location (scr_script, &location);
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
+scr_start_script(sc_game game, sx_script script) {
+ sc_char *command, *expectation;
+ sx_scr_location_t location;
+ assert(game && script);
+
+ /* Save the game and stream, and clear the line number and errors count. */
+ assert(!scr_game && !scr_script);
+ scr_game = game;
+ scr_script = script;
+ scr_line_number = 0;
+ scr_errors = 0;
+
+ /* Set up our callback functions to catch game i/o. */
+ stub_attach_handlers(scr_read_line_callback, scr_print_string_callback,
+ file_open_file_callback, file_read_file_callback,
+ file_write_file_callback, file_close_file_callback);
+
+ /*
+ * Handle any initial debugging commands, terminating on either a non-
+ * debugging one or an expectation for the game intro.
+ */
+ scr_script->seek(0);
+ scr_save_location(scr_script, &location);
+ while (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ if (scr_is_line_empty_debug_command(command)) {
+ /* It's an intro expectation - set and break loop. */
+ scr_expect(expectation);
+ sx_free(command);
+ sx_free(expectation);
+ break;
+ } else {
+ /* It's a full debug command - execute it as one. */
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+ }
+ } else {
+ /*
+ * It's an ordinary section - rewind so that it's the first one
+ * handled in the callback, and break loop.
+ */
+ scr_restore_location(scr_script, &location);
+ sx_free(command);
+ sx_free(expectation);
+ break;
+ }
+
+ /* Note script position before reading the next section. */
+ scr_save_location(scr_script, &location);
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
}
@@ -591,51 +542,46 @@ scr_start_script (sc_game game, sx_script script)
* count of errors detected during the script.
*/
sc_int
-scr_finalize_script (void)
-{
- sc_char *command, *expectation;
- sc_int errors;
-
- /* Check pending expectation, and clear settings. */
- scr_verify_expectation ();
-
- /* Drain the remainder of the script, ignoring non-debugging commands. */
- while (scr_get_next_section (scr_script, &command, &expectation))
- {
- if (scr_is_line_debug_command (command))
- {
- scr_execute_debugger_command (command, expectation);
- sx_free (command);
- sx_free (expectation);
- }
- else
- {
- /* Complain about script entries ignored because the game ended. */
- scr_test_failed ("Script error:"
- " Game completed, command \"%s\" ignored", command);
- sx_free (command);
- sx_free (expectation);
- }
- }
-
- /* Ensure the game debugger is off after this section. */
- sc_set_game_debugger_enabled (scr_game, FALSE);
-
- /*
- * Remove our callback functions from the stubs, and "close" any retained
- * stream data from game save/load tests.
- */
- stub_detach_handlers ();
- file_cleanup ();
-
- /* Clear local records of game stream, line number, and errors count. */
- errors = scr_errors;
- scr_game = NULL;
- scr_script = NULL;
- scr_line_number = 0;
- scr_errors = 0;
-
- return errors;
+scr_finalize_script(void) {
+ sc_char *command, *expectation;
+ sc_int errors;
+
+ /* Check pending expectation, and clear settings. */
+ scr_verify_expectation();
+
+ /* Drain the remainder of the script, ignoring non-debugging commands. */
+ while (scr_get_next_section(scr_script, &command, &expectation)) {
+ if (scr_is_line_debug_command(command)) {
+ scr_execute_debugger_command(command, expectation);
+ sx_free(command);
+ sx_free(expectation);
+ } else {
+ /* Complain about script entries ignored because the game ended. */
+ scr_test_failed("Script error:"
+ " Game completed, command \"%s\" ignored", command);
+ sx_free(command);
+ sx_free(expectation);
+ }
+ }
+
+ /* Ensure the game debugger is off after this section. */
+ sc_set_game_debugger_enabled(scr_game, FALSE);
+
+ /*
+ * Remove our callback functions from the stubs, and "close" any retained
+ * stream data from game save/load tests.
+ */
+ stub_detach_handlers();
+ file_cleanup();
+
+ /* Clear local records of game stream, line number, and errors count. */
+ errors = scr_errors;
+ scr_game = NULL;
+ scr_script = NULL;
+ scr_line_number = 0;
+ scr_errors = 0;
+
+ return errors;
}
} // End of namespace Adrift