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.31 */
11
/* copyright (c) Graham Nelson 1993 - 2006 */
13
/* ------------------------------------------------------------------------- */
17
int input_file; /* Number of source files so far */
19
int32 total_chars_read; /* Characters read in (from all
20
source files put together) */
22
static int checksum_low_byte, /* For calculating the Z-machine's */
23
checksum_high_byte; /* "verify" checksum */
25
static int32 checksum_long; /* For the Glulx checksum, */
26
static int checksum_count; /* similarly */
28
/* ------------------------------------------------------------------------- */
29
/* Most of the information about source files is kept by "lexer.c"; this */
30
/* level is only concerned with file names and handles. */
31
/* ------------------------------------------------------------------------- */
33
FileId *InputFiles=NULL; /* Ids for all the source files */
34
static char *filename_storage, /* Translated filenames */
36
static int filename_storage_left;
38
/* ------------------------------------------------------------------------- */
39
/* File handles and names for temporary files. */
40
/* ------------------------------------------------------------------------- */
42
FILE *Temp1_fp=NULL, *Temp2_fp=NULL, *Temp3_fp=NULL;
43
char Temp1_Name[PATHLEN], Temp2_Name[PATHLEN], Temp3_Name[PATHLEN];
45
/* ------------------------------------------------------------------------- */
46
/* Opening and closing source code files */
47
/* ------------------------------------------------------------------------- */
49
extern void load_sourcefile(char *filename_given, int same_directory_flag)
51
/* Meaning: open a new file of Inform source. (The lexer picks up on
52
this by noticing that input_file has increased.) */
54
char name[PATHLEN]; int x = 0; FILE *handle;
56
if (input_file == MAX_SOURCE_FILES)
57
memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
60
{ x = translate_in_filename(x, name, filename_given, same_directory_flag,
62
handle = fopen(name,"r");
63
} while ((handle == NULL) && (x != 0));
65
if (filename_storage_left <= (int)strlen(name))
66
memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
68
filename_storage_left -= strlen(name)+1;
69
strcpy(filename_storage_p, name);
70
InputFiles[input_file].filename = filename_storage_p;
72
filename_storage_p += strlen(name)+1;
75
{ write_debug_byte(FILE_DBR); write_debug_byte(input_file + 1);
76
write_debug_string(filename_given);
77
write_debug_string(name);
80
InputFiles[input_file].handle = handle;
81
if (InputFiles[input_file].handle==NULL)
82
fatalerror_named("Couldn't open source file", name);
84
if (line_trace_level > 0) printf("\nOpening file \"%s\"\n",name);
89
static void close_sourcefile(int file_number)
91
if (InputFiles[file_number-1].handle == NULL) return;
93
/* Close this file. */
95
if (ferror(InputFiles[file_number-1].handle))
96
fatalerror_named("I/O failure: couldn't read from source file",
97
InputFiles[file_number-1].filename);
99
fclose(InputFiles[file_number-1].handle);
101
InputFiles[file_number-1].handle = NULL;
103
if (line_trace_level > 0) printf("\nClosing file\n");
106
extern void close_all_source(void)
108
for (i=0; i<input_file; i++) close_sourcefile(i+1);
111
/* ------------------------------------------------------------------------- */
112
/* Feeding source code up into the lexical analyser's buffer */
113
/* (see "lexer.c" for its specification) */
114
/* ------------------------------------------------------------------------- */
116
extern int file_load_chars(int file_number, char *buffer, int length)
118
int read_in; FILE *handle;
120
if (file_number-1 > input_file)
121
{ buffer[0] = 0; return 1; }
123
handle = InputFiles[file_number-1].handle;
125
{ buffer[0] = 0; return 1; }
127
read_in = fread(buffer, 1, length, handle);
128
total_chars_read += read_in;
130
if (read_in == length) return length;
132
close_sourcefile(file_number);
134
if (file_number == 1)
135
{ buffer[read_in] = 0;
136
buffer[read_in+1] = 0;
137
buffer[read_in+2] = 0;
138
buffer[read_in+3] = 0;
141
{ buffer[read_in] = '\n';
142
buffer[read_in+1] = ' ';
143
buffer[read_in+2] = ' ';
144
buffer[read_in+3] = ' ';
147
return(-(read_in+4));
150
/* ------------------------------------------------------------------------- */
151
/* Final assembly and output of the story file/module. */
152
/* ------------------------------------------------------------------------- */
156
static void sf_put(int c)
160
/* The checksum is the unsigned sum mod 65536 of the bytes in the
161
story file from 0x0040 (first byte after header) to the end.
163
The link data does not contribute to the checksum of a module. */
165
checksum_low_byte += c;
166
if (checksum_low_byte>=256)
167
{ checksum_low_byte-=256;
168
if (++checksum_high_byte==256) checksum_high_byte=0;
174
/* The checksum is the unsigned 32-bit sum of the entire story file,
175
considered as a list of 32-bit words, with the checksum field
178
switch (checksum_count) {
180
checksum_long += (((int32)(c & 0xFF)) << 24);
183
checksum_long += (((int32)(c & 0xFF)) << 16);
186
checksum_long += (((int32)(c & 0xFF)) << 8);
189
checksum_long += ((int32)(c & 0xFF));
193
checksum_count = (checksum_count+1) & 3;
200
/* Recursive procedure to generate the Glulx compression table. */
202
static void output_compression(int entnum, int32 *size)
204
huffentity_t *ent = &(huff_entities[entnum]);
213
val = Write_Strings_At + huff_entities[ent->u.branch[0]].addr;
214
sf_put((val >> 24) & 0xFF);
215
sf_put((val >> 16) & 0xFF);
216
sf_put((val >> 8) & 0xFF);
217
sf_put((val) & 0xFF);
219
val = Write_Strings_At + huff_entities[ent->u.branch[1]].addr;
220
sf_put((val >> 24) & 0xFF);
221
sf_put((val >> 16) & 0xFF);
222
sf_put((val >> 8) & 0xFF);
223
sf_put((val) & 0xFF);
225
output_compression(ent->u.branch[0], size);
226
output_compression(ent->u.branch[1], size);
236
cx = (char *)abbreviations_at + ent->u.val*MAX_ABBREV_LENGTH;
246
val = abbreviations_offset + 4 + ent->u.val*4;
247
sf_put((val >> 24) & 0xFF);
248
sf_put((val >> 16) & 0xFF);
249
sf_put((val >> 8) & 0xFF);
250
sf_put((val) & 0xFF);
256
static void output_file_z(void)
257
{ FILE *fin; char new_name[PATHLEN];
258
int32 length, blanks=0, size, i, j;
262
/* At this point, construct_storyfile() has just been called. */
264
/* Enter the length information into the header. */
266
length=((int32) Write_Strings_At) + static_strings_extent;
267
if (module_switch) length += link_data_size +
268
zcode_backpatch_size +
269
zmachine_backpatch_size;
271
while ((length%length_scale_factor)!=0) { length++; blanks++; }
272
length=length/length_scale_factor;
273
zmachine_paged_memory[26]=(length & 0xff00)/0x100;
274
zmachine_paged_memory[27]=(length & 0xff);
276
/* To assist interpreters running a paged virtual memory system, Inform
277
writes files which are padded with zeros to the next multiple of
278
0.5K. This calculates the number of bytes of padding needed: */
280
while (((length_scale_factor*length)+blanks-1)%512 != 511) blanks++;
282
translate_out_filename(new_name, Code_Name);
284
sf_handle = fopen(new_name,"wb");
285
if (sf_handle == NULL)
286
fatalerror_named("Couldn't open output file", new_name);
289
/* Set the type and creator to Andrew Plotkin's MaxZip, a popular
290
Z-code interpreter on the Macintosh */
292
if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
295
/* (1) Output the paged memory. */
298
fputc(zmachine_paged_memory[i], sf_handle);
300
checksum_low_byte = 0;
301
checksum_high_byte = 0;
303
for (i=64; i<Write_Code_At; i++)
304
{ sf_put(zmachine_paged_memory[i]); size++;
307
/* (2) Output the compiled code area. */
309
if (temporary_files_switch)
311
fin=fopen(Temp2_Name,"rb");
313
fatalerror("I/O failure: couldn't reopen temporary file 2");
318
for (i=0; i<zcode_backpatch_size; i=i+3)
319
{ int long_flag = TRUE;
321
= 256*read_byte_from_memory_block(&zcode_backpatch_table, i+1)
322
+ read_byte_from_memory_block(&zcode_backpatch_table, i+2);
323
backpatch_error_flag = FALSE;
325
= read_byte_from_memory_block(&zcode_backpatch_table, i);
326
if (backpatch_marker >= 0x80) long_flag = FALSE;
327
backpatch_marker &= 0x7f;
328
offset = offset + (backpatch_marker/32)*0x10000;
329
while (offset+0x30000 < j) {
331
long_flag = !long_flag;
333
backpatch_marker &= 0x1f;
336
sf_put((temporary_files_switch)?fgetc(fin):
337
read_byte_from_memory_block(&zcode_area, j));
342
{ int32 v = (temporary_files_switch)?fgetc(fin):
343
read_byte_from_memory_block(&zcode_area, j);
344
v = 256*v + ((temporary_files_switch)?fgetc(fin):
345
read_byte_from_memory_block(&zcode_area, j+1));
346
v = backpatch_value(v);
347
sf_put(v/256); sf_put(v%256);
351
{ int32 v = (temporary_files_switch)?fgetc(fin):
352
read_byte_from_memory_block(&zcode_area, j);
353
v = backpatch_value(v);
358
if (backpatch_error_flag)
359
{ printf("*** %s zcode offset=%08lx backpatch offset=%08lx ***\n",
360
(long_flag)?"long":"short", (long int) j, (long int) i);
364
while (j<zmachine_pc)
366
sf_put((temporary_files_switch)?fgetc(fin):
367
read_byte_from_memory_block(&zcode_area, j));
371
if (temporary_files_switch)
373
fatalerror("I/O failure: couldn't read from temporary file 2");
377
/* (3) Output any null bytes (required to reach a packed address)
378
before the strings area. */
380
while (size<Write_Strings_At) { sf_put(0); size++; }
382
/* (4) Output the static strings area. */
384
if (temporary_files_switch)
386
fin=fopen(Temp1_Name,"rb");
388
fatalerror("I/O failure: couldn't reopen temporary file 1");
389
for (i=0; i<static_strings_extent; i++) sf_put(fgetc(fin));
391
fatalerror("I/O failure: couldn't read from temporary file 1");
393
remove(Temp1_Name); remove(Temp2_Name);
396
for (i=0; i<static_strings_extent; i++) {
397
sf_put(read_byte_from_memory_block(&static_strings_area,i));
401
/* (5) Output the linking data table (in the case of a module). */
403
if (temporary_files_switch)
406
fin=fopen(Temp3_Name,"rb");
408
fatalerror("I/O failure: couldn't reopen temporary file 3");
409
for (j=0; j<link_data_size; j++) sf_put(fgetc(fin));
411
fatalerror("I/O failure: couldn't read from temporary file 3");
418
for (i=0; i<link_data_size; i++)
419
sf_put(read_byte_from_memory_block(&link_data_area,i));
422
{ for (i=0; i<zcode_backpatch_size; i++)
423
sf_put(read_byte_from_memory_block(&zcode_backpatch_table, i));
424
for (i=0; i<zmachine_backpatch_size; i++)
425
sf_put(read_byte_from_memory_block(&zmachine_backpatch_table, i));
428
/* (6) Output null bytes to reach a multiple of 0.5K. */
430
while (blanks>0) { sf_put(0); blanks--; }
432
if (ferror(sf_handle))
433
fatalerror("I/O failure: couldn't write to story file");
435
fseek(sf_handle, 28, SEEK_SET);
436
fputc(checksum_high_byte, sf_handle);
437
fputc(checksum_low_byte, sf_handle);
439
if (ferror(sf_handle))
440
fatalerror("I/O failure: couldn't backtrack on story file for checksum");
444
/* Write a copy of the header into the debugging information file
445
(mainly so that it can be used to identify which story file matches
446
with which debugging info file) */
448
if (debugfile_switch)
449
{ write_debug_byte(HEADER_DBR);
451
{ if (i==28) write_debug_byte(checksum_high_byte);
452
else if (i==29) write_debug_byte(checksum_low_byte);
453
else write_debug_byte((int) (zmachine_paged_memory[i]));
458
{ char settype_command[PATHLEN];
459
sprintf(settype_command, "settype %s %s",
460
new_name, riscos_file_type());
461
system(settype_command);
466
InformFiletypes (new_name, INF_MODULE_TYPE);
468
InformFiletypes (new_name, INF_ZCODE_TYPE);
472
static void output_file_g(void)
473
{ FILE *fin; char new_name[PATHLEN];
478
/* At this point, construct_storyfile() has just been called. */
480
translate_out_filename(new_name, Code_Name);
482
sf_handle = fopen(new_name,"wb");
483
if (sf_handle == NULL)
484
fatalerror_named("Couldn't open output file", new_name);
487
/* Set the type and creator to Andrew Plotkin's MaxZip, a popular
488
Z-code interpreter on the Macintosh */
490
if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
496
/* (1) Output the header. We use sf_put here, instead of fputc,
497
because the header is included in the checksum. */
504
/* Version number -- 0x00020000 for now. */
510
sf_put((Write_RAM_At >> 24));
511
sf_put((Write_RAM_At >> 16));
512
sf_put((Write_RAM_At >> 8));
513
sf_put((Write_RAM_At));
514
/* EXTSTART, or game file size */
515
sf_put((Out_Size >> 24));
516
sf_put((Out_Size >> 16));
517
sf_put((Out_Size >> 8));
519
/* ENDMEM, which is also game file size */
520
sf_put((Out_Size >> 24));
521
sf_put((Out_Size >> 16));
522
sf_put((Out_Size >> 8));
524
/* STACKSIZE, which we guess at 4096. That's about enough for 90
525
nested function calls with 8 locals each -- the same capacity
526
as the Z-Spec's suggestion for Z-machine stack size. */
531
/* Initial function to call. Inform sets things up so that this
532
is the start of the executable-code area. */
533
sf_put((Write_Code_At >> 24));
534
sf_put((Write_Code_At >> 16));
535
sf_put((Write_Code_At >> 8));
536
sf_put((Write_Code_At));
537
/* String-encoding table. */
538
sf_put((Write_Strings_At >> 24));
539
sf_put((Write_Strings_At >> 16));
540
sf_put((Write_Strings_At >> 8));
541
sf_put((Write_Strings_At));
542
/* Checksum -- zero for the moment. */
548
size = GLULX_HEADER_SIZE;
550
/* (1a) Output the eight-byte memory layout identifier. */
552
sf_put('I'); sf_put('n'); sf_put('f'); sf_put('o');
553
sf_put(0); sf_put(1); sf_put(0); sf_put(0);
555
/* (1b) Output the rest of the Inform-specific data. */
557
/* Inform version number */
558
sf_put('0' + ((RELEASE_NUMBER/100)%10));
560
sf_put('0' + ((RELEASE_NUMBER/10)%10));
561
sf_put('0' + RELEASE_NUMBER%10);
562
/* Glulx back-end version number */
563
sf_put('0' + ((GLULX_RELEASE_NUMBER/100)%10));
565
sf_put('0' + ((GLULX_RELEASE_NUMBER/10)%10));
566
sf_put('0' + GLULX_RELEASE_NUMBER%10);
567
/* Game release number */
568
sf_put((release_number>>8) & 0xFF);
569
sf_put(release_number & 0xFF);
570
/* Game serial number */
573
write_serial_number(serialnum);
575
sf_put(serialnum[i]);
577
size += GLULX_STATIC_ROM_SIZE;
579
/* (2) Output the compiled code area. */
581
if (temporary_files_switch)
583
fin=fopen(Temp2_Name,"rb");
585
fatalerror("I/O failure: couldn't reopen temporary file 2");
590
for (i=0; i<zcode_backpatch_size; i=i+6) {
594
(read_byte_from_memory_block(&zcode_backpatch_table, i+2) << 24)
595
| (read_byte_from_memory_block(&zcode_backpatch_table, i+3) << 16)
596
| (read_byte_from_memory_block(&zcode_backpatch_table, i+4) << 8)
597
| (read_byte_from_memory_block(&zcode_backpatch_table, i+5));
598
backpatch_error_flag = FALSE;
600
read_byte_from_memory_block(&zcode_backpatch_table, i);
602
read_byte_from_memory_block(&zcode_backpatch_table, i+1);
606
sf_put((temporary_files_switch)?fgetc(fin):
607
read_byte_from_memory_block(&zcode_area, j));
614
v = ((temporary_files_switch)?fgetc(fin):
615
read_byte_from_memory_block(&zcode_area, j));
616
v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
617
read_byte_from_memory_block(&zcode_area, j+1));
618
v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
619
read_byte_from_memory_block(&zcode_area, j+2));
620
v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
621
read_byte_from_memory_block(&zcode_area, j+3));
622
v = backpatch_value(v);
623
sf_put((v >> 24) & 0xFF);
624
sf_put((v >> 16) & 0xFF);
625
sf_put((v >> 8) & 0xFF);
632
v = ((temporary_files_switch)?fgetc(fin):
633
read_byte_from_memory_block(&zcode_area, j));
634
v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
635
read_byte_from_memory_block(&zcode_area, j+1));
636
v = backpatch_value(v);
638
printf("*** backpatch value does not fit ***\n");
639
backpatch_error_flag = TRUE;
641
sf_put((v >> 8) & 0xFF);
648
v = ((temporary_files_switch)?fgetc(fin):
649
read_byte_from_memory_block(&zcode_area, j));
650
v = backpatch_value(v);
652
printf("*** backpatch value does not fit ***\n");
653
backpatch_error_flag = TRUE;
661
printf("*** unknown backpatch data len = %d ***\n",
663
backpatch_error_flag = TRUE;
666
if (backpatch_error_flag) {
667
printf("*** %d bytes zcode offset=%08lx backpatch offset=%08lx ***\n",
668
data_len, (long int) j, (long int) i);
672
while (j<zmachine_pc)
674
sf_put((temporary_files_switch)?fgetc(fin):
675
read_byte_from_memory_block(&zcode_area, j));
679
if (temporary_files_switch)
681
fatalerror("I/O failure: couldn't read from temporary file 2");
685
/* (4) Output the static strings area. */
687
if (temporary_files_switch) {
688
fseek(Temp1_fp, 0, SEEK_SET);
692
int ch, jx, curbyte, bx;
699
if (compression_switch) {
701
/* The 12-byte table header. */
702
lx = compression_table_size;
703
sf_put((lx >> 24) & 0xFF);
704
sf_put((lx >> 16) & 0xFF);
705
sf_put((lx >> 8) & 0xFF);
708
sf_put((no_huff_entities >> 24) & 0xFF);
709
sf_put((no_huff_entities >> 16) & 0xFF);
710
sf_put((no_huff_entities >> 8) & 0xFF);
711
sf_put((no_huff_entities) & 0xFF);
713
lx = Write_Strings_At + 12;
714
sf_put((lx >> 24) & 0xFF);
715
sf_put((lx >> 16) & 0xFF);
716
sf_put((lx >> 8) & 0xFF);
720
output_compression(huff_entity_root, &size);
723
if (size - origsize != compression_table_size)
724
compiler_error("Compression table size mismatch.");
728
for (lx=0, ix=0; lx<no_strings; lx++) {
729
int escapelen=0, escapetype=0;
732
if (compression_switch)
733
sf_put(0xE1); /* type byte -- compressed string */
735
sf_put(0xE0); /* type byte -- non-compressed string */
740
if (temporary_files_switch)
741
ch = fgetc(Temp1_fp);
743
ch = read_byte_from_memory_block(&static_strings_area, ix);
745
if (ix > static_strings_extent || ch < 0)
746
compiler_error("Read too much not-yet-compressed text.");
748
if (escapelen == -1) {
753
else if (ch == '0') {
756
else if (ch == 'A' || ch == 'D') {
763
compiler_error("Strange @ escape in processed text.");
766
else if (escapelen) {
767
escapeval = (escapeval << 4) | ((ch-'A') & 0x0F);
769
if (escapelen == 0) {
770
if (escapetype == 'A') {
771
ch = huff_abbrev_start+escapeval;
773
else if (escapetype == 'D') {
774
ch = huff_dynam_start+escapeval;
777
compiler_error("Strange @ escape in processed text.");
794
if (compression_switch) {
795
bits = &(huff_entities[ch].bits);
796
depth = huff_entities[ch].depth;
797
for (bx=0; bx<depth; bx++) {
798
if (bits->b[bx / 8] & (1 << (bx % 8)))
799
curbyte |= (1 << jx);
810
if (ch >= huff_dynam_start) {
811
sf_put(' '); sf_put(' '); sf_put(' ');
814
else if (ch >= huff_abbrev_start) {
818
/* 256, the string terminator, comes out as zero */
824
if (compression_switch && jx) {
830
if (size - origsize != compression_string_size)
831
compiler_error("Compression string size mismatch.");
835
/* (4.5) Output any null bytes (required to reach a GPAGESIZE address)
838
while (size % GPAGESIZE) { sf_put(0); size++; }
840
/* (5) Output RAM. */
842
for (i=0; i<RAM_Size; i++)
843
{ sf_put(zmachine_paged_memory[i]); size++;
846
if (ferror(sf_handle))
847
fatalerror("I/O failure: couldn't write to story file");
849
fseek(sf_handle, 32, SEEK_SET);
850
fputc((checksum_long >> 24) & 0xFF, sf_handle);
851
fputc((checksum_long >> 16) & 0xFF, sf_handle);
852
fputc((checksum_long >> 8) & 0xFF, sf_handle);
853
fputc((checksum_long) & 0xFF, sf_handle);
855
if (ferror(sf_handle))
856
fatalerror("I/O failure: couldn't backtrack on story file for checksum");
861
{ char settype_command[PATHLEN];
862
sprintf(settype_command, "settype %s %s",
863
new_name, riscos_file_type());
864
system(settype_command);
869
InformFiletypes (new_name, INF_MODULE_TYPE);
871
InformFiletypes (new_name, INF_ZCODE_TYPE);
875
extern void output_file(void)
883
/* ------------------------------------------------------------------------- */
884
/* Output the text transcript file (only called if there is to be one). */
885
/* ------------------------------------------------------------------------- */
887
FILE *transcript_file_handle; int transcript_open;
889
extern void write_to_transcript_file(char *text)
890
{ fputs(text, transcript_file_handle);
891
fputc('\n', transcript_file_handle);
894
extern void open_transcript_file(char *what_of)
895
{ char topline_buffer[256];
897
transcript_file_handle = fopen(Transcript_Name,"w");
898
if (transcript_file_handle==NULL)
899
fatalerror_named("Couldn't open transcript file",
902
transcript_open = TRUE;
904
sprintf(topline_buffer, "Transcript of the text of \"%s\"\n\
905
[From %s]\n", what_of, banner_line);
906
write_to_transcript_file(topline_buffer);
909
extern void abort_transcript_file(void)
910
{ if (transcript_switch && transcript_open)
911
fclose(transcript_file_handle);
912
transcript_open = FALSE;
915
extern void close_transcript_file(void)
916
{ char botline_buffer[256];
919
write_serial_number(sn_buffer);
920
sprintf(botline_buffer, "\n[End of transcript: release %d.%s]\n",
921
release_number, sn_buffer);
922
write_to_transcript_file(botline_buffer);
924
if (ferror(transcript_file_handle))
925
fatalerror("I/O failure: couldn't write to transcript file");
926
fclose(transcript_file_handle);
927
transcript_open = FALSE;
930
{ char settype_command[PATHLEN];
931
sprintf(settype_command, "settype %s text",
933
system(settype_command);
937
InformFiletypes (Transcript_Name, INF_TEXT_TYPE);
941
/* ------------------------------------------------------------------------- */
942
/* Access to the debugging information file. */
943
/* ------------------------------------------------------------------------- */
945
static FILE *Debug_fp; /* Handle of debugging info file */
947
extern void open_debug_file(void)
948
{ Debug_fp=fopen(Debugging_Name,"wb");
950
fatalerror_named("Couldn't open debugging information file",
954
extern void close_debug_file(void)
955
{ fputc(EOF_DBR, Debug_fp);
956
if (ferror(Debug_fp))
957
fatalerror("I/O failure: can't write to debugging info file");
960
InformFiletypes (Debugging_Name, INF_DEBUG_TYPE);
964
extern void write_debug_byte(int i)
966
/* All output to the debugging file is funneled through this routine */
969
if (ferror(Debug_fp))
970
fatalerror("I/O failure: can't write to debugging info file");
973
extern void write_debug_string(char *s)
975
/* Write a null-terminated string into the debugging file. */
978
for (i=0; s[i]!=0; i++)
979
write_debug_byte((int) s[i]);
983
extern void write_debug_address(int32 i)
985
/* Write a 3-byte address (capable of being a byte address in a story
986
file whose size may be as much as 512K) into the debugging file.
987
Also used for character positions in source files. */
989
write_debug_byte((int)((i/256)/256));
990
write_debug_byte((int)((i/256)%256));
991
write_debug_byte((int)(i%256));
994
/* ------------------------------------------------------------------------- */
995
/* There is a standard four-byte format to express code line refs in the */
996
/* debugging file: if X is a dbgl, */
998
/* X.b1 = file number (input files to Inform are numbered from 1 in */
999
/* order of being opened) */
1000
/* X.b2, X.b3 = high byte, low byte of line in this file (numbered */
1002
/* X.cc = character position in current line */
1003
/* ------------------------------------------------------------------------- */
1005
extern void write_dbgl(dbgl x)
1006
{ write_debug_byte(x.b1);
1007
write_debug_byte(x.b2); write_debug_byte(x.b3);
1008
write_debug_byte(x.cc);
1011
extern void begin_debug_file(void)
1012
{ open_debug_file();
1014
/* DEBF == Debugging File (sorry) */
1015
write_debug_byte(0xDE); write_debug_byte(0xBF);
1017
/* Debugging file format version number */
1018
write_debug_byte(0); write_debug_byte(0);
1020
/* Identify ourselves */
1021
write_debug_byte(VNUMBER/256); write_debug_byte(VNUMBER%256);
1024
/* ------------------------------------------------------------------------- */
1025
/* Temporary storage files: */
1027
/* Temp file 1 is used to hold the static strings area, as compiled */
1028
/* 2 to hold compiled routines of Z-code */
1029
/* 3 to hold the link data table (but only for modules) */
1031
/* (Though annoying, this procedure typically saves about 200K of memory, */
1032
/* an important point for Amiga and sub-386 PC users of Inform) */
1033
/* ------------------------------------------------------------------------- */
1035
extern void open_temporary_files(void)
1036
{ translate_temp_filename(1);
1037
Temp1_fp=fopen(Temp1_Name,"wb");
1038
if (Temp1_fp==NULL) fatalerror_named("Couldn't open temporary file 1",
1040
translate_temp_filename(2);
1041
Temp2_fp=fopen(Temp2_Name,"wb");
1042
if (Temp2_fp==NULL) fatalerror_named("Couldn't open temporary file 2",
1045
if (!module_switch) return;
1046
translate_temp_filename(3);
1047
Temp3_fp=fopen(Temp3_Name,"wb");
1048
if (Temp3_fp==NULL) fatalerror_named("Couldn't open temporary file 3",
1052
extern void check_temp_files(void)
1054
if (ferror(Temp1_fp))
1055
fatalerror("I/O failure: couldn't write to temporary file 1");
1056
if (ferror(Temp2_fp))
1057
fatalerror("I/O failure: couldn't write to temporary file 2");
1058
if (module_switch && ferror(Temp3_fp))
1059
fatalerror("I/O failure: couldn't write to temporary file 3");
1062
extern void remove_temp_files(void)
1063
{ if (Temp1_fp != NULL) fclose(Temp1_fp);
1064
if (Temp2_fp != NULL) fclose(Temp2_fp);
1065
remove(Temp1_Name); remove(Temp2_Name);
1067
{ if (Temp3_fp != NULL) fclose(Temp3_fp);
1072
/* ========================================================================= */
1073
/* Data structure management routines */
1074
/* ------------------------------------------------------------------------- */
1076
extern void init_files_vars(void)
1077
{ malloced_bytes = 0;
1078
checksum_low_byte = 0; /* Z-code */
1079
checksum_high_byte = 0;
1080
checksum_long = 0; /* Glulx */
1082
transcript_open = FALSE;
1085
extern void files_begin_prepass(void)
1089
extern void files_begin_pass(void)
1090
{ total_chars_read=0;
1091
if (temporary_files_switch)
1092
open_temporary_files();
1095
extern void files_allocate_arrays(void)
1096
{ filename_storage = my_malloc(MAX_SOURCE_FILES*64, "filename storage");
1097
filename_storage_p = filename_storage;
1098
filename_storage_left = MAX_SOURCE_FILES*64;
1099
InputFiles = my_malloc(MAX_SOURCE_FILES*sizeof(FileId),
1100
"input file storage");
1103
extern void files_free_arrays(void)
1104
{ my_free(&filename_storage, "filename storage");
1105
my_free(&InputFiles, "input file storage");
1108
/* ========================================================================= */