1 /* ------------------------------------------------------------------------- */
2 /* "files" : File handling for source code, the transcript file and the */
3 /* debugging information file; file handling and splicing of */
6 /* Note that filenaming conventions are left to the top-level */
7 /* routines in "inform.c", since they are tied up with ICL */
8 /* settings and are very host OS-dependent. */
10 /* Part of Inform 6.40 */
11 /* copyright (c) Graham Nelson 1993 - 2022 */
13 /* Inform is free software: you can redistribute it and/or modify */
14 /* it under the terms of the GNU General Public License as published by */
15 /* the Free Software Foundation, either version 3 of the License, or */
16 /* (at your option) any later version. */
18 /* Inform is distributed in the hope that it will be useful, */
19 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
20 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
21 /* GNU General Public License for more details. */
23 /* You should have received a copy of the GNU General Public License */
24 /* along with Inform. If not, see https://gnu.org/licenses/ */
26 /* ------------------------------------------------------------------------- */
30 int total_files; /* Number of files so far, including
31 #include and #origsource files */
32 int total_input_files; /* Number of source files so far
33 (excludes #origsource) */
34 int current_input_file; /* Most recently-opened source file */
35 static int current_origsource_file; /* Most recently-used #origsource */
37 int32 total_chars_read; /* Characters read in (from all
38 source files put together) */
40 static int checksum_low_byte, /* For calculating the Z-machine's */
41 checksum_high_byte; /* "verify" checksum */
43 static int32 checksum_long; /* For the Glulx checksum, */
44 static int checksum_count; /* similarly */
46 /* ------------------------------------------------------------------------- */
47 /* Most of the information about source files is kept by "lexer.c"; this */
48 /* level is only concerned with file names and handles. */
49 /* ------------------------------------------------------------------------- */
51 FileId *InputFiles=NULL; /* Ids for all the source files
52 Allocated to total_files */
53 static memory_list InputFiles_memlist;
55 /* ------------------------------------------------------------------------- */
56 /* When emitting debug information, we won't have addresses of routines, */
57 /* sequence points, Glulx objects (addresses of Z-machine objects aren't */
58 /* needed), globals, arrays, or grammar lines. We only have their */
59 /* offsets from base addresses, which won't be known until the end of */
60 /* compilation. Since everything else in the relevant debug records is */
61 /* known much earlier and is less convenient to store up, we emit the */
62 /* debug records with a placeholder value and then backpatch these */
63 /* placeholders. The following structs each store either an offset or a */
64 /* symbol index and the point in the debug information file where the */
65 /* corresponding address should be written once the base address is known. */
66 /* ------------------------------------------------------------------------- */
68 #define INITIAL_DEBUG_INFORMATION_BACKPATCH_ALLOCATION 65536
70 typedef struct value_and_backpatch_position_struct
72 fpos_t backpatch_position;
73 } value_and_backpatch_position;
75 typedef struct debug_backpatch_accumulator_struct
76 { int32 number_of_values_to_backpatch;
77 int32 number_of_available_backpatches;
78 value_and_backpatch_position *values_and_backpatch_positions;
79 int32 (* backpatching_function)(int32);
80 } debug_backpatch_accumulator;
82 static debug_backpatch_accumulator object_backpatch_accumulator;
83 static debug_backpatch_accumulator packed_code_backpatch_accumulator;
84 static debug_backpatch_accumulator code_backpatch_accumulator;
85 static debug_backpatch_accumulator global_backpatch_accumulator;
86 static debug_backpatch_accumulator array_backpatch_accumulator;
87 static debug_backpatch_accumulator grammar_backpatch_accumulator;
89 /* ------------------------------------------------------------------------- */
90 /* Opening and closing source code files */
91 /* ------------------------------------------------------------------------- */
93 #if defined(PC_WIN32) && defined(HAS_REALPATH)
95 char *realpath(const char *path, char *resolved_path)
97 return GetFullPathNameA(path,PATHLEN,resolved_path,NULL) != 0 ? resolved_path : 0;
101 extern void load_sourcefile(char *filename_given, int same_directory_flag)
103 /* Meaning: open a new file of Inform source. (The lexer picks up on
104 this by noticing that input_file has increased.) */
108 char absolute_name[PATHLEN];
113 ensure_memory_list_available(&InputFiles_memlist, total_files+1);
116 { x = translate_in_filename(x, name, filename_given, same_directory_flag,
117 (total_files==0)?1:0);
118 handle = fopen(name,"r");
119 } while ((handle == NULL) && (x != 0));
121 InputFiles[total_files].filename = my_malloc(strlen(name)+1, "filename storage");
122 strcpy(InputFiles[total_files].filename, name);
124 if (debugfile_switch)
125 { debug_file_printf("<source index=\"%d\">", total_files);
126 debug_file_printf("<given-path>");
127 debug_file_print_with_entities(filename_given);
128 debug_file_printf("</given-path>");
130 if (realpath(name, absolute_name))
131 { debug_file_printf("<resolved-path>");
132 debug_file_print_with_entities(absolute_name);
133 debug_file_printf("</resolved-path>");
136 debug_file_printf("<language>Inform 6</language>");
137 debug_file_printf("</source>");
140 InputFiles[total_files].handle = handle;
141 if (InputFiles[total_files].handle==NULL)
142 fatalerror_named("Couldn't open source file", name);
144 InputFiles[total_files].is_input = TRUE;
145 InputFiles[total_files].initial_buffering = TRUE;
147 if (files_trace_setting > 0)
148 printf("Opening file \"%s\"\n",name);
152 current_input_file = total_files;
155 static void close_sourcefile(int file_number)
157 if (InputFiles[file_number-1].handle == NULL) return;
159 /* Close this file. But keep the InputFiles entry around, including
162 if (ferror(InputFiles[file_number-1].handle))
163 fatalerror_named("I/O failure: couldn't read from source file",
164 InputFiles[file_number-1].filename);
166 fclose(InputFiles[file_number-1].handle);
168 InputFiles[file_number-1].handle = NULL;
170 if (files_trace_setting > 0) {
171 char *str = (InputFiles[file_number-1].initial_buffering ? " (in initial buffering)" : "");
172 printf("Closing file \"%s\"%s\n", InputFiles[file_number-1].filename, str);
176 extern void close_all_source(void)
178 for (i=0; i<total_files; i++) close_sourcefile(i+1);
181 /* ------------------------------------------------------------------------- */
182 /* Register an #origsource filename. This goes in the InputFiles table, */
183 /* but we do not open the file or advance current_input_file. */
184 /* ------------------------------------------------------------------------- */
186 extern int register_orig_sourcefile(char *filename)
191 /* If the filename has already been used as an origsource filename,
192 return that entry. We check the most-recently-used file first, and
193 then search the list. */
194 if (current_origsource_file > 0 && current_origsource_file <= total_files) {
195 if (!strcmp(filename, InputFiles[current_origsource_file-1].filename))
196 return current_origsource_file;
199 for (ix=0; ix<total_files; ix++) {
200 if (InputFiles[ix].is_input)
202 if (!strcmp(filename, InputFiles[ix].filename)) {
203 current_origsource_file = ix+1;
204 return current_origsource_file;
208 /* This filename has never been used before. Allocate a new InputFiles
211 name = filename; /* no translation */
213 ensure_memory_list_available(&InputFiles_memlist, total_files+1);
215 InputFiles[total_files].filename = my_malloc(strlen(name)+1, "filename storage");
216 strcpy(InputFiles[total_files].filename, name);
218 if (debugfile_switch)
219 { debug_file_printf("<source index=\"%d\">", total_files);
220 debug_file_printf("<given-path>");
221 debug_file_print_with_entities(filename);
222 debug_file_printf("</given-path>");
223 debug_file_printf("<language>Inform 7</language>");
224 debug_file_printf("</source>");
227 InputFiles[total_files].handle = NULL;
228 InputFiles[total_files].is_input = FALSE;
229 InputFiles[total_files].initial_buffering = FALSE;
232 current_origsource_file = total_files;
233 return current_origsource_file;
236 /* ------------------------------------------------------------------------- */
237 /* Feeding source code up into the lexical analyser's buffer */
238 /* (see "lexer.c" for its specification) */
239 /* ------------------------------------------------------------------------- */
241 extern int file_load_chars(int file_number, char *buffer, int length)
243 int read_in; FILE *handle;
245 if (file_number-1 > total_files)
246 { buffer[0] = 0; return 1; }
248 handle = InputFiles[file_number-1].handle;
250 { buffer[0] = 0; return 1; }
252 read_in = fread(buffer, 1, length, handle);
253 total_chars_read += read_in;
255 if (read_in == length) return length;
257 close_sourcefile(file_number);
259 if (file_number == 1)
260 { buffer[read_in] = 0;
261 buffer[read_in+1] = 0;
262 buffer[read_in+2] = 0;
263 buffer[read_in+3] = 0;
266 { buffer[read_in] = '\n';
267 buffer[read_in+1] = ' ';
268 buffer[read_in+2] = ' ';
269 buffer[read_in+3] = ' ';
272 return(-(read_in+4));
275 /* ------------------------------------------------------------------------- */
276 /* Final assembly and output of the story file/module. */
277 /* ------------------------------------------------------------------------- */
281 static void sf_put(int c)
285 /* The checksum is the unsigned sum mod 65536 of the bytes in the
286 story file from 0x0040 (first byte after header) to the end.
288 The link data does not contribute to the checksum of a module. */
290 checksum_low_byte += c;
291 if (checksum_low_byte>=256)
292 { checksum_low_byte-=256;
293 if (++checksum_high_byte==256) checksum_high_byte=0;
299 /* The checksum is the unsigned 32-bit sum of the entire story file,
300 considered as a list of 32-bit words, with the checksum field
303 switch (checksum_count) {
305 checksum_long += (((int32)(c & 0xFF)) << 24);
308 checksum_long += (((int32)(c & 0xFF)) << 16);
311 checksum_long += (((int32)(c & 0xFF)) << 8);
314 checksum_long += ((int32)(c & 0xFF));
318 checksum_count = (checksum_count+1) & 3;
325 /* Recursive procedure to generate the Glulx compression table. */
327 static void output_compression(int entnum, int32 *size, int *count)
329 huffentity_t *ent = &(huff_entities[entnum]);
339 val = Write_Strings_At + huff_entities[ent->u.branch[0]].addr;
340 sf_put((val >> 24) & 0xFF);
341 sf_put((val >> 16) & 0xFF);
342 sf_put((val >> 8) & 0xFF);
343 sf_put((val) & 0xFF);
345 val = Write_Strings_At + huff_entities[ent->u.branch[1]].addr;
346 sf_put((val >> 24) & 0xFF);
347 sf_put((val >> 16) & 0xFF);
348 sf_put((val >> 8) & 0xFF);
349 sf_put((val) & 0xFF);
351 output_compression(ent->u.branch[0], size, count);
352 output_compression(ent->u.branch[1], size, count);
362 cx = (char *)abbreviations_at + ent->u.val*MAX_ABBREV_LENGTH;
372 val = unicode_usage_entries[ent->u.val].ch;
373 sf_put((val >> 24) & 0xFF);
374 sf_put((val >> 16) & 0xFF);
375 sf_put((val >> 8) & 0xFF);
376 sf_put((val) & 0xFF);
380 val = abbreviations_offset + 4 + ent->u.val*4;
381 sf_put((val >> 24) & 0xFF);
382 sf_put((val >> 16) & 0xFF);
383 sf_put((val >> 8) & 0xFF);
384 sf_put((val) & 0xFF);
390 static void output_file_z(void)
391 { char new_name[PATHLEN];
392 int32 length, blanks=0, size, i, j, offset;
393 uint32 code_length, size_before_code, next_cons_check;
398 /* At this point, construct_storyfile() has just been called. */
400 /* Enter the length information into the header. */
402 length=((int32) Write_Strings_At) + static_strings_extent;
403 if (module_switch) length += link_data_size +
404 zcode_backpatch_size +
405 zmachine_backpatch_size;
407 while ((length%length_scale_factor)!=0) { length++; blanks++; }
408 length=length/length_scale_factor;
409 zmachine_paged_memory[26]=(length & 0xff00)/0x100;
410 zmachine_paged_memory[27]=(length & 0xff);
412 /* To assist interpreters running a paged virtual memory system, Inform
413 writes files which are padded with zeros to the next multiple of
414 0.5K. This calculates the number of bytes of padding needed: */
416 while (((length_scale_factor*length)+blanks-1)%512 != 511) blanks++;
418 translate_out_filename(new_name, Code_Name);
420 sf_handle = fopen(new_name,"wb");
421 if (sf_handle == NULL)
422 fatalerror_named("Couldn't open output file", new_name);
425 /* Set the type and creator to Andrew Plotkin's MaxZip, a popular
426 Z-code interpreter on the Macintosh */
428 if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
431 /* (1) Output the paged memory. */
434 fputc(zmachine_paged_memory[i], sf_handle);
436 checksum_low_byte = 0;
437 checksum_high_byte = 0;
439 for (i=64; i<Write_Code_At; i++)
440 { sf_put(zmachine_paged_memory[i]); size++;
443 /* (2) Output the compiled code area. */
445 if (!OMIT_UNUSED_ROUTINES) {
446 /* This is the old-fashioned case, which is easy. All of zcode_area
447 (zmachine_pc bytes) will be output. next_cons_check will be
448 ignored, because j will never reach it. */
449 code_length = zmachine_pc;
451 next_cons_check = code_length+1;
454 /* With dead function stripping, life is more complicated.
455 j will run from 0 to zmachine_pc, but only code_length of
456 those should be output. next_cons_check is the location of
457 the next function break; that's where we check whether
458 we're in a live function or a dead one.
459 (This logic is simplified by the assumption that a backpatch
460 marker will never straddle a function break.) */
461 if (zmachine_pc != df_total_size_before_stripping)
462 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
463 code_length = df_total_size_after_stripping;
466 df_prepare_function_iterate();
468 size_before_code = size;
472 for (i=0; i<zcode_backpatch_size; i=i+3)
473 { int long_flag = TRUE;
475 = 256*zcode_backpatch_table[i+1]
476 + zcode_backpatch_table[i+2];
477 backpatch_error_flag = FALSE;
479 = zcode_backpatch_table[i];
480 if (backpatch_marker >= 0x80) long_flag = FALSE;
481 backpatch_marker &= 0x7f;
482 offset = offset + (backpatch_marker/32)*0x10000;
483 while (offset+0x30000 < j) {
485 long_flag = !long_flag;
487 backpatch_marker &= 0x1f;
489 /* All code up until the next backpatch marker gets flushed out
490 as-is. (Unless we're in a stripped-out function.) */
493 while (j<offset && j<next_cons_check) {
498 while (j<offset && j<next_cons_check) {
500 sf_put(zcode_area[j]);
504 if (j == next_cons_check)
505 next_cons_check = df_next_function_iterate(&use_function);
509 { int32 v = zcode_area[j];
510 v = 256*v + (zcode_area[j+1]);
513 v = backpatch_value(v);
514 sf_put(v/256); sf_put(v%256);
519 { int32 v = zcode_area[j];
522 v = backpatch_value(v);
528 if (j > next_cons_check)
529 compiler_error("Backpatch appears to straddle function break");
531 if (backpatch_error_flag)
532 { printf("*** %s zcode offset=%08lx backpatch offset=%08lx ***\n",
533 (long_flag)?"long":"short", (long int) j, (long int) i);
537 /* Flush out the last bit of zcode_area, after the last backpatch
539 offset = zmachine_pc;
542 while (j<offset && j<next_cons_check) {
547 while (j<offset && j<next_cons_check) {
549 sf_put(zcode_area[j]);
553 if (j == next_cons_check)
554 next_cons_check = df_next_function_iterate(&use_function);
557 if (size_before_code + code_length != size)
558 compiler_error("Code output length did not match");
560 /* (3) Output any null bytes (required to reach a packed address)
561 before the strings area. */
563 while (size<Write_Strings_At) { sf_put(0); size++; }
565 /* (4) Output the static strings area. */
567 for (i=0; i<static_strings_extent; i++) {
568 sf_put(static_strings_area[i]);
572 /* (5) Output the linking data table (in the case of a module). */
575 for (i=0; i<link_data_size; i++)
576 sf_put(link_data_area[i]);
579 { for (i=0; i<zcode_backpatch_size; i++)
580 sf_put(zcode_backpatch_table[i]);
581 for (i=0; i<zmachine_backpatch_size; i++)
582 sf_put(zmachine_backpatch_table[i]);
585 /* (6) Output null bytes to reach a multiple of 0.5K. */
587 while (blanks>0) { sf_put(0); blanks--; }
589 if (ferror(sf_handle))
590 fatalerror("I/O failure: couldn't write to story file");
592 fseek(sf_handle, 28, SEEK_SET);
593 fputc(checksum_high_byte, sf_handle);
594 fputc(checksum_low_byte, sf_handle);
596 if (ferror(sf_handle))
597 fatalerror("I/O failure: couldn't backtrack on story file for checksum");
601 /* Write a copy of the header into the debugging information file
602 (mainly so that it can be used to identify which story file matches
603 with which debugging info file). */
605 if (debugfile_switch)
606 { debug_file_printf("<story-file-prefix>");
607 for (i = 0; i < 63; i += 3)
609 { debug_file_print_base_64_triple
610 (zmachine_paged_memory[27],
614 { debug_file_print_base_64_triple
615 (zmachine_paged_memory[i],
616 zmachine_paged_memory[i + 1],
617 zmachine_paged_memory[i + 2]);
620 debug_file_print_base_64_single(zmachine_paged_memory[63]);
621 debug_file_printf("</story-file-prefix>");
625 { char settype_command[PATHLEN];
626 sprintf(settype_command, "settype %s %s",
627 new_name, riscos_file_type());
628 system(settype_command);
633 InformFiletypes (new_name, INF_MODULE_TYPE);
635 InformFiletypes (new_name, INF_ZCODE_TYPE);
639 static void output_file_g(void)
640 { char new_name[PATHLEN];
641 int32 size, i, j, offset;
643 uint32 code_length, size_before_code, next_cons_check;
645 int first_byte_of_triple, second_byte_of_triple, third_byte_of_triple;
649 /* At this point, construct_storyfile() has just been called. */
651 translate_out_filename(new_name, Code_Name);
653 sf_handle = fopen(new_name,"wb+");
654 if (sf_handle == NULL)
655 fatalerror_named("Couldn't open output file", new_name);
658 /* Set the type and creator to Andrew Plotkin's MaxZip, a popular
659 Z-code interpreter on the Macintosh */
661 if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
667 /* Determine the version number. */
669 VersionNum = 0x00020000;
671 /* Increase for various features the game may have used. */
672 if (no_unicode_chars != 0 || (uses_unicode_features)) {
673 VersionNum = 0x00030000;
675 if (uses_memheap_features) {
676 VersionNum = 0x00030100;
678 if (uses_acceleration_features) {
679 VersionNum = 0x00030101;
681 if (uses_float_features) {
682 VersionNum = 0x00030102;
684 if (uses_extundo_features) {
685 VersionNum = 0x00030103;
688 /* And check if the user has requested a specific version. */
689 if (requested_glulx_version) {
690 if (requested_glulx_version < VersionNum) {
691 static char error_message_buff[256];
692 sprintf(error_message_buff, "Version 0x%08lx requested, but \
693 game features require version 0x%08lx", (long)requested_glulx_version, (long)VersionNum);
694 warning(error_message_buff);
697 VersionNum = requested_glulx_version;
701 /* (1) Output the header. We use sf_put here, instead of fputc,
702 because the header is included in the checksum. */
709 /* Version number. */
710 sf_put((VersionNum >> 24));
711 sf_put((VersionNum >> 16));
712 sf_put((VersionNum >> 8));
713 sf_put((VersionNum));
715 sf_put((Write_RAM_At >> 24));
716 sf_put((Write_RAM_At >> 16));
717 sf_put((Write_RAM_At >> 8));
718 sf_put((Write_RAM_At));
719 /* EXTSTART, or game file size */
720 sf_put((Out_Size >> 24));
721 sf_put((Out_Size >> 16));
722 sf_put((Out_Size >> 8));
724 /* ENDMEM, which the game file size plus MEMORY_MAP_EXTENSION */
725 i = Out_Size + MEMORY_MAP_EXTENSION;
731 sf_put((MAX_STACK_SIZE >> 24));
732 sf_put((MAX_STACK_SIZE >> 16));
733 sf_put((MAX_STACK_SIZE >> 8));
734 sf_put((MAX_STACK_SIZE));
735 /* Initial function to call. Inform sets things up so that this
736 is the start of the executable-code area. */
737 sf_put((Write_Code_At >> 24));
738 sf_put((Write_Code_At >> 16));
739 sf_put((Write_Code_At >> 8));
740 sf_put((Write_Code_At));
741 /* String-encoding table. */
742 sf_put((Write_Strings_At >> 24));
743 sf_put((Write_Strings_At >> 16));
744 sf_put((Write_Strings_At >> 8));
745 sf_put((Write_Strings_At));
746 /* Checksum -- zero for the moment. */
752 size = GLULX_HEADER_SIZE;
754 /* (1a) Output the eight-byte memory layout identifier. */
756 sf_put('I'); sf_put('n'); sf_put('f'); sf_put('o');
757 sf_put(0); sf_put(1); sf_put(0); sf_put(0);
759 /* (1b) Output the rest of the Inform-specific data. */
761 /* Inform version number */
762 sf_put('0' + ((RELEASE_NUMBER/100)%10));
764 sf_put('0' + ((RELEASE_NUMBER/10)%10));
765 sf_put('0' + RELEASE_NUMBER%10);
766 /* Glulx back-end version number */
767 sf_put('0' + ((GLULX_RELEASE_NUMBER/100)%10));
769 sf_put('0' + ((GLULX_RELEASE_NUMBER/10)%10));
770 sf_put('0' + GLULX_RELEASE_NUMBER%10);
771 /* Game release number */
772 sf_put((release_number>>8) & 0xFF);
773 sf_put(release_number & 0xFF);
774 /* Game serial number */
777 write_serial_number(serialnum);
779 sf_put(serialnum[i]);
781 size += GLULX_STATIC_ROM_SIZE;
783 /* (2) Output the compiled code area. */
785 if (!OMIT_UNUSED_ROUTINES) {
786 /* This is the old-fashioned case, which is easy. All of zcode_area
787 (zmachine_pc bytes) will be output. next_cons_check will be
788 ignored, because j will never reach it. */
789 code_length = zmachine_pc;
791 next_cons_check = code_length+1;
794 /* With dead function stripping, life is more complicated.
795 j will run from 0 to zmachine_pc, but only code_length of
796 those should be output. next_cons_check is the location of
797 the next function break; that's where we check whether
798 we're in a live function or a dead one.
799 (This logic is simplified by the assumption that a backpatch
800 marker will never straddle a function break.) */
801 if (zmachine_pc != df_total_size_before_stripping)
802 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
803 code_length = df_total_size_after_stripping;
806 df_prepare_function_iterate();
808 size_before_code = size;
812 for (i=0; i<zcode_backpatch_size; i=i+6) {
816 (zcode_backpatch_table[i+2] << 24)
817 | (zcode_backpatch_table[i+3] << 16)
818 | (zcode_backpatch_table[i+4] << 8)
819 | (zcode_backpatch_table[i+5]);
820 backpatch_error_flag = FALSE;
822 zcode_backpatch_table[i];
824 zcode_backpatch_table[i+1];
826 /* All code up until the next backpatch marker gets flushed out
827 as-is. (Unless we're in a stripped-out function.) */
830 while (j<offset && j<next_cons_check) {
835 while (j<offset && j<next_cons_check) {
837 sf_put(zcode_area[j]);
841 if (j == next_cons_check)
842 next_cons_check = df_next_function_iterate(&use_function);
845 /* Write out the converted value of the backpatch marker.
846 (Unless we're in a stripped-out function.) */
851 v = (v << 8) | (zcode_area[j+1]);
852 v = (v << 8) | (zcode_area[j+2]);
853 v = (v << 8) | (zcode_area[j+3]);
857 v = backpatch_value(v);
858 sf_put((v >> 24) & 0xFF);
859 sf_put((v >> 16) & 0xFF);
860 sf_put((v >> 8) & 0xFF);
867 v = (v << 8) | (zcode_area[j+1]);
871 v = backpatch_value(v);
873 printf("*** backpatch value does not fit ***\n");
874 backpatch_error_flag = TRUE;
876 sf_put((v >> 8) & 0xFF);
886 v = backpatch_value(v);
888 printf("*** backpatch value does not fit ***\n");
889 backpatch_error_flag = TRUE;
896 printf("*** unknown backpatch data len = %d ***\n",
898 backpatch_error_flag = TRUE;
901 if (j > next_cons_check)
902 compiler_error("Backpatch appears to straddle function break");
904 if (backpatch_error_flag) {
905 printf("*** %d bytes zcode offset=%08lx backpatch offset=%08lx ***\n",
906 data_len, (long int) j, (long int) i);
910 /* Flush out the last bit of zcode_area, after the last backpatch
912 offset = zmachine_pc;
915 while (j<offset && j<next_cons_check) {
920 while (j<offset && j<next_cons_check) {
922 sf_put(zcode_area[j]);
926 if (j == next_cons_check)
927 next_cons_check = df_next_function_iterate(&use_function);
930 if (size_before_code + code_length != size)
931 compiler_error("Code output length did not match");
933 /* (4) Output the static strings area. */
937 int ch, jx, curbyte, bx;
938 int depth, checkcount;
944 if (compression_switch) {
946 /* The 12-byte table header. */
947 lx = compression_table_size;
948 sf_put((lx >> 24) & 0xFF);
949 sf_put((lx >> 16) & 0xFF);
950 sf_put((lx >> 8) & 0xFF);
953 sf_put((no_huff_entities >> 24) & 0xFF);
954 sf_put((no_huff_entities >> 16) & 0xFF);
955 sf_put((no_huff_entities >> 8) & 0xFF);
956 sf_put((no_huff_entities) & 0xFF);
958 lx = Write_Strings_At + 12;
959 sf_put((lx >> 24) & 0xFF);
960 sf_put((lx >> 16) & 0xFF);
961 sf_put((lx >> 8) & 0xFF);
966 output_compression(huff_entity_root, &size, &checkcount);
967 if (checkcount != no_huff_entities)
968 compiler_error("Compression table count mismatch.");
971 if (size - origsize != compression_table_size)
972 compiler_error("Compression table size mismatch.");
976 for (lx=0, ix=0; lx<no_strings; lx++) {
977 int escapelen=0, escapetype=0;
980 if (compression_switch)
981 sf_put(0xE1); /* type byte -- compressed string */
983 sf_put(0xE0); /* type byte -- non-compressed string */
988 ch = static_strings_area[ix];
990 if (ix > static_strings_extent || ch < 0)
991 compiler_error("Read too much not-yet-compressed text.");
993 if (escapelen == -1) {
998 else if (ch == '0') {
1001 else if (ch == 'A' || ch == 'D' || ch == 'U') {
1008 compiler_error("Strange @ escape in processed text.");
1011 else if (escapelen) {
1012 escapeval = (escapeval << 4) | ((ch-'A') & 0x0F);
1014 if (escapelen == 0) {
1015 if (escapetype == 'A') {
1016 ch = huff_abbrev_start+escapeval;
1018 else if (escapetype == 'D') {
1019 ch = huff_dynam_start+escapeval;
1021 else if (escapetype == 'U') {
1022 ch = huff_unicode_start+escapeval;
1025 compiler_error("Strange @ escape in processed text.");
1042 if (compression_switch) {
1043 bits = &(huff_entities[ch].bits);
1044 depth = huff_entities[ch].depth;
1045 for (bx=0; bx<depth; bx++) {
1046 if (bits->b[bx / 8] & (1 << (bx % 8)))
1047 curbyte |= (1 << jx);
1058 if (ch >= huff_dynam_start) {
1059 sf_put(' '); sf_put(' '); sf_put(' ');
1062 else if (ch >= huff_abbrev_start) {
1066 /* 256, the string terminator, comes out as zero */
1072 if (compression_switch && jx) {
1078 if (size - origsize != compression_string_size)
1079 compiler_error("Compression string size mismatch.");
1083 /* (5) Output static arrays (if any). */
1085 /* We have to backpatch entries mentioned in staticarray_backpatch_table. */
1086 int32 size_before_arrays = size;
1088 for (ix=0, jx=0; ix<staticarray_backpatch_size; ix += 5) {
1089 backpatch_error_flag = FALSE;
1090 backpatch_marker = staticarray_backpatch_table[ix];
1091 /* datalen is always 4 for array backpatching */
1093 (staticarray_backpatch_table[ix+1] << 24)
1094 | (staticarray_backpatch_table[ix+2] << 16)
1095 | (staticarray_backpatch_table[ix+3] << 8)
1096 | (staticarray_backpatch_table[ix+4]);
1098 sf_put(static_array_area[jx]);
1103 /* Write out the converted value of the backpatch marker. */
1104 val = static_array_area[jx++];
1105 val = (val << 8) | static_array_area[jx++];
1106 val = (val << 8) | static_array_area[jx++];
1107 val = (val << 8) | static_array_area[jx++];
1108 val = backpatch_value(val);
1109 sf_put((val >> 24) & 0xFF);
1110 sf_put((val >> 16) & 0xFF);
1111 sf_put((val >> 8) & 0xFF);
1112 sf_put((val) & 0xFF);
1116 /* Flush out the last bit of static_array_area, after the last backpatch marker. */
1117 offset = static_array_area_size;
1119 sf_put(static_array_area[jx]);
1124 if (size_before_arrays + static_array_area_size != size)
1125 compiler_error("Static array output length did not match");
1128 /* (5.5) Output any null bytes (required to reach a GPAGESIZE address)
1131 while (size % GPAGESIZE) { sf_put(0); size++; }
1133 /* (6) Output RAM. */
1135 for (i=0; i<RAM_Size; i++)
1136 { sf_put(zmachine_paged_memory[i]); size++;
1139 if (ferror(sf_handle))
1140 fatalerror("I/O failure: couldn't write to story file");
1142 fseek(sf_handle, 32, SEEK_SET);
1143 fputc((checksum_long >> 24) & 0xFF, sf_handle);
1144 fputc((checksum_long >> 16) & 0xFF, sf_handle);
1145 fputc((checksum_long >> 8) & 0xFF, sf_handle);
1146 fputc((checksum_long) & 0xFF, sf_handle);
1148 if (ferror(sf_handle))
1149 fatalerror("I/O failure: couldn't backtrack on story file for checksum");
1151 /* Write a copy of the first 64 bytes into the debugging information file
1152 (mainly so that it can be used to identify which story file matches with
1153 which debugging info file). */
1155 if (debugfile_switch)
1156 { fseek(sf_handle, 0L, SEEK_SET);
1157 debug_file_printf("<story-file-prefix>");
1158 for (i = 0; i < 63; i += 3)
1159 { first_byte_of_triple = fgetc(sf_handle);
1160 second_byte_of_triple = fgetc(sf_handle);
1161 third_byte_of_triple = fgetc(sf_handle);
1162 debug_file_print_base_64_triple
1163 (first_byte_of_triple,
1164 second_byte_of_triple,
1165 third_byte_of_triple);
1167 debug_file_print_base_64_single(fgetc(sf_handle));
1168 debug_file_printf("</story-file-prefix>");
1174 { char settype_command[PATHLEN];
1175 sprintf(settype_command, "settype %s %s",
1176 new_name, riscos_file_type());
1177 system(settype_command);
1182 InformFiletypes (new_name, INF_MODULE_TYPE);
1184 InformFiletypes (new_name, INF_ZCODE_TYPE);
1188 extern void output_file(void)
1196 /* ------------------------------------------------------------------------- */
1197 /* Output the text transcript file (only called if there is to be one). */
1198 /* ------------------------------------------------------------------------- */
1200 FILE *transcript_file_handle; int transcript_open;
1202 extern void write_to_transcript_file(char *text, int linetype)
1204 if (TRANSCRIPT_FORMAT == 1) {
1211 case STRCTX_GAMEOPC:
1215 case STRCTX_VENEEROPC:
1217 case STRCTX_LOWSTRING:
1223 case STRCTX_OBJNAME:
1230 fputc(ch, transcript_file_handle);
1231 fputs(": ", transcript_file_handle);
1233 fputs(text, transcript_file_handle);
1234 fputc('\n', transcript_file_handle);
1237 extern void open_transcript_file(char *what_of)
1238 { char topline_buffer[256];
1240 transcript_file_handle = fopen(Transcript_Name,"w");
1241 if (transcript_file_handle==NULL)
1242 fatalerror_named("Couldn't open transcript file",
1245 transcript_open = TRUE;
1247 sprintf(topline_buffer, "Transcript of the text of \"%s\"", what_of);
1248 write_to_transcript_file(topline_buffer, STRCTX_INFO);
1249 sprintf(topline_buffer, "[From %s]", banner_line);
1250 write_to_transcript_file(topline_buffer, STRCTX_INFO);
1251 if (TRANSCRIPT_FORMAT == 1) {
1252 write_to_transcript_file("[I:info, G:game text, V:veneer text, L:lowmem string, A:abbreviation, D:dict word, O:object name, S:symbol, X:infix]", STRCTX_INFO);
1254 write_to_transcript_file("[H:game text inline in opcode, W:veneer text inline in opcode]", STRCTX_INFO);
1256 write_to_transcript_file("", STRCTX_INFO);
1259 extern void abort_transcript_file(void)
1260 { if (transcript_switch && transcript_open)
1261 fclose(transcript_file_handle);
1262 transcript_open = FALSE;
1265 extern void close_transcript_file(void)
1266 { char botline_buffer[256];
1269 write_serial_number(sn_buffer);
1270 sprintf(botline_buffer, "[End of transcript: release %d, serial %s]",
1271 release_number, sn_buffer);
1272 write_to_transcript_file("", STRCTX_INFO);
1273 write_to_transcript_file(botline_buffer, STRCTX_INFO);
1274 write_to_transcript_file("", STRCTX_INFO);
1276 if (ferror(transcript_file_handle))
1277 fatalerror("I/O failure: couldn't write to transcript file");
1278 fclose(transcript_file_handle);
1279 transcript_open = FALSE;
1282 { char settype_command[PATHLEN];
1283 sprintf(settype_command, "settype %s text",
1285 system(settype_command);
1289 InformFiletypes (Transcript_Name, INF_TEXT_TYPE);
1293 /* ------------------------------------------------------------------------- */
1294 /* Access to the debugging information file. */
1295 /* ------------------------------------------------------------------------- */
1297 static FILE *Debug_fp; /* Handle of debugging info file */
1299 static void open_debug_file(void)
1300 { Debug_fp=fopen(Debugging_Name,"wb");
1302 fatalerror_named("Couldn't open debugging information file",
1306 extern void nullify_debug_file_position(maybe_file_position *position) {
1307 position->valid = 0;
1310 static void close_debug_file(void)
1313 InformFiletypes (Debugging_Name, INF_DEBUG_TYPE);
1317 extern void begin_debug_file(void)
1318 { open_debug_file();
1320 debug_file_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
1321 debug_file_printf("<inform-story-file version=\"1.0\" ");
1322 debug_file_printf("content-creator=\"Inform\" ");
1324 ("content-creator-version=\"%d.%d%d\">",
1325 (VNUMBER / 100) % 10,
1326 (VNUMBER / 10) % 10,
1330 extern void debug_file_printf(const char*format, ...)
1331 { va_list argument_pointer;
1332 va_start(argument_pointer, format);
1333 vfprintf(Debug_fp, format, argument_pointer);
1334 va_end(argument_pointer);
1335 if (ferror(Debug_fp))
1336 { fatalerror("I/O failure: can't write to debugging information file");
1340 extern void debug_file_print_with_entities(const char*string)
1343 for (character = string[index]; character; character = string[++index])
1346 debug_file_printf(""");
1349 debug_file_printf("&");
1352 debug_file_printf("'");
1355 debug_file_printf("<");
1358 debug_file_printf(">");
1361 debug_file_printf("%c", character);
1367 static char base_64_digits[] =
1368 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1369 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
1370 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
1371 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
1372 '8', '9', '+', '/' };
1374 extern void debug_file_print_base_64_triple
1375 (uchar first, uchar second, uchar third)
1378 base_64_digits[first >> 2],
1379 base_64_digits[((first & 3) << 4) | (second >> 4)],
1380 base_64_digits[((second & 15) << 2) | (third >> 6)],
1381 base_64_digits[third & 63]);
1384 extern void debug_file_print_base_64_pair(uchar first, uchar second)
1387 base_64_digits[first >> 2],
1388 base_64_digits[((first & 3) << 4) | (second >> 4)],
1389 base_64_digits[(second & 15) << 2]);
1392 extern void debug_file_print_base_64_single(uchar first)
1395 base_64_digits[first >> 2],
1396 base_64_digits[(first & 3) << 4]);
1399 static void write_debug_location_internals(debug_location location)
1400 { debug_file_printf("<file-index>%d</file-index>", location.file_index - 1);
1402 ("<file-position>%d</file-position>", location.beginning_byte_index);
1404 ("<line>%d</line>", location.beginning_line_number);
1406 ("<character>%d</character>", location.beginning_character_number);
1407 if (location.beginning_byte_index != location.end_byte_index ||
1408 location.beginning_line_number != location.end_line_number ||
1409 location.beginning_character_number != location.end_character_number)
1411 ("<end-file-position>%d</end-file-position>",
1412 location.end_byte_index);
1414 ("<end-line>%d</end-line>", location.end_line_number);
1416 ("<end-character>%d</end-character>",
1417 location.end_character_number);
1421 static void write_debug_location_origsource_internals(debug_location location)
1423 ("<file-index>%d</file-index>", location.orig_file_index - 1);
1424 if (location.orig_beg_line_number)
1426 ("<line>%d</line>", location.orig_beg_line_number);
1427 if (location.orig_beg_char_number)
1429 ("<character>%d</character>", location.orig_beg_char_number);
1432 extern void write_debug_location(debug_location location)
1433 { if (location.file_index && location.file_index != 255)
1434 { debug_file_printf("<source-code-location>");
1435 write_debug_location_internals(location);
1436 debug_file_printf("</source-code-location>");
1438 if (location.orig_file_index)
1439 { debug_file_printf("<source-code-location>");
1440 write_debug_location_origsource_internals(location);
1441 debug_file_printf("</source-code-location>");
1445 extern void write_debug_locations(debug_locations locations)
1446 { if (locations.next)
1447 { const debug_locations*current = &locations;
1448 unsigned int index = 0;
1449 for (; current; current = current->next, ++index)
1450 { debug_file_printf("<source-code-location index=\"%d\">", index);
1451 write_debug_location_internals(current->location);
1452 debug_file_printf("</source-code-location>");
1454 if (locations.location.orig_file_index)
1455 { debug_file_printf("<source-code-location>");
1456 write_debug_location_origsource_internals(locations.location);
1457 debug_file_printf("</source-code-location>");
1461 { write_debug_location(locations.location);
1465 extern void write_debug_optional_identifier(int32 symbol_index)
1466 { if (symbols[symbol_index].type != ROUTINE_T)
1468 ("Attempt to write a replaceable identifier for a non-routine");
1470 if (symbol_debug_info[symbol_index].replacement_backpatch_pos.valid)
1473 &symbol_debug_info[symbol_index].replacement_backpatch_pos.position))
1474 { fatalerror("I/O failure: can't seek in debugging information file");
1477 ("<identifier artificial=\"true\">%s "
1478 "(superseded replacement)</identifier>",
1479 symbols[symbol_index].name);
1480 if (fseek(Debug_fp, 0L, SEEK_END))
1481 { fatalerror("I/O failure: can't seek in debugging information file");
1485 (Debug_fp, &symbol_debug_info[symbol_index].replacement_backpatch_pos.position);
1486 symbol_debug_info[symbol_index].replacement_backpatch_pos.valid = TRUE;
1487 debug_file_printf("<identifier>%s</identifier>", symbols[symbol_index].name);
1488 /* Space for: artificial="true" (superseded replacement) */
1489 debug_file_printf(" ");
1492 extern void write_debug_symbol_backpatch(int32 symbol_index)
1493 { if (symbol_debug_info[symbol_index].backpatch_pos.valid) {
1494 compiler_error("Symbol entry incorrectly reused in debug information "
1495 "file backpatching");
1497 fgetpos(Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position);
1498 symbol_debug_info[symbol_index].backpatch_pos.valid = TRUE;
1499 /* Reserve space for up to 10 digits plus a negative sign. */
1500 debug_file_printf("*BACKPATCH*");
1503 extern void write_debug_symbol_optional_backpatch(int32 symbol_index)
1504 { if (symbol_debug_info[symbol_index].backpatch_pos.valid) {
1505 compiler_error("Symbol entry incorrectly reused in debug information "
1506 "file backpatching");
1508 /* Reserve space for open and close value tags and up to 10 digits plus a
1509 negative sign, but take the backpatch position just inside the element,
1510 so that we'll be in the same case as above if the symbol is eventually
1512 debug_file_printf("<value>");
1513 fgetpos(Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position);
1514 symbol_debug_info[symbol_index].backpatch_pos.valid = TRUE;
1515 debug_file_printf("*BACKPATCH*</value>");
1518 static void write_debug_backpatch
1519 (debug_backpatch_accumulator *accumulator, int32 value)
1520 { if (accumulator->number_of_values_to_backpatch ==
1521 accumulator->number_of_available_backpatches)
1522 { my_realloc(&accumulator->values_and_backpatch_positions,
1523 sizeof(value_and_backpatch_position) *
1524 accumulator->number_of_available_backpatches,
1525 2 * sizeof(value_and_backpatch_position) *
1526 accumulator->number_of_available_backpatches,
1527 "values and debug information backpatch positions");
1528 accumulator->number_of_available_backpatches *= 2;
1530 accumulator->values_and_backpatch_positions
1531 [accumulator->number_of_values_to_backpatch].value = value;
1534 &accumulator->values_and_backpatch_positions
1535 [accumulator->number_of_values_to_backpatch].backpatch_position);
1536 ++(accumulator->number_of_values_to_backpatch);
1537 /* Reserve space for up to 10 digits plus a negative sign. */
1538 debug_file_printf("*BACKPATCH*");
1541 extern void write_debug_object_backpatch(int32 object_number)
1543 { write_debug_backpatch(&object_backpatch_accumulator, object_number - 1);
1546 { debug_file_printf("%d", object_number);
1550 static int32 backpatch_object_address(int32 index)
1551 { return object_tree_offset + OBJECT_BYTE_LENGTH * index;
1554 extern void write_debug_packed_code_backpatch(int32 offset)
1555 { write_debug_backpatch(&packed_code_backpatch_accumulator, offset);
1558 static int32 backpatch_packed_code_address(int32 offset)
1560 if (OMIT_UNUSED_ROUTINES) {
1562 offset = df_stripped_offset_for_code_offset(offset, &stripped);
1566 return (code_offset + offset) / scale_factor;
1569 extern void write_debug_code_backpatch(int32 offset)
1570 { write_debug_backpatch(&code_backpatch_accumulator, offset);
1573 static int32 backpatch_code_address(int32 offset)
1575 if (OMIT_UNUSED_ROUTINES) {
1577 offset = df_stripped_offset_for_code_offset(offset, &stripped);
1581 return code_offset + offset;
1584 extern void write_debug_global_backpatch(int32 offset)
1585 { write_debug_backpatch(&global_backpatch_accumulator, offset);
1588 static int32 backpatch_global_address(int32 offset)
1589 { return variables_offset + WORDSIZE * (offset - MAX_LOCAL_VARIABLES);
1592 extern void write_debug_array_backpatch(int32 offset)
1593 { write_debug_backpatch(&array_backpatch_accumulator, offset);
1596 static int32 backpatch_array_address(int32 offset)
1597 { return (glulx_mode ? arrays_offset : variables_offset) + offset;
1600 extern void write_debug_grammar_backpatch(int32 offset)
1601 { write_debug_backpatch(&grammar_backpatch_accumulator, offset);
1604 static int32 backpatch_grammar_address(int32 offset)
1605 { return grammar_table_offset + offset;
1608 extern void begin_writing_debug_sections()
1609 { debug_file_printf("<story-file-section>");
1610 debug_file_printf("<type>header</type>");
1611 debug_file_printf("<address>0</address>");
1614 extern void write_debug_section(const char*name, int32 beginning_address)
1615 { debug_file_printf("<end-address>%d</end-address>", beginning_address);
1616 debug_file_printf("</story-file-section>");
1617 debug_file_printf("<story-file-section>");
1618 debug_file_printf("<type>");
1619 debug_file_print_with_entities(name);
1620 debug_file_printf("</type>");
1621 debug_file_printf("<address>%d</address>", beginning_address);
1624 extern void end_writing_debug_sections(int32 end_address)
1625 { debug_file_printf("<end-address>%d</end-address>", end_address);
1626 debug_file_printf("</story-file-section>");
1629 extern void write_debug_undef(int32 symbol_index)
1630 { if (!symbol_debug_info[symbol_index].backpatch_pos.valid)
1632 ("Attempt to erase debugging information never written or since "
1635 if (symbols[symbol_index].type != CONSTANT_T)
1637 ("Attempt to erase debugging information for a non-constant "
1638 "because of an #undef");
1641 (Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position))
1642 { fatalerror("I/O failure: can't seek in debugging information file");
1644 /* There are 7 characters in ``<value>''. */
1645 if (fseek(Debug_fp, -7L, SEEK_CUR))
1646 { fatalerror("I/O failure: can't seek in debugging information file");
1648 /* Overwrite: <value>*BACKPATCH*</value> */
1649 debug_file_printf(" ");
1650 nullify_debug_file_position
1651 (&symbol_debug_info[symbol_index].backpatch_pos);
1652 if (fseek(Debug_fp, 0L, SEEK_END))
1653 { fatalerror("I/O failure: can't seek in debugging information file");
1657 static void apply_debug_information_backpatches
1658 (debug_backpatch_accumulator *accumulator)
1659 { int32 backpatch_index, backpatch_value;
1660 for (backpatch_index = accumulator->number_of_values_to_backpatch;
1664 &accumulator->values_and_backpatch_positions
1665 [backpatch_index].backpatch_position))
1667 ("I/O failure: can't seek in debugging information file");
1670 (*accumulator->backpatching_function)
1671 (accumulator->values_and_backpatch_positions
1672 [backpatch_index].value);
1674 ("%11d", /* Space for up to 10 digits plus a negative sign. */
1679 static void apply_debug_information_symbol_backpatches()
1680 { int backpatch_symbol;
1681 for (backpatch_symbol = no_symbols; backpatch_symbol--;)
1682 { if (symbol_debug_info[backpatch_symbol].backpatch_pos.valid)
1683 { if (fsetpos(Debug_fp,
1684 &symbol_debug_info[backpatch_symbol].backpatch_pos.position))
1686 ("I/O failure: can't seek in debugging information file");
1688 debug_file_printf("%11d", symbols[backpatch_symbol].value);
1693 static void write_debug_system_constants()
1694 { int *system_constant_list =
1695 glulx_mode ? glulx_system_constant_list : z_system_constant_list;
1696 int system_constant_index = 0;
1698 /* Store system constants. */
1699 for (; system_constant_list[system_constant_index] != -1;
1700 ++system_constant_index)
1701 { int system_constant = system_constant_list[system_constant_index];
1702 debug_file_printf("<constant>");
1704 ("<identifier>#%s</identifier>",
1705 system_constants.keywords[system_constant]);
1707 ("<value>%d</value>",
1708 value_of_system_constant(system_constant));
1709 debug_file_printf("</constant>");
1713 extern void end_debug_file()
1714 { write_debug_system_constants();
1715 debug_file_printf("</inform-story-file>\n");
1718 { apply_debug_information_backpatches(&object_backpatch_accumulator);
1720 { apply_debug_information_backpatches(&packed_code_backpatch_accumulator);
1722 apply_debug_information_backpatches(&code_backpatch_accumulator);
1723 apply_debug_information_backpatches(&global_backpatch_accumulator);
1724 apply_debug_information_backpatches(&array_backpatch_accumulator);
1725 apply_debug_information_backpatches(&grammar_backpatch_accumulator);
1727 apply_debug_information_symbol_backpatches();
1732 /* ========================================================================= */
1733 /* Data structure management routines */
1734 /* ------------------------------------------------------------------------- */
1736 extern void init_files_vars(void)
1737 { malloced_bytes = 0;
1738 checksum_low_byte = 0; /* Z-code */
1739 checksum_high_byte = 0;
1740 checksum_long = 0; /* Glulx */
1742 transcript_open = FALSE;
1745 extern void files_begin_prepass(void)
1748 total_input_files = 0;
1749 current_input_file = 0;
1750 current_origsource_file = 0;
1753 extern void files_begin_pass(void)
1754 { total_chars_read=0;
1757 static void initialise_accumulator
1758 (debug_backpatch_accumulator *accumulator,
1759 int32 (* backpatching_function)(int32))
1760 { accumulator->number_of_values_to_backpatch = 0;
1761 accumulator->number_of_available_backpatches =
1762 INITIAL_DEBUG_INFORMATION_BACKPATCH_ALLOCATION;
1763 accumulator->values_and_backpatch_positions =
1765 (sizeof(value_and_backpatch_position) *
1766 accumulator->number_of_available_backpatches,
1767 "values and debug information backpatch positions");
1768 accumulator->backpatching_function = backpatching_function;
1771 extern void files_allocate_arrays(void)
1773 initialise_memory_list(&InputFiles_memlist,
1774 sizeof(FileId), 16, (void**)&InputFiles,
1775 "input file storage");
1776 if (debugfile_switch)
1778 { initialise_accumulator
1779 (&object_backpatch_accumulator, &backpatch_object_address);
1781 { initialise_accumulator
1782 (&packed_code_backpatch_accumulator,
1783 &backpatch_packed_code_address);
1785 initialise_accumulator
1786 (&code_backpatch_accumulator, &backpatch_code_address);
1787 initialise_accumulator
1788 (&global_backpatch_accumulator, &backpatch_global_address);
1789 initialise_accumulator
1790 (&array_backpatch_accumulator, &backpatch_array_address);
1791 initialise_accumulator
1792 (&grammar_backpatch_accumulator, &backpatch_grammar_address);
1796 static void tear_down_accumulator(debug_backpatch_accumulator *accumulator)
1798 (&(accumulator->values_and_backpatch_positions),
1799 "values and debug information backpatch positions");
1802 extern void files_free_arrays(void)
1805 for (ix=0; ix<total_files; ix++)
1807 my_free(&InputFiles[ix].filename, "filename storage");
1809 deallocate_memory_list(&InputFiles_memlist);
1811 if (debugfile_switch)
1813 { tear_down_accumulator(&object_backpatch_accumulator);
1815 { tear_down_accumulator(&packed_code_backpatch_accumulator);
1817 tear_down_accumulator(&code_backpatch_accumulator);
1818 tear_down_accumulator(&global_backpatch_accumulator);
1819 tear_down_accumulator(&array_backpatch_accumulator);
1820 tear_down_accumulator(&grammar_backpatch_accumulator);
1824 /* ========================================================================= */