files.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761
  1. /* ------------------------------------------------------------------------- */
  2. /* "files" : File handling for source code, the transcript file and the */
  3. /* debugging information file; file handling and splicing of */
  4. /* the output file. */
  5. /* */
  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. */
  9. /* */
  10. /* Part of Inform 6.33 */
  11. /* copyright (c) Graham Nelson 1993 - 2014 */
  12. /* */
  13. /* ------------------------------------------------------------------------- */
  14. #include "header.h"
  15. int input_file; /* Number of source files so far */
  16. int32 total_chars_read; /* Characters read in (from all
  17. source files put together) */
  18. static int checksum_low_byte, /* For calculating the Z-machine's */
  19. checksum_high_byte; /* "verify" checksum */
  20. static int32 checksum_long; /* For the Glulx checksum, */
  21. static int checksum_count; /* similarly */
  22. /* ------------------------------------------------------------------------- */
  23. /* Most of the information about source files is kept by "lexer.c"; this */
  24. /* level is only concerned with file names and handles. */
  25. /* ------------------------------------------------------------------------- */
  26. FileId *InputFiles=NULL; /* Ids for all the source files */
  27. static char *filename_storage, /* Translated filenames */
  28. *filename_storage_p;
  29. static int filename_storage_left;
  30. /* ------------------------------------------------------------------------- */
  31. /* When emitting debug information, we won't have addresses of routines, */
  32. /* sequence points, Glulx objects (addresses of Z-machine objects aren't */
  33. /* needed), globals, arrays, or grammar lines. We only have their */
  34. /* offsets from base addresses, which won't be known until the end of */
  35. /* compilation. Since everything else in the relevant debug records is */
  36. /* known much earlier and is less convenient to store up, we emit the */
  37. /* debug records with a placeholder value and then backpatch these */
  38. /* placeholders. The following structs each store either an offset or a */
  39. /* symbol index and the point in the debug information file where the */
  40. /* corresponding address should be written once the base address is known. */
  41. /* ------------------------------------------------------------------------- */
  42. #define INITIAL_DEBUG_INFORMATION_BACKPATCH_ALLOCATION 65536
  43. typedef struct value_and_backpatch_position_struct
  44. { int32 value;
  45. fpos_t backpatch_position;
  46. } value_and_backpatch_position;
  47. typedef struct debug_backpatch_accumulator_struct
  48. { int32 number_of_values_to_backpatch;
  49. int32 number_of_available_backpatches;
  50. value_and_backpatch_position *values_and_backpatch_positions;
  51. int32 (* backpatching_function)(int32);
  52. } debug_backpatch_accumulator;
  53. static debug_backpatch_accumulator object_backpatch_accumulator;
  54. static debug_backpatch_accumulator packed_code_backpatch_accumulator;
  55. static debug_backpatch_accumulator code_backpatch_accumulator;
  56. static debug_backpatch_accumulator global_backpatch_accumulator;
  57. static debug_backpatch_accumulator array_backpatch_accumulator;
  58. static debug_backpatch_accumulator grammar_backpatch_accumulator;
  59. /* ------------------------------------------------------------------------- */
  60. /* File handles and names for temporary files. */
  61. /* ------------------------------------------------------------------------- */
  62. FILE *Temp1_fp=NULL, *Temp2_fp=NULL, *Temp3_fp=NULL;
  63. char Temp1_Name[PATHLEN], Temp2_Name[PATHLEN], Temp3_Name[PATHLEN];
  64. /* ------------------------------------------------------------------------- */
  65. /* Opening and closing source code files */
  66. /* ------------------------------------------------------------------------- */
  67. #if defined(PC_WIN32) && defined(HAS_REALPATH)
  68. #include <windows.h>
  69. char *realpath(const char *path, char *resolved_path)
  70. {
  71. return GetFullPathNameA(path,PATHLEN,resolved_path,NULL) != 0 ? resolved_path : 0;
  72. }
  73. #endif
  74. extern void load_sourcefile(char *filename_given, int same_directory_flag)
  75. {
  76. /* Meaning: open a new file of Inform source. (The lexer picks up on
  77. this by noticing that input_file has increased.) */
  78. char name[PATHLEN];
  79. #ifdef HAS_REALPATH
  80. char absolute_name[PATHLEN];
  81. #endif
  82. int x = 0;
  83. FILE *handle;
  84. if (input_file == MAX_SOURCE_FILES)
  85. memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
  86. do
  87. { x = translate_in_filename(x, name, filename_given, same_directory_flag,
  88. (input_file==0)?1:0);
  89. handle = fopen(name,"r");
  90. } while ((handle == NULL) && (x != 0));
  91. if (filename_storage_left <= (int)strlen(name))
  92. memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
  93. filename_storage_left -= strlen(name)+1;
  94. strcpy(filename_storage_p, name);
  95. InputFiles[input_file].filename = filename_storage_p;
  96. filename_storage_p += strlen(name)+1;
  97. if (debugfile_switch)
  98. { debug_file_printf("<source index=\"%d\">", input_file);
  99. debug_file_printf("<given-path>");
  100. debug_file_print_with_entities(filename_given);
  101. debug_file_printf("</given-path>");
  102. #ifdef HAS_REALPATH
  103. if (realpath(name, absolute_name))
  104. { debug_file_printf("<resolved-path>");
  105. debug_file_print_with_entities(absolute_name);
  106. debug_file_printf("</resolved-path>");
  107. }
  108. #endif
  109. debug_file_printf("<language>Inform 6</language>");
  110. debug_file_printf("</source>");
  111. }
  112. InputFiles[input_file].handle = handle;
  113. if (InputFiles[input_file].handle==NULL)
  114. fatalerror_named("Couldn't open source file", name);
  115. if (line_trace_level > 0) printf("\nOpening file \"%s\"\n",name);
  116. input_file++;
  117. }
  118. static void close_sourcefile(int file_number)
  119. {
  120. if (InputFiles[file_number-1].handle == NULL) return;
  121. /* Close this file. */
  122. if (ferror(InputFiles[file_number-1].handle))
  123. fatalerror_named("I/O failure: couldn't read from source file",
  124. InputFiles[file_number-1].filename);
  125. fclose(InputFiles[file_number-1].handle);
  126. InputFiles[file_number-1].handle = NULL;
  127. if (line_trace_level > 0) printf("\nClosing file\n");
  128. }
  129. extern void close_all_source(void)
  130. { int i;
  131. for (i=0; i<input_file; i++) close_sourcefile(i+1);
  132. }
  133. /* ------------------------------------------------------------------------- */
  134. /* Feeding source code up into the lexical analyser's buffer */
  135. /* (see "lexer.c" for its specification) */
  136. /* ------------------------------------------------------------------------- */
  137. extern int file_load_chars(int file_number, char *buffer, int length)
  138. {
  139. int read_in; FILE *handle;
  140. if (file_number-1 > input_file)
  141. { buffer[0] = 0; return 1; }
  142. handle = InputFiles[file_number-1].handle;
  143. if (handle == NULL)
  144. { buffer[0] = 0; return 1; }
  145. read_in = fread(buffer, 1, length, handle);
  146. total_chars_read += read_in;
  147. if (read_in == length) return length;
  148. close_sourcefile(file_number);
  149. if (file_number == 1)
  150. { buffer[read_in] = 0;
  151. buffer[read_in+1] = 0;
  152. buffer[read_in+2] = 0;
  153. buffer[read_in+3] = 0;
  154. }
  155. else
  156. { buffer[read_in] = '\n';
  157. buffer[read_in+1] = ' ';
  158. buffer[read_in+2] = ' ';
  159. buffer[read_in+3] = ' ';
  160. }
  161. return(-(read_in+4));
  162. }
  163. /* ------------------------------------------------------------------------- */
  164. /* Final assembly and output of the story file/module. */
  165. /* ------------------------------------------------------------------------- */
  166. FILE *sf_handle;
  167. static void sf_put(int c)
  168. {
  169. if (!glulx_mode) {
  170. /* The checksum is the unsigned sum mod 65536 of the bytes in the
  171. story file from 0x0040 (first byte after header) to the end.
  172. The link data does not contribute to the checksum of a module. */
  173. checksum_low_byte += c;
  174. if (checksum_low_byte>=256)
  175. { checksum_low_byte-=256;
  176. if (++checksum_high_byte==256) checksum_high_byte=0;
  177. }
  178. }
  179. else {
  180. /* The checksum is the unsigned 32-bit sum of the entire story file,
  181. considered as a list of 32-bit words, with the checksum field
  182. being zero. */
  183. switch (checksum_count) {
  184. case 0:
  185. checksum_long += (((int32)(c & 0xFF)) << 24);
  186. break;
  187. case 1:
  188. checksum_long += (((int32)(c & 0xFF)) << 16);
  189. break;
  190. case 2:
  191. checksum_long += (((int32)(c & 0xFF)) << 8);
  192. break;
  193. case 3:
  194. checksum_long += ((int32)(c & 0xFF));
  195. break;
  196. }
  197. checksum_count = (checksum_count+1) & 3;
  198. }
  199. fputc(c, sf_handle);
  200. }
  201. /* Recursive procedure to generate the Glulx compression table. */
  202. static void output_compression(int entnum, int32 *size, int *count)
  203. {
  204. huffentity_t *ent = &(huff_entities[entnum]);
  205. int32 val;
  206. char *cx;
  207. sf_put(ent->type);
  208. (*size)++;
  209. (*count)++;
  210. switch (ent->type) {
  211. case 0:
  212. val = Write_Strings_At + huff_entities[ent->u.branch[0]].addr;
  213. sf_put((val >> 24) & 0xFF);
  214. sf_put((val >> 16) & 0xFF);
  215. sf_put((val >> 8) & 0xFF);
  216. sf_put((val) & 0xFF);
  217. (*size) += 4;
  218. val = Write_Strings_At + huff_entities[ent->u.branch[1]].addr;
  219. sf_put((val >> 24) & 0xFF);
  220. sf_put((val >> 16) & 0xFF);
  221. sf_put((val >> 8) & 0xFF);
  222. sf_put((val) & 0xFF);
  223. (*size) += 4;
  224. output_compression(ent->u.branch[0], size, count);
  225. output_compression(ent->u.branch[1], size, count);
  226. break;
  227. case 1:
  228. /* no data */
  229. break;
  230. case 2:
  231. sf_put(ent->u.ch);
  232. (*size) += 1;
  233. break;
  234. case 3:
  235. cx = (char *)abbreviations_at + ent->u.val*MAX_ABBREV_LENGTH;
  236. while (*cx) {
  237. sf_put(*cx);
  238. cx++;
  239. (*size) += 1;
  240. }
  241. sf_put('\0');
  242. (*size) += 1;
  243. break;
  244. case 4:
  245. val = unicode_usage_entries[ent->u.val].ch;
  246. sf_put((val >> 24) & 0xFF);
  247. sf_put((val >> 16) & 0xFF);
  248. sf_put((val >> 8) & 0xFF);
  249. sf_put((val) & 0xFF);
  250. (*size) += 4;
  251. break;
  252. case 9:
  253. val = abbreviations_offset + 4 + ent->u.val*4;
  254. sf_put((val >> 24) & 0xFF);
  255. sf_put((val >> 16) & 0xFF);
  256. sf_put((val >> 8) & 0xFF);
  257. sf_put((val) & 0xFF);
  258. (*size) += 4;
  259. break;
  260. }
  261. }
  262. static void output_file_z(void)
  263. { FILE *fin; char new_name[PATHLEN];
  264. int32 length, blanks=0, size, i, j, offset;
  265. uint32 code_length, size_before_code, next_cons_check;
  266. int use_function;
  267. ASSERT_ZCODE();
  268. /* At this point, construct_storyfile() has just been called. */
  269. /* Enter the length information into the header. */
  270. length=((int32) Write_Strings_At) + static_strings_extent;
  271. if (module_switch) length += link_data_size +
  272. zcode_backpatch_size +
  273. zmachine_backpatch_size;
  274. while ((length%length_scale_factor)!=0) { length++; blanks++; }
  275. length=length/length_scale_factor;
  276. zmachine_paged_memory[26]=(length & 0xff00)/0x100;
  277. zmachine_paged_memory[27]=(length & 0xff);
  278. /* To assist interpreters running a paged virtual memory system, Inform
  279. writes files which are padded with zeros to the next multiple of
  280. 0.5K. This calculates the number of bytes of padding needed: */
  281. while (((length_scale_factor*length)+blanks-1)%512 != 511) blanks++;
  282. translate_out_filename(new_name, Code_Name);
  283. sf_handle = fopen(new_name,"wb");
  284. if (sf_handle == NULL)
  285. fatalerror_named("Couldn't open output file", new_name);
  286. #ifdef MAC_MPW
  287. /* Set the type and creator to Andrew Plotkin's MaxZip, a popular
  288. Z-code interpreter on the Macintosh */
  289. if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
  290. #endif
  291. /* (1) Output the paged memory. */
  292. for (i=0;i<64;i++)
  293. fputc(zmachine_paged_memory[i], sf_handle);
  294. size = 64;
  295. checksum_low_byte = 0;
  296. checksum_high_byte = 0;
  297. for (i=64; i<Write_Code_At; i++)
  298. { sf_put(zmachine_paged_memory[i]); size++;
  299. }
  300. /* (2) Output the compiled code area. */
  301. if (temporary_files_switch)
  302. { fclose(Temp2_fp);
  303. fin=fopen(Temp2_Name,"rb");
  304. if (fin==NULL)
  305. fatalerror("I/O failure: couldn't reopen temporary file 2");
  306. }
  307. if (!OMIT_UNUSED_ROUTINES) {
  308. /* This is the old-fashioned case, which is easy. All of zcode_area
  309. (zmachine_pc bytes) will be output. next_cons_check will be
  310. ignored, because j will never reach it. */
  311. code_length = zmachine_pc;
  312. use_function = TRUE;
  313. next_cons_check = code_length+1;
  314. }
  315. else {
  316. /* With dead function stripping, life is more complicated.
  317. j will run from 0 to zmachine_pc, but only code_length of
  318. those should be output. next_cons_check is the location of
  319. the next function break; that's where we check whether
  320. we're in a live function or a dead one.
  321. (This logic is simplified by the assumption that a backpatch
  322. marker will never straddle a function break.) */
  323. if (zmachine_pc != df_total_size_before_stripping)
  324. compiler_error("Code size does not match (zmachine_pc and df_total_size).");
  325. code_length = df_total_size_after_stripping;
  326. use_function = TRUE;
  327. next_cons_check = 0;
  328. df_prepare_function_iterate();
  329. }
  330. size_before_code = size;
  331. j=0;
  332. if (!module_switch)
  333. for (i=0; i<zcode_backpatch_size; i=i+3)
  334. { int long_flag = TRUE;
  335. offset
  336. = 256*read_byte_from_memory_block(&zcode_backpatch_table, i+1)
  337. + read_byte_from_memory_block(&zcode_backpatch_table, i+2);
  338. backpatch_error_flag = FALSE;
  339. backpatch_marker
  340. = read_byte_from_memory_block(&zcode_backpatch_table, i);
  341. if (backpatch_marker >= 0x80) long_flag = FALSE;
  342. backpatch_marker &= 0x7f;
  343. offset = offset + (backpatch_marker/32)*0x10000;
  344. while (offset+0x30000 < j) {
  345. offset += 0x40000;
  346. long_flag = !long_flag;
  347. }
  348. backpatch_marker &= 0x1f;
  349. /* All code up until the next backpatch marker gets flushed out
  350. as-is. (Unless we're in a stripped-out function.) */
  351. while (j<offset) {
  352. if (!use_function) {
  353. while (j<offset && j<next_cons_check) {
  354. /* get dummy value */
  355. ((temporary_files_switch)?fgetc(fin):
  356. read_byte_from_memory_block(&zcode_area, j));
  357. j++;
  358. }
  359. }
  360. else {
  361. while (j<offset && j<next_cons_check) {
  362. size++;
  363. sf_put((temporary_files_switch)?fgetc(fin):
  364. read_byte_from_memory_block(&zcode_area, j));
  365. j++;
  366. }
  367. }
  368. if (j == next_cons_check)
  369. next_cons_check = df_next_function_iterate(&use_function);
  370. }
  371. if (long_flag)
  372. { int32 v = (temporary_files_switch)?fgetc(fin):
  373. read_byte_from_memory_block(&zcode_area, j);
  374. v = 256*v + ((temporary_files_switch)?fgetc(fin):
  375. read_byte_from_memory_block(&zcode_area, j+1));
  376. j += 2;
  377. if (use_function) {
  378. v = backpatch_value(v);
  379. sf_put(v/256); sf_put(v%256);
  380. size += 2;
  381. }
  382. }
  383. else
  384. { int32 v = (temporary_files_switch)?fgetc(fin):
  385. read_byte_from_memory_block(&zcode_area, j);
  386. j++;
  387. if (use_function) {
  388. v = backpatch_value(v);
  389. sf_put(v);
  390. size++;
  391. }
  392. }
  393. if (j > next_cons_check)
  394. compiler_error("Backpatch appears to straddle function break");
  395. if (backpatch_error_flag)
  396. { printf("*** %s zcode offset=%08lx backpatch offset=%08lx ***\n",
  397. (long_flag)?"long":"short", (long int) j, (long int) i);
  398. }
  399. }
  400. /* Flush out the last bit of zcode_area, after the last backpatch
  401. marker. */
  402. offset = zmachine_pc;
  403. while (j<offset) {
  404. if (!use_function) {
  405. while (j<offset && j<next_cons_check) {
  406. /* get dummy value */
  407. ((temporary_files_switch)?fgetc(fin):
  408. read_byte_from_memory_block(&zcode_area, j));
  409. j++;
  410. }
  411. }
  412. else {
  413. while (j<offset && j<next_cons_check) {
  414. size++;
  415. sf_put((temporary_files_switch)?fgetc(fin):
  416. read_byte_from_memory_block(&zcode_area, j));
  417. j++;
  418. }
  419. }
  420. if (j == next_cons_check)
  421. next_cons_check = df_next_function_iterate(&use_function);
  422. }
  423. if (temporary_files_switch)
  424. { if (ferror(fin))
  425. fatalerror("I/O failure: couldn't read from temporary file 2");
  426. fclose(fin);
  427. }
  428. if (size_before_code + code_length != size)
  429. compiler_error("Code output length did not match");
  430. /* (3) Output any null bytes (required to reach a packed address)
  431. before the strings area. */
  432. while (size<Write_Strings_At) { sf_put(0); size++; }
  433. /* (4) Output the static strings area. */
  434. if (temporary_files_switch)
  435. { fclose(Temp1_fp);
  436. fin=fopen(Temp1_Name,"rb");
  437. if (fin==NULL)
  438. fatalerror("I/O failure: couldn't reopen temporary file 1");
  439. for (i=0; i<static_strings_extent; i++) sf_put(fgetc(fin));
  440. if (ferror(fin))
  441. fatalerror("I/O failure: couldn't read from temporary file 1");
  442. fclose(fin);
  443. remove(Temp1_Name); remove(Temp2_Name);
  444. }
  445. else
  446. for (i=0; i<static_strings_extent; i++) {
  447. sf_put(read_byte_from_memory_block(&static_strings_area,i));
  448. size++;
  449. }
  450. /* (5) Output the linking data table (in the case of a module). */
  451. if (temporary_files_switch)
  452. { if (module_switch)
  453. { fclose(Temp3_fp);
  454. fin=fopen(Temp3_Name,"rb");
  455. if (fin==NULL)
  456. fatalerror("I/O failure: couldn't reopen temporary file 3");
  457. for (j=0; j<link_data_size; j++) sf_put(fgetc(fin));
  458. if (ferror(fin))
  459. fatalerror("I/O failure: couldn't read from temporary file 3");
  460. fclose(fin);
  461. remove(Temp3_Name);
  462. }
  463. }
  464. else
  465. if (module_switch)
  466. for (i=0; i<link_data_size; i++)
  467. sf_put(read_byte_from_memory_block(&link_data_area,i));
  468. if (module_switch)
  469. { for (i=0; i<zcode_backpatch_size; i++)
  470. sf_put(read_byte_from_memory_block(&zcode_backpatch_table, i));
  471. for (i=0; i<zmachine_backpatch_size; i++)
  472. sf_put(read_byte_from_memory_block(&zmachine_backpatch_table, i));
  473. }
  474. /* (6) Output null bytes to reach a multiple of 0.5K. */
  475. while (blanks>0) { sf_put(0); blanks--; }
  476. if (ferror(sf_handle))
  477. fatalerror("I/O failure: couldn't write to story file");
  478. fseek(sf_handle, 28, SEEK_SET);
  479. fputc(checksum_high_byte, sf_handle);
  480. fputc(checksum_low_byte, sf_handle);
  481. if (ferror(sf_handle))
  482. fatalerror("I/O failure: couldn't backtrack on story file for checksum");
  483. fclose(sf_handle);
  484. /* Write a copy of the header into the debugging information file
  485. (mainly so that it can be used to identify which story file matches
  486. with which debugging info file). */
  487. if (debugfile_switch)
  488. { debug_file_printf("<story-file-prefix>");
  489. for (i = 0; i < 63; i += 3)
  490. { if (i == 27)
  491. { debug_file_print_base_64_triple
  492. (zmachine_paged_memory[27],
  493. checksum_high_byte,
  494. checksum_low_byte);
  495. } else
  496. { debug_file_print_base_64_triple
  497. (zmachine_paged_memory[i],
  498. zmachine_paged_memory[i + 1],
  499. zmachine_paged_memory[i + 2]);
  500. }
  501. }
  502. debug_file_print_base_64_single(zmachine_paged_memory[63]);
  503. debug_file_printf("</story-file-prefix>");
  504. }
  505. #ifdef ARCHIMEDES
  506. { char settype_command[PATHLEN];
  507. sprintf(settype_command, "settype %s %s",
  508. new_name, riscos_file_type());
  509. system(settype_command);
  510. }
  511. #endif
  512. #ifdef MAC_FACE
  513. if (module_switch)
  514. InformFiletypes (new_name, INF_MODULE_TYPE);
  515. else
  516. InformFiletypes (new_name, INF_ZCODE_TYPE);
  517. #endif
  518. }
  519. static void output_file_g(void)
  520. { FILE *fin; char new_name[PATHLEN];
  521. int32 size, i, j, offset;
  522. int32 VersionNum;
  523. uint32 code_length, size_before_code, next_cons_check;
  524. int use_function;
  525. int first_byte_of_triple, second_byte_of_triple, third_byte_of_triple;
  526. ASSERT_GLULX();
  527. /* At this point, construct_storyfile() has just been called. */
  528. translate_out_filename(new_name, Code_Name);
  529. sf_handle = fopen(new_name,"wb+");
  530. if (sf_handle == NULL)
  531. fatalerror_named("Couldn't open output file", new_name);
  532. #ifdef MAC_MPW
  533. /* Set the type and creator to Andrew Plotkin's MaxZip, a popular
  534. Z-code interpreter on the Macintosh */
  535. if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
  536. #endif
  537. checksum_long = 0;
  538. checksum_count = 0;
  539. /* Determine the version number. */
  540. VersionNum = 0x00020000;
  541. /* Increase for various features the game may have used. */
  542. if (no_unicode_chars != 0 || (uses_unicode_features)) {
  543. VersionNum = 0x00030000;
  544. }
  545. if (uses_memheap_features) {
  546. VersionNum = 0x00030100;
  547. }
  548. if (uses_acceleration_features) {
  549. VersionNum = 0x00030101;
  550. }
  551. if (uses_float_features) {
  552. VersionNum = 0x00030102;
  553. }
  554. /* And check if the user has requested a specific version. */
  555. if (requested_glulx_version) {
  556. if (requested_glulx_version < VersionNum) {
  557. static char error_message_buff[256];
  558. sprintf(error_message_buff, "Version 0x%08lx requested, but \
  559. game features require version 0x%08lx", (long)requested_glulx_version, (long)VersionNum);
  560. warning(error_message_buff);
  561. }
  562. else {
  563. VersionNum = requested_glulx_version;
  564. }
  565. }
  566. /* (1) Output the header. We use sf_put here, instead of fputc,
  567. because the header is included in the checksum. */
  568. /* Magic number */
  569. sf_put('G');
  570. sf_put('l');
  571. sf_put('u');
  572. sf_put('l');
  573. /* Version number. */
  574. sf_put((VersionNum >> 24));
  575. sf_put((VersionNum >> 16));
  576. sf_put((VersionNum >> 8));
  577. sf_put((VersionNum));
  578. /* RAMSTART */
  579. sf_put((Write_RAM_At >> 24));
  580. sf_put((Write_RAM_At >> 16));
  581. sf_put((Write_RAM_At >> 8));
  582. sf_put((Write_RAM_At));
  583. /* EXTSTART, or game file size */
  584. sf_put((Out_Size >> 24));
  585. sf_put((Out_Size >> 16));
  586. sf_put((Out_Size >> 8));
  587. sf_put((Out_Size));
  588. /* ENDMEM, which the game file size plus MEMORY_MAP_EXTENSION */
  589. i = Out_Size + MEMORY_MAP_EXTENSION;
  590. sf_put((i >> 24));
  591. sf_put((i >> 16));
  592. sf_put((i >> 8));
  593. sf_put((i));
  594. /* STACKSIZE */
  595. sf_put((MAX_STACK_SIZE >> 24));
  596. sf_put((MAX_STACK_SIZE >> 16));
  597. sf_put((MAX_STACK_SIZE >> 8));
  598. sf_put((MAX_STACK_SIZE));
  599. /* Initial function to call. Inform sets things up so that this
  600. is the start of the executable-code area. */
  601. sf_put((Write_Code_At >> 24));
  602. sf_put((Write_Code_At >> 16));
  603. sf_put((Write_Code_At >> 8));
  604. sf_put((Write_Code_At));
  605. /* String-encoding table. */
  606. sf_put((Write_Strings_At >> 24));
  607. sf_put((Write_Strings_At >> 16));
  608. sf_put((Write_Strings_At >> 8));
  609. sf_put((Write_Strings_At));
  610. /* Checksum -- zero for the moment. */
  611. sf_put(0x00);
  612. sf_put(0x00);
  613. sf_put(0x00);
  614. sf_put(0x00);
  615. size = GLULX_HEADER_SIZE;
  616. /* (1a) Output the eight-byte memory layout identifier. */
  617. sf_put('I'); sf_put('n'); sf_put('f'); sf_put('o');
  618. sf_put(0); sf_put(1); sf_put(0); sf_put(0);
  619. /* (1b) Output the rest of the Inform-specific data. */
  620. /* Inform version number */
  621. sf_put('0' + ((RELEASE_NUMBER/100)%10));
  622. sf_put('.');
  623. sf_put('0' + ((RELEASE_NUMBER/10)%10));
  624. sf_put('0' + RELEASE_NUMBER%10);
  625. /* Glulx back-end version number */
  626. sf_put('0' + ((GLULX_RELEASE_NUMBER/100)%10));
  627. sf_put('.');
  628. sf_put('0' + ((GLULX_RELEASE_NUMBER/10)%10));
  629. sf_put('0' + GLULX_RELEASE_NUMBER%10);
  630. /* Game release number */
  631. sf_put((release_number>>8) & 0xFF);
  632. sf_put(release_number & 0xFF);
  633. /* Game serial number */
  634. {
  635. char serialnum[8];
  636. write_serial_number(serialnum);
  637. for (i=0; i<6; i++)
  638. sf_put(serialnum[i]);
  639. }
  640. size += GLULX_STATIC_ROM_SIZE;
  641. /* (2) Output the compiled code area. */
  642. if (temporary_files_switch)
  643. { fclose(Temp2_fp);
  644. fin=fopen(Temp2_Name,"rb");
  645. if (fin==NULL)
  646. fatalerror("I/O failure: couldn't reopen temporary file 2");
  647. }
  648. if (!OMIT_UNUSED_ROUTINES) {
  649. /* This is the old-fashioned case, which is easy. All of zcode_area
  650. (zmachine_pc bytes) will be output. next_cons_check will be
  651. ignored, because j will never reach it. */
  652. code_length = zmachine_pc;
  653. use_function = TRUE;
  654. next_cons_check = code_length+1;
  655. }
  656. else {
  657. /* With dead function stripping, life is more complicated.
  658. j will run from 0 to zmachine_pc, but only code_length of
  659. those should be output. next_cons_check is the location of
  660. the next function break; that's where we check whether
  661. we're in a live function or a dead one.
  662. (This logic is simplified by the assumption that a backpatch
  663. marker will never straddle a function break.) */
  664. if (zmachine_pc != df_total_size_before_stripping)
  665. compiler_error("Code size does not match (zmachine_pc and df_total_size).");
  666. code_length = df_total_size_after_stripping;
  667. use_function = TRUE;
  668. next_cons_check = 0;
  669. df_prepare_function_iterate();
  670. }
  671. size_before_code = size;
  672. j=0;
  673. if (!module_switch)
  674. for (i=0; i<zcode_backpatch_size; i=i+6) {
  675. int data_len;
  676. int32 v;
  677. offset =
  678. (read_byte_from_memory_block(&zcode_backpatch_table, i+2) << 24)
  679. | (read_byte_from_memory_block(&zcode_backpatch_table, i+3) << 16)
  680. | (read_byte_from_memory_block(&zcode_backpatch_table, i+4) << 8)
  681. | (read_byte_from_memory_block(&zcode_backpatch_table, i+5));
  682. backpatch_error_flag = FALSE;
  683. backpatch_marker =
  684. read_byte_from_memory_block(&zcode_backpatch_table, i);
  685. data_len =
  686. read_byte_from_memory_block(&zcode_backpatch_table, i+1);
  687. /* All code up until the next backpatch marker gets flushed out
  688. as-is. (Unless we're in a stripped-out function.) */
  689. while (j<offset) {
  690. if (!use_function) {
  691. while (j<offset && j<next_cons_check) {
  692. /* get dummy value */
  693. ((temporary_files_switch)?fgetc(fin):
  694. read_byte_from_memory_block(&zcode_area, j));
  695. j++;
  696. }
  697. }
  698. else {
  699. while (j<offset && j<next_cons_check) {
  700. size++;
  701. sf_put((temporary_files_switch)?fgetc(fin):
  702. read_byte_from_memory_block(&zcode_area, j));
  703. j++;
  704. }
  705. }
  706. if (j == next_cons_check)
  707. next_cons_check = df_next_function_iterate(&use_function);
  708. }
  709. /* Write out the converted value of the backpatch marker.
  710. (Unless we're in a stripped-out function.) */
  711. switch (data_len) {
  712. case 4:
  713. v = ((temporary_files_switch)?fgetc(fin):
  714. read_byte_from_memory_block(&zcode_area, j));
  715. v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
  716. read_byte_from_memory_block(&zcode_area, j+1));
  717. v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
  718. read_byte_from_memory_block(&zcode_area, j+2));
  719. v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
  720. read_byte_from_memory_block(&zcode_area, j+3));
  721. j += 4;
  722. if (!use_function)
  723. break;
  724. v = backpatch_value(v);
  725. sf_put((v >> 24) & 0xFF);
  726. sf_put((v >> 16) & 0xFF);
  727. sf_put((v >> 8) & 0xFF);
  728. sf_put((v) & 0xFF);
  729. size += 4;
  730. break;
  731. case 2:
  732. v = ((temporary_files_switch)?fgetc(fin):
  733. read_byte_from_memory_block(&zcode_area, j));
  734. v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
  735. read_byte_from_memory_block(&zcode_area, j+1));
  736. j += 2;
  737. if (!use_function)
  738. break;
  739. v = backpatch_value(v);
  740. if (v >= 0x10000) {
  741. printf("*** backpatch value does not fit ***\n");
  742. backpatch_error_flag = TRUE;
  743. }
  744. sf_put((v >> 8) & 0xFF);
  745. sf_put((v) & 0xFF);
  746. size += 2;
  747. break;
  748. case 1:
  749. v = ((temporary_files_switch)?fgetc(fin):
  750. read_byte_from_memory_block(&zcode_area, j));
  751. j += 1;
  752. if (!use_function)
  753. break;
  754. v = backpatch_value(v);
  755. if (v >= 0x100) {
  756. printf("*** backpatch value does not fit ***\n");
  757. backpatch_error_flag = TRUE;
  758. }
  759. sf_put((v) & 0xFF);
  760. size += 1;
  761. break;
  762. default:
  763. printf("*** unknown backpatch data len = %d ***\n",
  764. data_len);
  765. backpatch_error_flag = TRUE;
  766. }
  767. if (j > next_cons_check)
  768. compiler_error("Backpatch appears to straddle function break");
  769. if (backpatch_error_flag) {
  770. printf("*** %d bytes zcode offset=%08lx backpatch offset=%08lx ***\n",
  771. data_len, (long int) j, (long int) i);
  772. }
  773. }
  774. /* Flush out the last bit of zcode_area, after the last backpatch
  775. marker. */
  776. offset = zmachine_pc;
  777. while (j<offset) {
  778. if (!use_function) {
  779. while (j<offset && j<next_cons_check) {
  780. /* get dummy value */
  781. ((temporary_files_switch)?fgetc(fin):
  782. read_byte_from_memory_block(&zcode_area, j));
  783. j++;
  784. }
  785. }
  786. else {
  787. while (j<offset && j<next_cons_check) {
  788. size++;
  789. sf_put((temporary_files_switch)?fgetc(fin):
  790. read_byte_from_memory_block(&zcode_area, j));
  791. j++;
  792. }
  793. }
  794. if (j == next_cons_check)
  795. next_cons_check = df_next_function_iterate(&use_function);
  796. }
  797. if (temporary_files_switch)
  798. { if (ferror(fin))
  799. fatalerror("I/O failure: couldn't read from temporary file 2");
  800. fclose(fin);
  801. }
  802. if (size_before_code + code_length != size)
  803. compiler_error("Code output length did not match");
  804. /* (4) Output the static strings area. */
  805. if (temporary_files_switch) {
  806. fseek(Temp1_fp, 0, SEEK_SET);
  807. }
  808. {
  809. int32 ix, lx;
  810. int ch, jx, curbyte, bx;
  811. int depth, checkcount;
  812. huffbitlist_t *bits;
  813. int32 origsize;
  814. origsize = size;
  815. if (compression_switch) {
  816. /* The 12-byte table header. */
  817. lx = compression_table_size;
  818. sf_put((lx >> 24) & 0xFF);
  819. sf_put((lx >> 16) & 0xFF);
  820. sf_put((lx >> 8) & 0xFF);
  821. sf_put((lx) & 0xFF);
  822. size += 4;
  823. sf_put((no_huff_entities >> 24) & 0xFF);
  824. sf_put((no_huff_entities >> 16) & 0xFF);
  825. sf_put((no_huff_entities >> 8) & 0xFF);
  826. sf_put((no_huff_entities) & 0xFF);
  827. size += 4;
  828. lx = Write_Strings_At + 12;
  829. sf_put((lx >> 24) & 0xFF);
  830. sf_put((lx >> 16) & 0xFF);
  831. sf_put((lx >> 8) & 0xFF);
  832. sf_put((lx) & 0xFF);
  833. size += 4;
  834. checkcount = 0;
  835. output_compression(huff_entity_root, &size, &checkcount);
  836. if (checkcount != no_huff_entities)
  837. compiler_error("Compression table count mismatch.");
  838. }
  839. if (size - origsize != compression_table_size)
  840. compiler_error("Compression table size mismatch.");
  841. origsize = size;
  842. for (lx=0, ix=0; lx<no_strings; lx++) {
  843. int escapelen=0, escapetype=0;
  844. int done=FALSE;
  845. int32 escapeval;
  846. if (compression_switch)
  847. sf_put(0xE1); /* type byte -- compressed string */
  848. else
  849. sf_put(0xE0); /* type byte -- non-compressed string */
  850. size++;
  851. jx = 0;
  852. curbyte = 0;
  853. while (!done) {
  854. if (temporary_files_switch)
  855. ch = fgetc(Temp1_fp);
  856. else
  857. ch = read_byte_from_memory_block(&static_strings_area, ix);
  858. ix++;
  859. if (ix > static_strings_extent || ch < 0)
  860. compiler_error("Read too much not-yet-compressed text.");
  861. if (escapelen == -1) {
  862. escapelen = 0;
  863. if (ch == '@') {
  864. ch = '@';
  865. }
  866. else if (ch == '0') {
  867. ch = '\0';
  868. }
  869. else if (ch == 'A' || ch == 'D' || ch == 'U') {
  870. escapelen = 4;
  871. escapetype = ch;
  872. escapeval = 0;
  873. continue;
  874. }
  875. else {
  876. compiler_error("Strange @ escape in processed text.");
  877. }
  878. }
  879. else if (escapelen) {
  880. escapeval = (escapeval << 4) | ((ch-'A') & 0x0F);
  881. escapelen--;
  882. if (escapelen == 0) {
  883. if (escapetype == 'A') {
  884. ch = huff_abbrev_start+escapeval;
  885. }
  886. else if (escapetype == 'D') {
  887. ch = huff_dynam_start+escapeval;
  888. }
  889. else if (escapetype == 'U') {
  890. ch = huff_unicode_start+escapeval;
  891. }
  892. else {
  893. compiler_error("Strange @ escape in processed text.");
  894. }
  895. }
  896. else
  897. continue;
  898. }
  899. else {
  900. if (ch == '@') {
  901. escapelen = -1;
  902. continue;
  903. }
  904. if (ch == 0) {
  905. ch = 256;
  906. done = TRUE;
  907. }
  908. }
  909. if (compression_switch) {
  910. bits = &(huff_entities[ch].bits);
  911. depth = huff_entities[ch].depth;
  912. for (bx=0; bx<depth; bx++) {
  913. if (bits->b[bx / 8] & (1 << (bx % 8)))
  914. curbyte |= (1 << jx);
  915. jx++;
  916. if (jx == 8) {
  917. sf_put(curbyte);
  918. size++;
  919. curbyte = 0;
  920. jx = 0;
  921. }
  922. }
  923. }
  924. else {
  925. if (ch >= huff_dynam_start) {
  926. sf_put(' '); sf_put(' '); sf_put(' ');
  927. size += 3;
  928. }
  929. else if (ch >= huff_abbrev_start) {
  930. /* nothing */
  931. }
  932. else {
  933. /* 256, the string terminator, comes out as zero */
  934. sf_put(ch & 0xFF);
  935. size++;
  936. }
  937. }
  938. }
  939. if (compression_switch && jx) {
  940. sf_put(curbyte);
  941. size++;
  942. }
  943. }
  944. if (size - origsize != compression_string_size)
  945. compiler_error("Compression string size mismatch.");
  946. }
  947. /* (4.5) Output any null bytes (required to reach a GPAGESIZE address)
  948. before RAMSTART. */
  949. while (size % GPAGESIZE) { sf_put(0); size++; }
  950. /* (5) Output RAM. */
  951. for (i=0; i<RAM_Size; i++)
  952. { sf_put(zmachine_paged_memory[i]); size++;
  953. }
  954. if (ferror(sf_handle))
  955. fatalerror("I/O failure: couldn't write to story file");
  956. fseek(sf_handle, 32, SEEK_SET);
  957. fputc((checksum_long >> 24) & 0xFF, sf_handle);
  958. fputc((checksum_long >> 16) & 0xFF, sf_handle);
  959. fputc((checksum_long >> 8) & 0xFF, sf_handle);
  960. fputc((checksum_long) & 0xFF, sf_handle);
  961. if (ferror(sf_handle))
  962. fatalerror("I/O failure: couldn't backtrack on story file for checksum");
  963. /* Write a copy of the first 64 bytes into the debugging information file
  964. (mainly so that it can be used to identify which story file matches with
  965. which debugging info file). */
  966. if (debugfile_switch)
  967. { fseek(sf_handle, 0L, SEEK_SET);
  968. debug_file_printf("<story-file-prefix>");
  969. for (i = 0; i < 63; i += 3)
  970. { first_byte_of_triple = fgetc(sf_handle);
  971. second_byte_of_triple = fgetc(sf_handle);
  972. third_byte_of_triple = fgetc(sf_handle);
  973. debug_file_print_base_64_triple
  974. (first_byte_of_triple,
  975. second_byte_of_triple,
  976. third_byte_of_triple);
  977. }
  978. debug_file_print_base_64_single(fgetc(sf_handle));
  979. debug_file_printf("</story-file-prefix>");
  980. }
  981. fclose(sf_handle);
  982. #ifdef ARCHIMEDES
  983. { char settype_command[PATHLEN];
  984. sprintf(settype_command, "settype %s %s",
  985. new_name, riscos_file_type());
  986. system(settype_command);
  987. }
  988. #endif
  989. #ifdef MAC_FACE
  990. if (module_switch)
  991. InformFiletypes (new_name, INF_MODULE_TYPE);
  992. else
  993. InformFiletypes (new_name, INF_ZCODE_TYPE);
  994. #endif
  995. }
  996. extern void output_file(void)
  997. {
  998. if (!glulx_mode)
  999. output_file_z();
  1000. else
  1001. output_file_g();
  1002. }
  1003. /* ------------------------------------------------------------------------- */
  1004. /* Output the text transcript file (only called if there is to be one). */
  1005. /* ------------------------------------------------------------------------- */
  1006. FILE *transcript_file_handle; int transcript_open;
  1007. extern void write_to_transcript_file(char *text)
  1008. { fputs(text, transcript_file_handle);
  1009. fputc('\n', transcript_file_handle);
  1010. }
  1011. extern void open_transcript_file(char *what_of)
  1012. { char topline_buffer[256];
  1013. transcript_file_handle = fopen(Transcript_Name,"w");
  1014. if (transcript_file_handle==NULL)
  1015. fatalerror_named("Couldn't open transcript file",
  1016. Transcript_Name);
  1017. transcript_open = TRUE;
  1018. sprintf(topline_buffer, "Transcript of the text of \"%s\"\n\
  1019. [From %s]\n", what_of, banner_line);
  1020. write_to_transcript_file(topline_buffer);
  1021. }
  1022. extern void abort_transcript_file(void)
  1023. { if (transcript_switch && transcript_open)
  1024. fclose(transcript_file_handle);
  1025. transcript_open = FALSE;
  1026. }
  1027. extern void close_transcript_file(void)
  1028. { char botline_buffer[256];
  1029. char sn_buffer[7];
  1030. write_serial_number(sn_buffer);
  1031. sprintf(botline_buffer, "\n[End of transcript: release %d.%s]\n",
  1032. release_number, sn_buffer);
  1033. write_to_transcript_file(botline_buffer);
  1034. if (ferror(transcript_file_handle))
  1035. fatalerror("I/O failure: couldn't write to transcript file");
  1036. fclose(transcript_file_handle);
  1037. transcript_open = FALSE;
  1038. #ifdef ARCHIMEDES
  1039. { char settype_command[PATHLEN];
  1040. sprintf(settype_command, "settype %s text",
  1041. Transcript_Name);
  1042. system(settype_command);
  1043. }
  1044. #endif
  1045. #ifdef MAC_FACE
  1046. InformFiletypes (Transcript_Name, INF_TEXT_TYPE);
  1047. #endif
  1048. }
  1049. /* ------------------------------------------------------------------------- */
  1050. /* Access to the debugging information file. */
  1051. /* ------------------------------------------------------------------------- */
  1052. static FILE *Debug_fp; /* Handle of debugging info file */
  1053. static void open_debug_file(void)
  1054. { Debug_fp=fopen(Debugging_Name,"wb");
  1055. if (Debug_fp==NULL)
  1056. fatalerror_named("Couldn't open debugging information file",
  1057. Debugging_Name);
  1058. }
  1059. extern void nullify_debug_file_position(maybe_file_position *position) {
  1060. position->valid = 0;
  1061. }
  1062. static void close_debug_file(void)
  1063. { fclose(Debug_fp);
  1064. #ifdef MAC_FACE
  1065. InformFiletypes (Debugging_Name, INF_DEBUG_TYPE);
  1066. #endif
  1067. }
  1068. extern void begin_debug_file(void)
  1069. { open_debug_file();
  1070. debug_file_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  1071. debug_file_printf("<inform-story-file version=\"1.0\" ");
  1072. debug_file_printf("content-creator=\"Inform\" ");
  1073. debug_file_printf
  1074. ("content-creator-version=\"%d.%d%d\">",
  1075. (VNUMBER / 100) % 10,
  1076. (VNUMBER / 10) % 10,
  1077. VNUMBER % 10);
  1078. }
  1079. extern void debug_file_printf(const char*format, ...)
  1080. { va_list argument_pointer;
  1081. va_start(argument_pointer, format);
  1082. vfprintf(Debug_fp, format, argument_pointer);
  1083. va_end(argument_pointer);
  1084. if (ferror(Debug_fp))
  1085. { fatalerror("I/O failure: can't write to debugging information file");
  1086. }
  1087. }
  1088. extern void debug_file_print_with_entities(const char*string)
  1089. { int index = 0;
  1090. char character;
  1091. for (character = string[index]; character; character = string[++index])
  1092. { switch(character)
  1093. { case '"':
  1094. debug_file_printf("&quot;");
  1095. break;
  1096. case '&':
  1097. debug_file_printf("&amp;");
  1098. break;
  1099. case '\'':
  1100. debug_file_printf("&apos;");
  1101. break;
  1102. case '<':
  1103. debug_file_printf("&lt;");
  1104. break;
  1105. case '>':
  1106. debug_file_printf("&gt;");
  1107. break;
  1108. default:
  1109. debug_file_printf("%c", character);
  1110. break;
  1111. }
  1112. }
  1113. }
  1114. static char base_64_digits[] =
  1115. { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  1116. 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
  1117. 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
  1118. 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
  1119. '8', '9', '+', '/' };
  1120. extern void debug_file_print_base_64_triple
  1121. (uchar first, uchar second, uchar third)
  1122. { debug_file_printf
  1123. ("%c%c%c%c",
  1124. base_64_digits[first >> 2],
  1125. base_64_digits[((first & 3) << 4) | (second >> 4)],
  1126. base_64_digits[((second & 15) << 2) | (third >> 6)],
  1127. base_64_digits[third & 63]);
  1128. }
  1129. extern void debug_file_print_base_64_pair(uchar first, uchar second)
  1130. { debug_file_printf
  1131. ("%c%c%c=",
  1132. base_64_digits[first >> 2],
  1133. base_64_digits[((first & 3) << 4) | (second >> 4)],
  1134. base_64_digits[(second & 15) << 2]);
  1135. }
  1136. extern void debug_file_print_base_64_single(uchar first)
  1137. { debug_file_printf
  1138. ("%c%c==",
  1139. base_64_digits[first >> 2],
  1140. base_64_digits[(first & 3) << 4]);
  1141. }
  1142. static void write_debug_location_internals(debug_location location)
  1143. { debug_file_printf("<file-index>%d</file-index>", location.file_index - 1);
  1144. debug_file_printf
  1145. ("<file-position>%d</file-position>", location.beginning_byte_index);
  1146. debug_file_printf
  1147. ("<line>%d</line>", location.beginning_line_number);
  1148. debug_file_printf
  1149. ("<character>%d</character>", location.beginning_character_number);
  1150. if (location.beginning_byte_index != location.end_byte_index ||
  1151. location.beginning_line_number != location.end_line_number ||
  1152. location.beginning_character_number != location.end_character_number)
  1153. { debug_file_printf
  1154. ("<end-file-position>%d</end-file-position>",
  1155. location.end_byte_index);
  1156. debug_file_printf
  1157. ("<end-line>%d</end-line>", location.end_line_number);
  1158. debug_file_printf
  1159. ("<end-character>%d</end-character>",
  1160. location.end_character_number);
  1161. }
  1162. }
  1163. extern void write_debug_location(debug_location location)
  1164. { if (location.file_index && location.file_index != 255)
  1165. { debug_file_printf("<source-code-location>");
  1166. write_debug_location_internals(location);
  1167. debug_file_printf("</source-code-location>");
  1168. }
  1169. }
  1170. extern void write_debug_locations(debug_locations locations)
  1171. { if (locations.next)
  1172. { const debug_locations*current = &locations;
  1173. unsigned int index = 0;
  1174. for (; current; current = current->next, ++index)
  1175. { debug_file_printf("<source-code-location index=\"%d\">", index);
  1176. write_debug_location_internals(current->location);
  1177. debug_file_printf("</source-code-location>");
  1178. }
  1179. }
  1180. else
  1181. { write_debug_location(locations.location);
  1182. }
  1183. }
  1184. extern void write_debug_optional_identifier(int32 symbol_index)
  1185. { if (stypes[symbol_index] != ROUTINE_T)
  1186. { compiler_error
  1187. ("Attempt to write a replaceable identifier for a non-routine");
  1188. }
  1189. if (replacement_debug_backpatch_positions[symbol_index].valid)
  1190. { if (fsetpos
  1191. (Debug_fp,
  1192. &replacement_debug_backpatch_positions[symbol_index].position))
  1193. { fatalerror("I/O failure: can't seek in debugging information file");
  1194. }
  1195. debug_file_printf
  1196. ("<identifier artificial=\"true\">%s "
  1197. "(superseded replacement)</identifier>",
  1198. symbs[symbol_index]);
  1199. if (fseek(Debug_fp, 0L, SEEK_END))
  1200. { fatalerror("I/O failure: can't seek in debugging information file");
  1201. }
  1202. }
  1203. fgetpos
  1204. (Debug_fp, &replacement_debug_backpatch_positions[symbol_index].position);
  1205. replacement_debug_backpatch_positions[symbol_index].valid = TRUE;
  1206. debug_file_printf("<identifier>%s</identifier>", symbs[symbol_index]);
  1207. /* Space for: artificial="true" (superseded replacement) */
  1208. debug_file_printf(" ");
  1209. }
  1210. extern void write_debug_symbol_backpatch(int32 symbol_index)
  1211. { if (symbol_debug_backpatch_positions[symbol_index].valid) {
  1212. compiler_error("Symbol entry incorrectly reused in debug information "
  1213. "file backpatching");
  1214. }
  1215. fgetpos(Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position);
  1216. symbol_debug_backpatch_positions[symbol_index].valid = TRUE;
  1217. /* Reserve space for up to 10 digits plus a negative sign. */
  1218. debug_file_printf("*BACKPATCH*");
  1219. }
  1220. extern void write_debug_symbol_optional_backpatch(int32 symbol_index)
  1221. { if (symbol_debug_backpatch_positions[symbol_index].valid) {
  1222. compiler_error("Symbol entry incorrectly reused in debug information "
  1223. "file backpatching");
  1224. }
  1225. /* Reserve space for open and close value tags and up to 10 digits plus a
  1226. negative sign, but take the backpatch position just inside the element,
  1227. so that we'll be in the same case as above if the symbol is eventually
  1228. defined. */
  1229. debug_file_printf("<value>");
  1230. fgetpos(Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position);
  1231. symbol_debug_backpatch_positions[symbol_index].valid = TRUE;
  1232. debug_file_printf("*BACKPATCH*</value>");
  1233. }
  1234. static void write_debug_backpatch
  1235. (debug_backpatch_accumulator *accumulator, int32 value)
  1236. { if (accumulator->number_of_values_to_backpatch ==
  1237. accumulator->number_of_available_backpatches)
  1238. { my_realloc(&accumulator->values_and_backpatch_positions,
  1239. sizeof(value_and_backpatch_position) *
  1240. accumulator->number_of_available_backpatches,
  1241. 2 * sizeof(value_and_backpatch_position) *
  1242. accumulator->number_of_available_backpatches,
  1243. "values and debug information backpatch positions");
  1244. accumulator->number_of_available_backpatches *= 2;
  1245. }
  1246. accumulator->values_and_backpatch_positions
  1247. [accumulator->number_of_values_to_backpatch].value = value;
  1248. fgetpos
  1249. (Debug_fp,
  1250. &accumulator->values_and_backpatch_positions
  1251. [accumulator->number_of_values_to_backpatch].backpatch_position);
  1252. ++(accumulator->number_of_values_to_backpatch);
  1253. /* Reserve space for up to 10 digits plus a negative sign. */
  1254. debug_file_printf("*BACKPATCH*");
  1255. }
  1256. extern void write_debug_object_backpatch(int32 object_number)
  1257. { if (glulx_mode)
  1258. { write_debug_backpatch(&object_backpatch_accumulator, object_number - 1);
  1259. }
  1260. else
  1261. { debug_file_printf("%d", object_number);
  1262. }
  1263. }
  1264. static int32 backpatch_object_address(int32 index)
  1265. { return object_tree_offset + OBJECT_BYTE_LENGTH * index;
  1266. }
  1267. extern void write_debug_packed_code_backpatch(int32 offset)
  1268. { write_debug_backpatch(&packed_code_backpatch_accumulator, offset);
  1269. }
  1270. static int32 backpatch_packed_code_address(int32 offset)
  1271. { return (code_offset + offset) / scale_factor;
  1272. }
  1273. extern void write_debug_code_backpatch(int32 offset)
  1274. { write_debug_backpatch(&code_backpatch_accumulator, offset);
  1275. }
  1276. static int32 backpatch_code_address(int32 offset)
  1277. { return code_offset + offset;
  1278. }
  1279. extern void write_debug_global_backpatch(int32 offset)
  1280. { write_debug_backpatch(&global_backpatch_accumulator, offset);
  1281. }
  1282. static int32 backpatch_global_address(int32 offset)
  1283. { return variables_offset + WORDSIZE * (offset - MAX_LOCAL_VARIABLES);
  1284. }
  1285. extern void write_debug_array_backpatch(int32 offset)
  1286. { write_debug_backpatch(&array_backpatch_accumulator, offset);
  1287. }
  1288. static int32 backpatch_array_address(int32 offset)
  1289. { return (glulx_mode ? arrays_offset : variables_offset) + offset;
  1290. }
  1291. extern void write_debug_grammar_backpatch(int32 offset)
  1292. { write_debug_backpatch(&grammar_backpatch_accumulator, offset);
  1293. }
  1294. static int32 backpatch_grammar_address(int32 offset)
  1295. { return grammar_table_offset + offset;
  1296. }
  1297. extern void begin_writing_debug_sections()
  1298. { debug_file_printf("<story-file-section>");
  1299. debug_file_printf("<type>header</type>");
  1300. debug_file_printf("<address>0</address>");
  1301. }
  1302. extern void write_debug_section(const char*name, int32 beginning_address)
  1303. { debug_file_printf("<end-address>%d</end-address>", beginning_address);
  1304. debug_file_printf("</story-file-section>");
  1305. debug_file_printf("<story-file-section>");
  1306. debug_file_printf("<type>");
  1307. debug_file_print_with_entities(name);
  1308. debug_file_printf("</type>");
  1309. debug_file_printf("<address>%d</address>", beginning_address);
  1310. }
  1311. extern void end_writing_debug_sections(int32 end_address)
  1312. { debug_file_printf("<end-address>%d</end-address>", end_address);
  1313. debug_file_printf("</story-file-section>");
  1314. }
  1315. extern void write_debug_undef(int32 symbol_index)
  1316. { if (!symbol_debug_backpatch_positions[symbol_index].valid)
  1317. { compiler_error
  1318. ("Attempt to erase debugging information never written or since "
  1319. "erased");
  1320. }
  1321. if (stypes[symbol_index] != CONSTANT_T)
  1322. { compiler_error
  1323. ("Attempt to erase debugging information for a non-constant "
  1324. "because of an #undef");
  1325. }
  1326. if (fsetpos
  1327. (Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position))
  1328. { fatalerror("I/O failure: can't seek in debugging information file");
  1329. }
  1330. /* There are 7 characters in ``<value>''. */
  1331. if (fseek(Debug_fp, -7L, SEEK_CUR))
  1332. { fatalerror("I/O failure: can't seek in debugging information file");
  1333. }
  1334. /* Overwrite: <value>*BACKPATCH*</value> */
  1335. debug_file_printf(" ");
  1336. nullify_debug_file_position
  1337. (&symbol_debug_backpatch_positions[symbol_index]);
  1338. if (fseek(Debug_fp, 0L, SEEK_END))
  1339. { fatalerror("I/O failure: can't seek in debugging information file");
  1340. }
  1341. }
  1342. static void apply_debug_information_backpatches
  1343. (debug_backpatch_accumulator *accumulator)
  1344. { int32 backpatch_index, backpatch_value;
  1345. for (backpatch_index = accumulator->number_of_values_to_backpatch;
  1346. backpatch_index--;)
  1347. { if (fsetpos
  1348. (Debug_fp,
  1349. &accumulator->values_and_backpatch_positions
  1350. [backpatch_index].backpatch_position))
  1351. { fatalerror
  1352. ("I/O failure: can't seek in debugging information file");
  1353. }
  1354. backpatch_value =
  1355. (*accumulator->backpatching_function)
  1356. (accumulator->values_and_backpatch_positions
  1357. [backpatch_index].value);
  1358. debug_file_printf
  1359. ("%11d", /* Space for up to 10 digits plus a negative sign. */
  1360. backpatch_value);
  1361. }
  1362. }
  1363. static void apply_debug_information_symbol_backpatches()
  1364. { int backpatch_symbol;
  1365. for (backpatch_symbol = no_symbols; backpatch_symbol--;)
  1366. { if (symbol_debug_backpatch_positions[backpatch_symbol].valid)
  1367. { if (fsetpos(Debug_fp,
  1368. &symbol_debug_backpatch_positions
  1369. [backpatch_symbol].position))
  1370. { fatalerror
  1371. ("I/O failure: can't seek in debugging information file");
  1372. }
  1373. debug_file_printf("%11d", svals[backpatch_symbol]);
  1374. }
  1375. }
  1376. }
  1377. static void write_debug_system_constants()
  1378. { int *system_constant_list =
  1379. glulx_mode ? glulx_system_constant_list : z_system_constant_list;
  1380. int system_constant_index = 0;
  1381. /* Store system constants. */
  1382. for (; system_constant_list[system_constant_index] != -1;
  1383. ++system_constant_index)
  1384. { int system_constant = system_constant_list[system_constant_index];
  1385. debug_file_printf("<constant>");
  1386. debug_file_printf
  1387. ("<identifier>#%s</identifier>",
  1388. system_constants.keywords[system_constant]);
  1389. debug_file_printf
  1390. ("<value>%d</value>",
  1391. value_of_system_constant(system_constant));
  1392. debug_file_printf("</constant>");
  1393. }
  1394. }
  1395. extern void end_debug_file()
  1396. { write_debug_system_constants();
  1397. debug_file_printf("</inform-story-file>\n");
  1398. if (glulx_mode)
  1399. { apply_debug_information_backpatches(&object_backpatch_accumulator);
  1400. } else
  1401. { apply_debug_information_backpatches(&packed_code_backpatch_accumulator);
  1402. }
  1403. apply_debug_information_backpatches(&code_backpatch_accumulator);
  1404. apply_debug_information_backpatches(&global_backpatch_accumulator);
  1405. apply_debug_information_backpatches(&array_backpatch_accumulator);
  1406. apply_debug_information_backpatches(&grammar_backpatch_accumulator);
  1407. apply_debug_information_symbol_backpatches();
  1408. close_debug_file();
  1409. }
  1410. /* ------------------------------------------------------------------------- */
  1411. /* Temporary storage files: */
  1412. /* */
  1413. /* Temp file 1 is used to hold the static strings area, as compiled */
  1414. /* 2 to hold compiled routines of Z-code */
  1415. /* 3 to hold the link data table (but only for modules) */
  1416. /* */
  1417. /* (Though annoying, this procedure typically saves about 200K of memory, */
  1418. /* an important point for Amiga and sub-386 PC users of Inform) */
  1419. /* ------------------------------------------------------------------------- */
  1420. extern void open_temporary_files(void)
  1421. { translate_temp_filename(1);
  1422. Temp1_fp=fopen(Temp1_Name,"wb");
  1423. if (Temp1_fp==NULL) fatalerror_named("Couldn't open temporary file 1",
  1424. Temp1_Name);
  1425. translate_temp_filename(2);
  1426. Temp2_fp=fopen(Temp2_Name,"wb");
  1427. if (Temp2_fp==NULL) fatalerror_named("Couldn't open temporary file 2",
  1428. Temp2_Name);
  1429. if (!module_switch) return;
  1430. translate_temp_filename(3);
  1431. Temp3_fp=fopen(Temp3_Name,"wb");
  1432. if (Temp3_fp==NULL) fatalerror_named("Couldn't open temporary file 3",
  1433. Temp3_Name);
  1434. }
  1435. extern void check_temp_files(void)
  1436. {
  1437. if (ferror(Temp1_fp))
  1438. fatalerror("I/O failure: couldn't write to temporary file 1");
  1439. if (ferror(Temp2_fp))
  1440. fatalerror("I/O failure: couldn't write to temporary file 2");
  1441. if (module_switch && ferror(Temp3_fp))
  1442. fatalerror("I/O failure: couldn't write to temporary file 3");
  1443. }
  1444. extern void remove_temp_files(void)
  1445. { if (Temp1_fp != NULL) fclose(Temp1_fp);
  1446. if (Temp2_fp != NULL) fclose(Temp2_fp);
  1447. remove(Temp1_Name); remove(Temp2_Name);
  1448. if (module_switch)
  1449. { if (Temp3_fp != NULL) fclose(Temp3_fp);
  1450. remove(Temp3_Name);
  1451. }
  1452. }
  1453. /* ========================================================================= */
  1454. /* Data structure management routines */
  1455. /* ------------------------------------------------------------------------- */
  1456. extern void init_files_vars(void)
  1457. { malloced_bytes = 0;
  1458. checksum_low_byte = 0; /* Z-code */
  1459. checksum_high_byte = 0;
  1460. checksum_long = 0; /* Glulx */
  1461. checksum_count = 0;
  1462. transcript_open = FALSE;
  1463. }
  1464. extern void files_begin_prepass(void)
  1465. { input_file = 0;
  1466. }
  1467. extern void files_begin_pass(void)
  1468. { total_chars_read=0;
  1469. if (temporary_files_switch)
  1470. open_temporary_files();
  1471. }
  1472. static void initialise_accumulator
  1473. (debug_backpatch_accumulator *accumulator,
  1474. int32 (* backpatching_function)(int32))
  1475. { accumulator->number_of_values_to_backpatch = 0;
  1476. accumulator->number_of_available_backpatches =
  1477. INITIAL_DEBUG_INFORMATION_BACKPATCH_ALLOCATION;
  1478. accumulator->values_and_backpatch_positions =
  1479. my_malloc
  1480. (sizeof(value_and_backpatch_position) *
  1481. accumulator->number_of_available_backpatches,
  1482. "values and debug information backpatch positions");
  1483. accumulator->backpatching_function = backpatching_function;
  1484. }
  1485. extern void files_allocate_arrays(void)
  1486. { filename_storage = my_malloc(MAX_SOURCE_FILES*64, "filename storage");
  1487. filename_storage_p = filename_storage;
  1488. filename_storage_left = MAX_SOURCE_FILES*64;
  1489. InputFiles = my_malloc(MAX_SOURCE_FILES*sizeof(FileId),
  1490. "input file storage");
  1491. if (debugfile_switch)
  1492. { if (glulx_mode)
  1493. { initialise_accumulator
  1494. (&object_backpatch_accumulator, &backpatch_object_address);
  1495. } else
  1496. { initialise_accumulator
  1497. (&packed_code_backpatch_accumulator,
  1498. &backpatch_packed_code_address);
  1499. }
  1500. initialise_accumulator
  1501. (&code_backpatch_accumulator, &backpatch_code_address);
  1502. initialise_accumulator
  1503. (&global_backpatch_accumulator, &backpatch_global_address);
  1504. initialise_accumulator
  1505. (&array_backpatch_accumulator, &backpatch_array_address);
  1506. initialise_accumulator
  1507. (&grammar_backpatch_accumulator, &backpatch_grammar_address);
  1508. }
  1509. }
  1510. static void tear_down_accumulator(debug_backpatch_accumulator *accumulator)
  1511. { my_free
  1512. (&(accumulator->values_and_backpatch_positions),
  1513. "values and debug information backpatch positions");
  1514. }
  1515. extern void files_free_arrays(void)
  1516. { my_free(&filename_storage, "filename storage");
  1517. my_free(&InputFiles, "input file storage");
  1518. if (debugfile_switch)
  1519. { if (!glulx_mode)
  1520. { tear_down_accumulator(&object_backpatch_accumulator);
  1521. } else
  1522. { tear_down_accumulator(&packed_code_backpatch_accumulator);
  1523. }
  1524. tear_down_accumulator(&code_backpatch_accumulator);
  1525. tear_down_accumulator(&global_backpatch_accumulator);
  1526. tear_down_accumulator(&array_backpatch_accumulator);
  1527. tear_down_accumulator(&grammar_backpatch_accumulator);
  1528. }
  1529. }
  1530. /* ========================================================================= */