linker.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. /* ------------------------------------------------------------------------- */
  2. /* "linker" : For compiling and linking modules */
  3. /* */
  4. /* Part of Inform 6.33 */
  5. /* copyright (c) Graham Nelson 1993 - 2014 */
  6. /* */
  7. /* ------------------------------------------------------------------------- */
  8. #include "header.h"
  9. memory_block link_data_area;
  10. uchar *link_data_holding_area, *link_data_top;
  11. /* Start, current top, size of */
  12. int32 link_data_size; /* link data table being written */
  13. /* (holding import/export names) */
  14. extern int32 *action_symbol;
  15. /* ------------------------------------------------------------------------- */
  16. /* Marker values */
  17. /* ------------------------------------------------------------------------- */
  18. extern char *describe_mv(int mval)
  19. { switch(mval)
  20. { case NULL_MV: return("null");
  21. /* Marker values used in ordinary story file backpatching */
  22. case DWORD_MV: return("dictionary word");
  23. case STRING_MV: return("string literal");
  24. case INCON_MV: return("system constant");
  25. case IROUTINE_MV: return("routine");
  26. case VROUTINE_MV: return("veneer routine");
  27. case ARRAY_MV: return("internal array");
  28. case NO_OBJS_MV: return("the number of objects");
  29. case INHERIT_MV: return("inherited common p value");
  30. case INDIVPT_MV: return("indiv prop table address");
  31. case INHERIT_INDIV_MV: return("inherited indiv p value");
  32. case MAIN_MV: return("ref to Main");
  33. case SYMBOL_MV: return("ref to symbol value");
  34. /* Additional marker values used in module backpatching */
  35. case VARIABLE_MV: return("global variable");
  36. case IDENT_MV: return("prop identifier number");
  37. case ACTION_MV: return("action");
  38. case OBJECT_MV: return("internal object");
  39. /* Record types in the import/export table (not really marker
  40. values at all) */
  41. case EXPORT_MV: return("Export ");
  42. case EXPORTSF_MV: return("Export sf");
  43. case EXPORTAC_MV: return("Export ##");
  44. case IMPORT_MV: return("Import ");
  45. }
  46. return("** No such MV **");
  47. }
  48. /* ------------------------------------------------------------------------- */
  49. /* Import/export records */
  50. /* ------------------------------------------------------------------------- */
  51. typedef struct importexport_s
  52. { int module_value;
  53. int32 symbol_number;
  54. char symbol_type;
  55. int backpatch;
  56. int32 symbol_value;
  57. char *symbol_name;
  58. } ImportExport;
  59. static void describe_importexport(ImportExport *I)
  60. { printf("%8s %20s %04d %04x %s\n",
  61. describe_mv(I->module_value), I->symbol_name,
  62. I->symbol_number, I->symbol_value, typename(I->symbol_type));
  63. }
  64. /* ========================================================================= */
  65. /* Linking in external modules: this code is run when the external */
  66. /* program hits a Link directive. */
  67. /* ------------------------------------------------------------------------- */
  68. /* This map is between global variable numbers in the module and in the */
  69. /* external program: variables_map[n] will be the external global variable */
  70. /* no for module global variable no n. (The entries [0] to [15] are not */
  71. /* used.) */
  72. /* ------------------------------------------------------------------------- */
  73. static int variables_map[256], actions_map[256];
  74. int32 module_map[16];
  75. ImportExport IE;
  76. /* ------------------------------------------------------------------------- */
  77. /* These are offsets within the module: */
  78. /* ------------------------------------------------------------------------- */
  79. static int32 m_code_offset, m_strs_offset, m_static_offset, m_dict_offset,
  80. m_vars_offset, m_objs_offset, m_props_offset, m_class_numbers,
  81. m_individuals_offset, m_individuals_length;
  82. static int m_no_objects, m_no_globals, p_no_globals, lowest_imported_global_no;
  83. int32 *xref_table; int xref_top;
  84. int32 *property_identifier_map;
  85. int *accession_numbers_map;
  86. int32 routine_replace[64],
  87. routine_replace_with[64]; int no_rr;
  88. /* ------------------------------------------------------------------------- */
  89. /* Reading and writing bytes/words in the module (as loaded in), indexing */
  90. /* via "marker addresses". */
  91. /* ------------------------------------------------------------------------- */
  92. static int32 read_marker_address(uchar *p, int size,
  93. int zmachine_area, int32 offset)
  94. {
  95. /* A routine to read the value referred to by the marker address
  96. (zmachine_area, offset): size is 1 for byte, 2 for word, and the
  97. module itself resides at p. */
  98. int32 addr = 0;
  99. switch(zmachine_area)
  100. {
  101. case DYNAMIC_ARRAY_ZA:
  102. addr = m_vars_offset; break;
  103. case ZCODE_ZA:
  104. addr = m_code_offset; break;
  105. case STATIC_STRINGS_ZA:
  106. addr = m_strs_offset; break;
  107. case DICTIONARY_ZA:
  108. addr = m_dict_offset; break;
  109. case OBJECT_TREE_ZA:
  110. addr = m_objs_offset; break;
  111. case PROP_ZA:
  112. addr = m_props_offset; break;
  113. case INDIVIDUAL_PROP_ZA:
  114. addr = m_individuals_offset; break;
  115. }
  116. if (size == 1) return p[addr+offset];
  117. return 256*p[addr+offset] + p[addr+offset+1];
  118. }
  119. static void write_marker_address(uchar *p, int size,
  120. int zmachine_area, int32 offset, int32 value)
  121. {
  122. /* Similar, but to write to it. */
  123. int32 addr = 0;
  124. switch(zmachine_area)
  125. {
  126. case DYNAMIC_ARRAY_ZA:
  127. addr = m_vars_offset; break;
  128. case ZCODE_ZA:
  129. addr = m_code_offset; break;
  130. case STATIC_STRINGS_ZA:
  131. addr = m_strs_offset; break;
  132. case DICTIONARY_ZA:
  133. addr = m_dict_offset; break;
  134. case OBJECT_TREE_ZA:
  135. addr = m_objs_offset; break;
  136. case PROP_ZA:
  137. addr = m_props_offset; break;
  138. case INDIVIDUAL_PROP_ZA:
  139. addr = m_individuals_offset; break;
  140. }
  141. if (size == 1) { p[addr+offset] = value%256; return; }
  142. p[addr+offset] = value/256;
  143. p[addr+offset+1] = value%256;
  144. }
  145. int m_read_pos;
  146. static int get_next_record(uchar *p)
  147. { int i;
  148. int record_type = p[m_read_pos++];
  149. switch(record_type)
  150. { case 0: break;
  151. case EXPORT_MV:
  152. case EXPORTSF_MV:
  153. case EXPORTAC_MV:
  154. case IMPORT_MV:
  155. IE.module_value = record_type;
  156. i=p[m_read_pos++]; IE.symbol_number = 256*i + p[m_read_pos++];
  157. IE.symbol_type = p[m_read_pos++];
  158. if (record_type != IMPORT_MV) IE.backpatch = p[m_read_pos++];
  159. i=p[m_read_pos++]; IE.symbol_value = 256*i + p[m_read_pos++];
  160. IE.symbol_name = (char *) (p+m_read_pos);
  161. m_read_pos += strlen((char *) (p+m_read_pos))+1;
  162. if (linker_trace_level >= 2) describe_importexport(&IE);
  163. break;
  164. default:
  165. printf("Marker value of %d\n", record_type);
  166. compiler_error("Link: illegal import/export marker value");
  167. return -1;
  168. }
  169. return record_type;
  170. }
  171. static char link_errorm[128];
  172. static void accept_export(void)
  173. { int32 index, map_to = IE.symbol_value % 0x10000;
  174. index = symbol_index(IE.symbol_name, -1);
  175. xref_table[IE.symbol_number] = index;
  176. if (!(sflags[index] & UNKNOWN_SFLAG))
  177. { if (IE.module_value == EXPORTAC_MV)
  178. { if ((!(sflags[index] & ACTION_SFLAG))
  179. && (stypes[index] != FAKE_ACTION_T))
  180. link_error_named(
  181. "action name clash with", IE.symbol_name);
  182. }
  183. else
  184. if (stypes[index] == IE.symbol_type)
  185. { switch(IE.symbol_type)
  186. { case CONSTANT_T:
  187. if ((!(svals[index] == IE.symbol_value))
  188. || (IE.backpatch != 0))
  189. link_error_named(
  190. "program and module give differing values of", IE.symbol_name);
  191. break;
  192. case INDIVIDUAL_PROPERTY_T:
  193. property_identifier_map[IE.symbol_value] = svals[index];
  194. break;
  195. case ROUTINE_T:
  196. if ((IE.module_value == EXPORTSF_MV)
  197. && (sflags[index] & REPLACE_SFLAG))
  198. break;
  199. default:
  200. sprintf(link_errorm,
  201. "%s '%s' in both program and module",
  202. typename(IE.symbol_type), IE.symbol_name);
  203. link_error(link_errorm);
  204. break;
  205. }
  206. }
  207. else
  208. { sprintf(link_errorm,
  209. "'%s' has type %s in program but type %s in module",
  210. IE.symbol_name, typename(stypes[index]),
  211. typename(IE.symbol_type));
  212. link_error(link_errorm);
  213. }
  214. }
  215. else
  216. { if (IE.module_value == EXPORTAC_MV)
  217. { IE.symbol_value = no_actions;
  218. action_symbol[no_actions++] = index;
  219. if (linker_trace_level >= 4)
  220. printf("Creating action ##%s\n", (char *) symbs[index]);
  221. }
  222. else
  223. switch(IE.symbol_type)
  224. { case ROUTINE_T:
  225. if ((IE.module_value == EXPORTSF_MV)
  226. && (sflags[index] & REPLACE_SFLAG))
  227. { routine_replace[no_rr] = IE.symbol_value;
  228. routine_replace_with[no_rr++] = index;
  229. return;
  230. }
  231. IE.symbol_value += (zmachine_pc/scale_factor);
  232. break;
  233. case OBJECT_T:
  234. case CLASS_T:
  235. IE.symbol_value += no_objects;
  236. break;
  237. case ARRAY_T:
  238. IE.symbol_value += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
  239. break;
  240. case GLOBAL_VARIABLE_T:
  241. if (no_globals==233)
  242. { link_error(
  243. "failed because too many extra global variables needed");
  244. return;
  245. }
  246. variables_map[16 + m_no_globals++] = 16 + no_globals;
  247. set_variable_value(no_globals, IE.symbol_value);
  248. IE.symbol_value = 16 + no_globals++;
  249. break;
  250. case INDIVIDUAL_PROPERTY_T:
  251. property_identifier_map[IE.symbol_value]
  252. = no_individual_properties;
  253. IE.symbol_value = no_individual_properties++;
  254. if (debugfile_switch)
  255. { debug_file_printf("<property>");
  256. debug_file_printf
  257. ("<identifier>%s</identifier>", IE.symbol_name);
  258. debug_file_printf
  259. ("<value>%d</value>", IE.symbol_value);
  260. debug_file_printf("</property>");
  261. }
  262. break;
  263. }
  264. assign_symbol(index, IE.backpatch*0x10000 + IE.symbol_value,
  265. IE.symbol_type);
  266. if (IE.backpatch != 0) sflags[index] |= CHANGE_SFLAG;
  267. sflags[index] |= EXPORT_SFLAG;
  268. if (IE.module_value == EXPORTSF_MV)
  269. sflags[index] |= INSF_SFLAG;
  270. if (IE.module_value == EXPORTAC_MV)
  271. sflags[index] |= ACTION_SFLAG;
  272. }
  273. if (IE.module_value == EXPORTAC_MV)
  274. { if (linker_trace_level >= 4)
  275. printf("Map %d '%s' to %d\n",
  276. IE.symbol_value, (char *) (symbs[index]), svals[index]);
  277. actions_map[map_to] = svals[index];
  278. }
  279. }
  280. static void accept_import(void)
  281. { int32 index;
  282. index = symbol_index(IE.symbol_name, -1);
  283. sflags[index] |= USED_SFLAG;
  284. xref_table[IE.symbol_number] = index;
  285. if (!(sflags[index] & UNKNOWN_SFLAG))
  286. { switch (IE.symbol_type)
  287. {
  288. case GLOBAL_VARIABLE_T:
  289. if (stypes[index] != GLOBAL_VARIABLE_T)
  290. link_error_named(
  291. "module (wrongly) declared this a variable:", IE.symbol_name);
  292. variables_map[IE.symbol_value] = svals[index];
  293. if (IE.symbol_value < lowest_imported_global_no)
  294. lowest_imported_global_no = IE.symbol_value;
  295. break;
  296. default:
  297. switch(stypes[index])
  298. { case ATTRIBUTE_T:
  299. link_error_named(
  300. "this attribute is undeclared within module:", IE.symbol_name);; break;
  301. case PROPERTY_T:
  302. link_error_named(
  303. "this property is undeclared within module:", IE.symbol_name); break;
  304. case INDIVIDUAL_PROPERTY_T:
  305. case ARRAY_T:
  306. case ROUTINE_T:
  307. case CONSTANT_T:
  308. case OBJECT_T:
  309. case CLASS_T:
  310. case FAKE_ACTION_T:
  311. break;
  312. default:
  313. link_error_named(
  314. "this was referred to as a constant, but isn't:", IE.symbol_name);
  315. break;
  316. }
  317. break;
  318. }
  319. }
  320. else
  321. { switch (IE.symbol_type)
  322. {
  323. case GLOBAL_VARIABLE_T:
  324. if (stypes[index] != GLOBAL_VARIABLE_T)
  325. link_error_named(
  326. "Module tried to import a Global variable not defined here:",
  327. IE.symbol_name);
  328. variables_map[IE.symbol_value] = 16;
  329. if (IE.symbol_value < lowest_imported_global_no)
  330. lowest_imported_global_no = IE.symbol_value;
  331. break;
  332. }
  333. }
  334. }
  335. static int32 backpatch_backpatch(int32 v)
  336. { switch(backpatch_marker)
  337. {
  338. /* Backpatches made now which are final */
  339. case OBJECT_MV:
  340. v += no_objects;
  341. backpatch_marker = NULL_MV;
  342. break;
  343. case ACTION_MV:
  344. if ((v<0) || (v>=256) || (actions_map[v] == -1))
  345. { link_error("unmapped action number");
  346. printf("*** Link: unmapped action number %d ***", v);
  347. v = 0;
  348. break;
  349. }
  350. v = actions_map[v];
  351. backpatch_marker = NULL_MV;
  352. break;
  353. case IDENT_MV:
  354. { int f = v & 0x8000;
  355. v = f + property_identifier_map[v-f];
  356. backpatch_marker = NULL_MV;
  357. break;
  358. }
  359. case VARIABLE_MV:
  360. backpatch_marker = NULL_MV;
  361. if (v < lowest_imported_global_no)
  362. { v = v + p_no_globals; break;
  363. }
  364. if (variables_map[v] == -1)
  365. { printf("** Unmapped variable %d! **\n", v);
  366. variables_map[v] = 16;
  367. link_error("unmapped variable error"); break;
  368. }
  369. v = variables_map[v];
  370. break;
  371. /* Backpatch values which are themselves being backpatched */
  372. case INDIVPT_MV:
  373. v += individuals_length;
  374. break;
  375. case SYMBOL_MV:
  376. v = xref_table[v];
  377. if ((v<0) || (v>=no_symbols))
  378. { printf("** Symbol number %d cannot be crossreferenced **\n", v);
  379. link_error("symbol crossreference error"); v=0;
  380. break;
  381. }
  382. break;
  383. case STRING_MV:
  384. v += static_strings_extent/scale_factor;
  385. break;
  386. case IROUTINE_MV:
  387. { int i;
  388. for (i=0;i<no_rr;i++)
  389. if (v == routine_replace[i])
  390. { v = routine_replace_with[i];
  391. backpatch_marker = SYMBOL_MV;
  392. goto IR_Done;
  393. }
  394. v += zmachine_pc/scale_factor;
  395. }
  396. IR_Done: break;
  397. case VROUTINE_MV:
  398. veneer_routine(v);
  399. break;
  400. case ARRAY_MV:
  401. if (v < (MAX_GLOBAL_VARIABLES*2))
  402. { v = 2*(variables_map[v/2 + 16] - 16);
  403. }
  404. else
  405. { v += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
  406. }
  407. break;
  408. case DWORD_MV:
  409. v = accession_numbers_map[v];
  410. break;
  411. case INHERIT_MV:
  412. v += properties_table_size;
  413. break;
  414. case INHERIT_INDIV_MV:
  415. v += individuals_length;
  416. break;
  417. }
  418. return v;
  419. }
  420. static void backpatch_module_image(uchar *p,
  421. int marker_value, int zmachine_area, int32 offset)
  422. { int size = (marker_value>=0x80)?1:2; int32 v;
  423. marker_value &= 0x7f;
  424. backpatch_marker = marker_value;
  425. if (zmachine_area == PROP_DEFAULTS_ZA) return;
  426. if (linker_trace_level >= 3)
  427. printf("Backpatch %s area %d offset %04x size %d: ",
  428. describe_mv(marker_value), zmachine_area, offset, size);
  429. v = read_marker_address(p, size, zmachine_area, offset);
  430. if (linker_trace_level >= 3) printf("%04x ", v);
  431. v = backpatch_backpatch(v);
  432. write_marker_address(p, size, zmachine_area, offset, v);
  433. if (linker_trace_level >= 3) printf("%04x\n", v);
  434. }
  435. /* ------------------------------------------------------------------------- */
  436. /* The main routine: linking in a module with the given filename. */
  437. /* ------------------------------------------------------------------------- */
  438. char current_module_filename[128];
  439. void link_module(char *given_filename)
  440. { FILE *fin;
  441. int record_type;
  442. char filename[128];
  443. uchar *p, p0[64];
  444. int32 last, i, j, k, l, m, vn, len, size, link_offset, module_size, map,
  445. max_property_identifier, symbols_base = no_symbols;
  446. strcpy(current_module_filename, given_filename);
  447. /* (1) Load in the module to link */
  448. i = 0;
  449. do
  450. { i = translate_link_filename(i, filename, given_filename);
  451. fin=fopen(filename,"rb");
  452. } while ((fin == NULL) && (i != 0));
  453. if (fin==NULL)
  454. { error_named("Couldn't open module file", filename); return;
  455. }
  456. for (i=0;i<64;i++) p0[i]=fgetc(fin);
  457. vn = p0[0];
  458. if ((vn<65) || (vn>75))
  459. { error_named("File isn't a module:", filename);
  460. fclose(fin); return;
  461. }
  462. if (vn != 64 + version_number)
  463. { char ebuff[100];
  464. sprintf(ebuff,
  465. "module compiled as Version %d (so it can't link\
  466. into this V%d game):", vn-64, version_number);
  467. error_named(ebuff, filename);
  468. fclose(fin); return;
  469. }
  470. module_size = (256*p0[26] + p0[27])*scale_factor;
  471. p = my_malloc(module_size + 16, "link module storage");
  472. /* The + 16 allows for rounding errors */
  473. for (k=0;k<64;k++) p[k] = p0[k];
  474. for (k=64;k<module_size;k++) p[k] = fgetc(fin);
  475. fclose(fin);
  476. if ((p0[52] != 0) || (p0[53] != 0))
  477. { /* Then the module contains a character set table */
  478. if (alphabet_modified)
  479. { k = FALSE; m = 256*p0[52] + p0[53];
  480. for (i=0;i<3;i++) for (j=0;j<26;j++)
  481. { l = alphabet[i][j]; if (l == '~') l = '\"';
  482. if (l != p[m]) k = TRUE;
  483. }
  484. if (k)
  485. link_error("module and game both define non-standard character sets, \
  486. but they disagree");
  487. k = FALSE;
  488. }
  489. else k = TRUE;
  490. }
  491. else
  492. { if (alphabet_modified) k = TRUE;
  493. else k = FALSE;
  494. }
  495. if (k)
  496. link_error("module and game use different character sets");
  497. i = p[1];
  498. if (i > MODULE_VERSION_NUMBER)
  499. warning_named("module has a more advanced format than this release \
  500. of the Inform 6 compiler knows about: it may not link in correctly", filename);
  501. /* (2) Calculate offsets: see the header-writing code in "tables.c" */
  502. map = (256*p[6] + p[7]);
  503. for (i=0; i<16; i++) module_map[i] = 256*p[map + i*2] + p[map + i*2 + 1];
  504. m_vars_offset = (256*p[12] + p[13]);
  505. m_static_offset = (256*p[14] + p[15]);
  506. m_dict_offset = (256*p[8] + p[9]);
  507. m_code_offset = (256*p[4] + p[5]);
  508. /* (3) Read the "module map" table */
  509. if (linker_trace_level>=4)
  510. { printf("[Reading module map:\n");
  511. for (i=0; i<16; i++) printf("%04x ", module_map[i]);
  512. printf("]\n");
  513. }
  514. m_objs_offset = module_map[0];
  515. m_props_offset = module_map[1];
  516. m_strs_offset = scale_factor*module_map[2];
  517. m_class_numbers = module_map[3];
  518. m_individuals_offset = module_map[4];
  519. m_individuals_length = module_map[5];
  520. for (i=16;i<256;i++) variables_map[i] = -1;
  521. for (i=0;i<16;i++) variables_map[i] = i;
  522. for (i=LOWEST_SYSTEM_VAR_NUMBER;i<256;i++) variables_map[i] = i;
  523. for (i=0;i<256;i++) actions_map[i] = -1;
  524. xref_table = my_calloc(sizeof(int32), module_map[6],
  525. "linker cross-references table");
  526. for (i=0;i<module_map[6];i++) xref_table[i] = -1;
  527. max_property_identifier = module_map[7];
  528. property_identifier_map = my_calloc(sizeof(int32), max_property_identifier,
  529. "property identifier map");
  530. for (i=0; i<max_property_identifier; i++)
  531. property_identifier_map[i] = i;
  532. m_no_objects = module_map[8];
  533. link_offset = module_map[9];
  534. m_no_globals = 0; p_no_globals = no_globals;
  535. lowest_imported_global_no=236;
  536. no_rr = 0;
  537. if ((linker_trace_level>=1) || transcript_switch)
  538. { char link_banner[128];
  539. sprintf(link_banner,
  540. "[Linking release %d.%c%c%c%c%c%c of module '%s' (size %dK)]",
  541. p[2]*256 + p[3], p[18], p[19], p[20], p[21], p[22], p[23],
  542. filename, module_size/1024);
  543. if (linker_trace_level >= 1) printf("%s\n", link_banner);
  544. if (transcript_switch)
  545. write_to_transcript_file(link_banner);
  546. }
  547. /* (4) Merge in the dictionary */
  548. if (linker_trace_level >= 2)
  549. printf("Merging module's dictionary at %04x\n", m_dict_offset);
  550. k=m_dict_offset; k+=p[k]+1;
  551. len=p[k++];
  552. size = p[k]*256 + p[k+1]; k+=2;
  553. accession_numbers_map = my_calloc(sizeof(int), size,
  554. "dictionary accession numbers map");
  555. for (i=0;i<size;i++, k+=len)
  556. { char word[10];
  557. word_to_ascii(p+k,word);
  558. if (linker_trace_level >= 3)
  559. printf("%03d %04x '%s' %02x %02x %02x\n",i,k,
  560. word, p[k+len-3], p[k+len-2], p[k+len-1]);
  561. accession_numbers_map[i]
  562. = dictionary_add(word, p[k+len-3], p[k+len-2], p[k+len-1]);
  563. }
  564. /* (5) Run through import/export table */
  565. m_read_pos = module_map[9];
  566. if (linker_trace_level>=2)
  567. printf("Import/export table is at byte offset %04x\n", m_read_pos);
  568. do
  569. { record_type = get_next_record(p);
  570. if (((record_type == EXPORT_MV) || (record_type == EXPORTSF_MV))
  571. && (IE.symbol_type == INDIVIDUAL_PROPERTY_T))
  572. { int32 si = symbol_index(IE.symbol_name, -1);
  573. property_identifier_map[IE.symbol_value] = svals[si];
  574. }
  575. switch(record_type)
  576. { case EXPORT_MV:
  577. case EXPORTSF_MV:
  578. case EXPORTAC_MV:
  579. accept_export(); break;
  580. case IMPORT_MV:
  581. accept_import(); break;
  582. }
  583. } while (record_type != 0);
  584. if ((linker_trace_level >= 4) && (no_rr != 0))
  585. { printf("Replaced routine addresses:\n");
  586. for (i=0; i<no_rr; i++)
  587. { printf("Replace code offset %04x with %04x\n",
  588. routine_replace[i], routine_replace_with[i]);
  589. }
  590. }
  591. if (linker_trace_level >= 4)
  592. { printf("Symbol cross-references table:\n");
  593. for (i=0; i<module_map[6]; i++)
  594. { if (xref_table[i] != -1)
  595. printf("module %4d -> story file '%s'\n", i,
  596. (char *) symbs[xref_table[i]]);
  597. }
  598. }
  599. if (linker_trace_level >= 4)
  600. { printf("Action numbers map:\n");
  601. for (i=0; i<256; i++)
  602. if (actions_map[i] != -1)
  603. printf("%3d -> %3d\n", i, actions_map[i]);
  604. }
  605. if ((linker_trace_level >= 4) && (max_property_identifier > 72))
  606. { printf("Property identifier number map:\n");
  607. for (i=72; i<max_property_identifier; i++)
  608. { printf("module %04x -> program %04x\n",
  609. i, property_identifier_map[i]);
  610. }
  611. }
  612. /* (6) Backpatch the backpatch markers attached to exported symbols */
  613. for (i=symbols_base; i<no_symbols; i++)
  614. { if ((sflags[i] & CHANGE_SFLAG) && (sflags[i] & EXPORT_SFLAG))
  615. { backpatch_marker = svals[i]/0x10000;
  616. j = svals[i] % 0x10000;
  617. j = backpatch_backpatch(j);
  618. svals[i] = backpatch_marker*0x10000 + j;
  619. if (backpatch_marker == 0) sflags[i] &= (~(CHANGE_SFLAG));
  620. }
  621. }
  622. /* (7) Run through the Z-code backpatch table */
  623. for (i=module_map[11]; i<module_map[11]+module_map[12]; i += 3)
  624. { int marker_value = p[i];
  625. int32 offset = 256*p[i+1] + p[i+2];
  626. switch(marker_value & 0x7f)
  627. { case OBJECT_MV:
  628. case ACTION_MV:
  629. case IDENT_MV:
  630. case VARIABLE_MV:
  631. backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
  632. break;
  633. default:
  634. backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
  635. write_byte_to_memory_block(&zcode_backpatch_table,
  636. zcode_backpatch_size++, backpatch_marker);
  637. write_byte_to_memory_block(&zcode_backpatch_table,
  638. zcode_backpatch_size++, (offset + zmachine_pc)/256);
  639. write_byte_to_memory_block(&zcode_backpatch_table,
  640. zcode_backpatch_size++, (offset + zmachine_pc)%256);
  641. break;
  642. }
  643. }
  644. /* (8) Run through the Z-machine backpatch table */
  645. for (i=module_map[13]; i<module_map[13]+module_map[14]; i += 4)
  646. { int marker_value = p[i], zmachine_area = p[i+1];
  647. int32 offset = 256*p[i+2] + p[i+3];
  648. switch(marker_value)
  649. { case OBJECT_MV:
  650. case ACTION_MV:
  651. case IDENT_MV:
  652. backpatch_module_image(p, marker_value, zmachine_area, offset);
  653. break;
  654. default:
  655. backpatch_module_image(p, marker_value, zmachine_area, offset);
  656. switch(zmachine_area)
  657. { case PROP_DEFAULTS_ZA:
  658. break;
  659. case PROP_ZA:
  660. offset += properties_table_size; break;
  661. case INDIVIDUAL_PROP_ZA:
  662. offset += individuals_length; break;
  663. case DYNAMIC_ARRAY_ZA:
  664. if (offset < (MAX_GLOBAL_VARIABLES*2))
  665. { offset = 2*(variables_map[offset/2 + 16] - 16);
  666. }
  667. else
  668. { offset += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
  669. }
  670. break;
  671. }
  672. backpatch_zmachine(backpatch_marker, zmachine_area, offset);
  673. break;
  674. }
  675. }
  676. /* (9) Adjust initial values of variables */
  677. if (linker_trace_level >= 3)
  678. printf("\nFinal variables map, Module -> Main:\n");
  679. for (i=16;i<255;i++)
  680. if (variables_map[i]!=-1)
  681. { if (linker_trace_level>=2)
  682. printf("%d->%d ",i,variables_map[i]);
  683. if (i<lowest_imported_global_no)
  684. { int32 j = read_marker_address(p, 2,
  685. DYNAMIC_ARRAY_ZA, 2*(i-16));
  686. set_variable_value(variables_map[i]-16, j);
  687. if (linker_trace_level>=2)
  688. printf("(set var %d to %d) ",
  689. variables_map[i], j);
  690. }
  691. }
  692. if (linker_trace_level>=2) printf("\n");
  693. /* (10) Glue in the dynamic array data */
  694. i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
  695. if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
  696. memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
  697. if (linker_trace_level >= 2)
  698. printf("Inserting dynamic array area, %04x to %04x, at %04x\n",
  699. m_vars_offset + MAX_GLOBAL_VARIABLES*2, m_static_offset,
  700. variables_offset + dynamic_array_area_size);
  701. for (k=0;k<i;k++)
  702. { dynamic_array_area[dynamic_array_area_size+k]
  703. = p[m_vars_offset+MAX_GLOBAL_VARIABLES*2+k];
  704. }
  705. dynamic_array_area_size+=i;
  706. /* (11) Glue in the code area */
  707. if (linker_trace_level >= 2)
  708. printf("Inserting code area, %04x to %04x, at code offset %04x (+%04x)\n",
  709. m_code_offset, m_strs_offset, code_offset, zmachine_pc);
  710. for (k=m_code_offset;k<m_strs_offset;k++)
  711. { if (temporary_files_switch)
  712. { fputc(p[k],Temp2_fp);
  713. zmachine_pc++;
  714. }
  715. else
  716. write_byte_to_memory_block(&zcode_area, zmachine_pc++, p[k]);
  717. }
  718. /* (12) Glue in the static strings area */
  719. if (linker_trace_level >= 2)
  720. printf("Inserting strings area, %04x to %04x, \
  721. at strings offset %04x (+%04x)\n",
  722. m_strs_offset, link_offset, strings_offset,
  723. static_strings_extent);
  724. for (k=m_strs_offset;k<link_offset;k++)
  725. { if (temporary_files_switch)
  726. { fputc(p[k], Temp1_fp);
  727. static_strings_extent++;
  728. }
  729. else
  730. write_byte_to_memory_block(&static_strings_area,
  731. static_strings_extent++, p[k]);
  732. }
  733. /* (13) Append the class object-numbers table: note that modules
  734. provide extra information in this table */
  735. i = m_class_numbers;
  736. do
  737. { j = p[i]*256 + p[i+1]; i+=2;
  738. if (j == 0) break;
  739. class_object_numbers[no_classes] = j + no_objects;
  740. j = p[i]*256 + p[i+1]; i+=2;
  741. class_begins_at[no_classes++] = j + properties_table_size;
  742. } while (TRUE);
  743. /* (14) Glue on the object tree */
  744. if ((linker_trace_level>=2) && (m_no_objects>0))
  745. printf("Joining on object tree of size %d\n", m_no_objects);
  746. for (i=0, k=no_objects, last=m_props_offset;i<m_no_objects;i++)
  747. { objectsz[no_objects].atts[0]=p[m_objs_offset+14*i];
  748. objectsz[no_objects].atts[1]=p[m_objs_offset+14*i+1];
  749. objectsz[no_objects].atts[2]=p[m_objs_offset+14*i+2];
  750. objectsz[no_objects].atts[3]=p[m_objs_offset+14*i+3];
  751. objectsz[no_objects].atts[4]=p[m_objs_offset+14*i+4];
  752. objectsz[no_objects].atts[5]=p[m_objs_offset+14*i+5];
  753. objectsz[no_objects].parent =
  754. (p[m_objs_offset+14*i+6])*256+p[m_objs_offset+14*i+7];
  755. objectsz[no_objects].next =
  756. (p[m_objs_offset+14*i+8])*256+p[m_objs_offset+14*i+9];
  757. objectsz[no_objects].child =
  758. (p[m_objs_offset+14*i+10])*256+p[m_objs_offset+14*i+11];
  759. if (linker_trace_level>=4)
  760. printf("Module objects[%d] has %d,%d,%d\n",
  761. i,objectsz[no_objects].parent,
  762. objectsz[no_objects].next,objectsz[no_objects].child);
  763. if (objectsz[no_objects].parent == 0x7fff)
  764. { objectsz[no_objects].parent = 1;
  765. if (objectsz[1].child == 0)
  766. { objectsz[1].child = no_objects+1;
  767. }
  768. else
  769. { int j1, j2 = objectsz[1].child;
  770. while (j2 != 0)
  771. { j1 = j2;
  772. j2 = objectsz[j2].next;
  773. }
  774. objectsz[j1].next = no_objects+1;
  775. }
  776. objectsz[no_objects].next = 0;
  777. }
  778. else
  779. if (objectsz[no_objects].parent>0) objectsz[no_objects].parent += k;
  780. if (objectsz[no_objects].next>0) objectsz[no_objects].next += k;
  781. if (objectsz[no_objects].child>0) objectsz[no_objects].child += k;
  782. objectsz[no_objects].propsize =
  783. (p[m_objs_offset+14*i+12])*256+p[m_objs_offset+14*i+13];
  784. last += objectsz[no_objects].propsize;
  785. if (linker_trace_level>=4)
  786. printf("Objects[%d] has %d,%d,%d\n",
  787. no_objects,objectsz[no_objects].parent,
  788. objectsz[no_objects].next,objectsz[no_objects].child);
  789. no_objects++;
  790. }
  791. /* (15) Glue on the properties */
  792. if (last>m_props_offset)
  793. { i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
  794. if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
  795. memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
  796. if (linker_trace_level >= 2)
  797. printf("Inserting object properties area, %04x to %04x, at +%04x\n",
  798. m_props_offset, last, properties_table_size);
  799. for (k=0;k<last-m_props_offset;k++)
  800. properties_table[properties_table_size++] = p[m_props_offset+k];
  801. }
  802. /* (16) Bitwise OR Flags 2 (Z-machine requirements flags) */
  803. j = p[16]*256 + p[17];
  804. for (i=0, k=1;i<16;i++, k=k*2) flags2_requirements[i] |= ((j/k)%2);
  805. /* (17) Append the individual property values table */
  806. i = m_individuals_length;
  807. if (individuals_length + i >= MAX_INDIV_PROP_TABLE_SIZE)
  808. memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
  809. MAX_INDIV_PROP_TABLE_SIZE);
  810. if (linker_trace_level >= 2)
  811. printf("Inserting individual prop tables area, %04x to %04x, at +%04x\n",
  812. m_individuals_offset, m_individuals_offset + i,
  813. individuals_length);
  814. for (k=0;k<i;k++)
  815. { individuals_table[individuals_length + k]
  816. = p[m_individuals_offset + k];
  817. }
  818. individuals_length += i;
  819. /* (18) All done */
  820. if (linker_trace_level >= 2)
  821. printf("Link complete\n");
  822. my_free(&p, "link module storage");
  823. my_free(&xref_table, "linker cross-references table");
  824. my_free(&property_identifier_map, "property identifier map");
  825. my_free(&accession_numbers_map, "accession numbers map");
  826. }
  827. /* ========================================================================= */
  828. /* Writing imports, exports and markers to the link data table during */
  829. /* module compilation */
  830. /* ------------------------------------------------------------------------- */
  831. /* Writing to the link data table */
  832. /* ------------------------------------------------------------------------- */
  833. static void write_link_byte(int x)
  834. { *link_data_top=(unsigned char) x; link_data_top++; link_data_size++;
  835. if (subtract_pointers(link_data_top,link_data_holding_area)
  836. >= MAX_LINK_DATA_SIZE)
  837. { memoryerror("MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE);
  838. }
  839. }
  840. extern void flush_link_data(void)
  841. { int32 i, j;
  842. j = subtract_pointers(link_data_top, link_data_holding_area);
  843. if (temporary_files_switch)
  844. for (i=0;i<j;i++) fputc(link_data_holding_area[i], Temp3_fp);
  845. else
  846. for (i=0;i<j;i++)
  847. write_byte_to_memory_block(&link_data_area, link_data_size-j+i,
  848. link_data_holding_area[i]);
  849. link_data_top=link_data_holding_area;
  850. }
  851. static void write_link_word(int32 x)
  852. { write_link_byte(x/256); write_link_byte(x%256);
  853. }
  854. static void write_link_string(char *s)
  855. { int i;
  856. for (i=0; s[i]!=0; i++) write_link_byte(s[i]);
  857. write_link_byte(0);
  858. }
  859. /* ------------------------------------------------------------------------- */
  860. /* Exports and imports */
  861. /* ------------------------------------------------------------------------- */
  862. static void export_symbols(void)
  863. { int symbol_number;
  864. for (symbol_number = 0; symbol_number < no_symbols; symbol_number++)
  865. { int export_flag = FALSE, import_flag = FALSE;
  866. if (stypes[symbol_number]==GLOBAL_VARIABLE_T)
  867. { if (svals[symbol_number] < LOWEST_SYSTEM_VAR_NUMBER)
  868. { if (sflags[symbol_number] & IMPORT_SFLAG)
  869. import_flag = TRUE;
  870. else
  871. if (!(sflags[symbol_number] & SYSTEM_SFLAG))
  872. export_flag = TRUE;
  873. }
  874. }
  875. else
  876. { if (!(sflags[symbol_number] & SYSTEM_SFLAG))
  877. { if (sflags[symbol_number] & UNKNOWN_SFLAG)
  878. { if (sflags[symbol_number] & IMPORT_SFLAG)
  879. import_flag = TRUE;
  880. }
  881. else
  882. switch(stypes[symbol_number])
  883. { case LABEL_T:
  884. case ATTRIBUTE_T:
  885. case PROPERTY_T:
  886. /* Ephemera */
  887. break;
  888. default: export_flag = TRUE;
  889. }
  890. }
  891. }
  892. if (export_flag)
  893. { if (linker_trace_level >= 1)
  894. { IE.module_value = EXPORT_MV;
  895. IE.symbol_number = symbol_number;
  896. IE.symbol_type = stypes[symbol_number];
  897. IE.symbol_value = svals[symbol_number];
  898. IE.symbol_name = (char *) (symbs[symbol_number]);
  899. describe_importexport(&IE);
  900. }
  901. if (sflags[symbol_number] & ACTION_SFLAG)
  902. write_link_byte(EXPORTAC_MV);
  903. else
  904. if (sflags[symbol_number] & INSF_SFLAG)
  905. write_link_byte(EXPORTSF_MV);
  906. else
  907. write_link_byte(EXPORT_MV);
  908. write_link_word(symbol_number);
  909. write_link_byte(stypes[symbol_number]);
  910. if (sflags[symbol_number] & CHANGE_SFLAG)
  911. write_link_byte(svals[symbol_number] / 0x10000);
  912. else write_link_byte(0);
  913. write_link_word(svals[symbol_number] % 0x10000);
  914. write_link_string((char *) (symbs[symbol_number]));
  915. flush_link_data();
  916. }
  917. if (import_flag)
  918. { if (linker_trace_level >= 1)
  919. { IE.module_value = IMPORT_MV;
  920. IE.symbol_number = symbol_number;
  921. IE.symbol_type = stypes[symbol_number];
  922. IE.symbol_value = svals[symbol_number];
  923. IE.symbol_name = (char *) (symbs[symbol_number]);
  924. describe_importexport(&IE);
  925. }
  926. write_link_byte(IMPORT_MV);
  927. write_link_word(symbol_number);
  928. write_link_byte(stypes[symbol_number]);
  929. write_link_word(svals[symbol_number]);
  930. write_link_string((char *) (symbs[symbol_number]));
  931. flush_link_data();
  932. }
  933. }
  934. }
  935. /* ------------------------------------------------------------------------- */
  936. /* Marking for later importation */
  937. /* ------------------------------------------------------------------------- */
  938. int mv_vref=LOWEST_SYSTEM_VAR_NUMBER-1;
  939. void import_symbol(int32 symbol_number)
  940. { sflags[symbol_number] |= IMPORT_SFLAG;
  941. switch(stypes[symbol_number])
  942. { case GLOBAL_VARIABLE_T:
  943. assign_symbol(symbol_number, mv_vref--, stypes[symbol_number]);
  944. break;
  945. }
  946. }
  947. /* ========================================================================= */
  948. /* Data structure management routines */
  949. /* ------------------------------------------------------------------------- */
  950. extern void init_linker_vars(void)
  951. { link_data_size = 0;
  952. initialise_memory_block(&link_data_area);
  953. }
  954. extern void linker_begin_pass(void)
  955. { link_data_top = link_data_holding_area;
  956. }
  957. extern void linker_endpass(void)
  958. { export_symbols();
  959. write_link_byte(0);
  960. flush_link_data();
  961. }
  962. extern void linker_allocate_arrays(void)
  963. { if (!module_switch)
  964. link_data_holding_area
  965. = my_malloc(64, "link data holding area");
  966. else
  967. link_data_holding_area
  968. = my_malloc(MAX_LINK_DATA_SIZE, "link data holding area");
  969. }
  970. extern void linker_free_arrays(void)
  971. { my_free(&link_data_holding_area, "link data holding area");
  972. deallocate_memory_block(&link_data_area);
  973. }
  974. /* ========================================================================= */