Sync with upstream
[inform.git] / tables.c
1 /* ------------------------------------------------------------------------- */
2 /*   "tables" :  Constructs the story file or module (the output) up to the  */
3 /*               end of dynamic memory, gluing together all the required     */
4 /*               tables.                                                     */
5 /*                                                                           */
6 /* Copyright (c) Graham Nelson 1993 - 2018                                   */
7 /*                                                                           */
8 /* This file is part of Inform.                                              */
9 /*                                                                           */
10 /* Inform is free software: you can redistribute it and/or modify            */
11 /* it under the terms of the GNU General Public License as published by      */
12 /* the Free Software Foundation, either version 3 of the License, or         */
13 /* (at your option) any later version.                                       */
14 /*                                                                           */
15 /* Inform is distributed in the hope that it will be useful,                 */
16 /* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
17 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
18 /* GNU General Public License for more details.                              */
19 /*                                                                           */
20 /* You should have received a copy of the GNU General Public License         */
21 /* along with Inform. If not, see https://gnu.org/licenses/                  */
22 /*                                                                           */
23 /* ------------------------------------------------------------------------- */
24
25 #include "header.h"
26
27 uchar *zmachine_paged_memory;          /* Where we shall store the story file
28                                           constructed (contains all of paged
29                                           memory, i.e. all but code and the
30                                           static strings: allocated only when
31                                           we know how large it needs to be,
32                                           at the end of the compilation pass */
33
34 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
35    the header, the code, and the static strings. */
36
37 /* ------------------------------------------------------------------------- */
38 /*   Offsets of various areas in the Z-machine: these are set to nominal     */
39 /*   values before the compilation pass, and to their calculated final       */
40 /*   values only when construct_storyfile() happens.  These are then used to */
41 /*   backpatch the incorrect values now existing in the Z-machine which      */
42 /*   used these nominal values.                                              */
43 /*   Most of the nominal values are 0x800 because this is guaranteed to      */
44 /*   be assembled as a long constant if it's needed in code, since the       */
45 /*   largest possible value of scale_factor is 8 and 0x800/8 = 256.          */
46 /*                                                                           */
47 /*   In Glulx, I use 0x12345 instead of 0x800. This will always be a long    */
48 /*   (32-bit) constant, since there's no scale_factor.                       */
49 /* ------------------------------------------------------------------------- */
50
51 int32 code_offset,
52       actions_offset,
53       preactions_offset,
54       dictionary_offset,
55       adjectives_offset,
56       variables_offset,
57       strings_offset,
58       class_numbers_offset,
59       individuals_offset,
60       identifier_names_offset,
61       array_names_offset,
62       prop_defaults_offset,
63       prop_values_offset,
64       static_memory_offset,
65       attribute_names_offset,
66       action_names_offset,
67       fake_action_names_offset,
68       routine_names_offset,
69       constant_names_offset,
70       routines_array_offset,
71       constants_array_offset,
72       routine_flags_array_offset,
73       global_names_offset,
74       global_flags_array_offset,
75       array_flags_array_offset;
76 int32 arrays_offset,
77       object_tree_offset,
78       grammar_table_offset,
79       abbreviations_offset; /* Glulx */
80
81 int32 Out_Size, Write_Code_At, Write_Strings_At;
82 int32 RAM_Size, Write_RAM_At; /* Glulx */
83
84 /* ------------------------------------------------------------------------- */
85 /*   Story file header settings.   (Written to in "directs.c" and "asm.c".)  */
86 /* ------------------------------------------------------------------------- */
87
88 int release_number,                    /* Release number game is to have     */
89     statusline_flag;                   /* Either TIME_STYLE or SCORE_STYLE   */
90
91 int serial_code_given_in_program       /* If TRUE, a Serial directive has    */
92     = FALSE;                           /* specified this 6-digit serial code */
93 char serial_code_buffer[7];            /* (overriding the usual date-stamp)  */
94 int flags2_requirements[16];           /* An array of which bits in Flags 2 of
95                                           the header will need to be set:
96                                           e.g. if the save_undo / restore_undo
97                                           opcodes are ever assembled, we have
98                                           to set the "games want UNDO" bit.
99                                           Values are 0 or 1.                 */
100
101 /* ------------------------------------------------------------------------- */
102 /*   Construct story/module file (up to code area start).                    */
103 /*                                                                           */
104 /*   (To understand what follows, you really need to look at the run-time    */
105 /*   system's specification, the Z-Machine Standards document.)              */
106 /* ------------------------------------------------------------------------- */
107
108 extern void write_serial_number(char *buffer)
109 {
110     /*  Note that this function may require modification for "ANSI" compilers
111         which do not provide the standard time functions: what is needed is
112         the ability to work out today's date                                 */
113
114     time_t tt;  tt=time(0);
115     if (serial_code_given_in_program)
116         strcpy(buffer, serial_code_buffer);
117     else
118 #ifdef TIME_UNAVAILABLE
119         sprintf(buffer,"970000");
120 #else
121         strftime(buffer,10,"%y%m%d",localtime(&tt));
122 #endif
123 }
124
125 static void percentage(char *name, int32 x, int32 total)
126 {   printf("   %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10);
127 }
128
129 static char *version_name(int v)
130 {
131   if (!glulx_mode) {
132     switch(v)
133     {   case 3: return "Standard";
134         case 4: return "Plus";
135         case 5: return "Advanced";
136         case 6: return "Graphical";
137         case 8: return "Extended";
138     }
139     return "experimental format";
140   }
141   else {
142     return "Glulx";
143   }
144 }
145
146 static int32 rough_size_of_paged_memory_z(void)
147 {
148     /*  This function calculates a modest over-estimate of the amount of
149         memory required to store the Z-machine's paged memory area
150         (that is, everything up to the start of the code area).              */
151
152     int32 total, i;
153
154     ASSERT_ZCODE();
155
156     total = 64                                                     /* header */
157             + 2 + subtract_pointers(low_strings_top, low_strings)
158                                                          /* low strings pool */
159             + 6*32;                                   /* abbreviations table */
160
161     total += 8;                                    /* header extension table */
162     if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2;
163
164     if (alphabet_modified) total += 78;               /* character set table */
165
166     if (zscii_defn_modified)                    /* Unicode translation table */
167         total += 2 + 2*zscii_high_water_mark;
168
169     total += 2*((version_number==3)?31:63)        /* property default values */
170             + no_objects*((version_number==3)?9:14)     /* object tree table */
171             + properties_table_size            /* property values of objects */
172             + (no_classes+1)*(module_switch?4:2)
173                                                /* class object numbers table */
174             + no_symbols*2                       /* names of numerous things */
175             + individuals_length                 /* tables of prop variables */
176             + dynamic_array_area_size;               /* variables and arrays */
177
178     for (i=0; i<no_Inform_verbs; i++)
179         total += 2 + 1 +                        /* address of grammar table, */
180                                                   /* number of grammar lines */
181                  ((grammar_version_number == 1)?
182                   (8*Inform_verbs[i].lines):0);             /* grammar lines */
183
184     if (grammar_version_number != 1)
185         total += grammar_lines_top;            /* size of grammar lines area */
186
187     total +=  2 + 4*no_adjectives                        /* adjectives table */
188               + 2*no_actions                              /* action routines */
189               + 2*no_grammar_token_routines;     /* general parsing routines */
190
191     total += (subtract_pointers(dictionary_top, dictionary))  /* dictionary */
192              + ((module_switch)?30:0);                        /* module map */
193
194     total += scale_factor*0x100            /* maximum null bytes before code */
195             + 1000;             /* fudge factor (in case the above is wrong) */
196
197     return(total);
198 }
199
200 static int32 rough_size_of_paged_memory_g(void)
201 {
202     /*  This function calculates a modest over-estimate of the amount of
203         memory required to store the machine's paged memory area
204         (that is, everything up to the start of the code area).              */
205
206     int32 total;
207
208     ASSERT_GLULX();
209
210     /* No header for us! */
211     total = 1000; /* bit of a fudge factor */
212
213     total += dynamic_array_area_size; /* arrays and global variables */
214
215     total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
216     total += properties_table_size; /* property tables */
217     total += no_properties * 4; /* property defaults table */
218
219     total += 4 + no_classes * 4; /* class prototype object numbers */
220
221     total += 32; /* address/length of the identifier tables */
222     total += no_properties * 4;
223     total += (no_individual_properties-INDIV_PROP_START) * 4;
224     total += (NUM_ATTR_BYTES*8) * 4;
225     total += (no_actions + no_fake_actions) * 4;
226     total += 4 + no_arrays * 4;
227
228     total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
229     total += grammar_lines_top; /* grammar tables */
230
231     total += 4 + no_actions * 4; /* actions functions table */
232
233     total += 4;
234     total += subtract_pointers(dictionary_top, dictionary);
235
236     while (total % GPAGESIZE)
237       total++;
238
239     return(total);
240 }
241
242 static void construct_storyfile_z(void)
243 {   uchar *p;
244     int32 i, j, k, l, mark, objs, strings_length, code_length,
245           limit=0, excess=0, extend_offset=0, headerext_length=0;
246     int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
247           abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
248           map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
249           terminating_chars_at=0, unicode_at=0, id_names_length=0;
250     int skip_backpatching = FALSE;
251     char *output_called = (module_switch)?"module":"story file";
252
253     ASSERT_ZCODE();
254
255     individual_name_strings =
256         my_calloc(sizeof(int32), no_individual_properties,
257             "identifier name strings");
258     action_name_strings =
259         my_calloc(sizeof(int32), no_actions + no_fake_actions,
260             "action name strings");
261     attribute_name_strings =
262         my_calloc(sizeof(int32), 48,
263             "attribute name strings");
264     array_name_strings =
265         my_calloc(sizeof(int32),
266             no_symbols,
267             "array name strings");
268
269     write_the_identifier_names();
270
271     /*  We now know how large the buffer to hold our construction has to be  */
272
273     zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
274         "output buffer");
275
276     /*  Foolish code to make this routine compile on all ANSI compilers      */
277
278     p = (uchar *) zmachine_paged_memory;
279
280     /*  In what follows, the "mark" will move upwards in memory: at various
281         points its value will be recorded for milestones like
282         "dictionary table start".  It begins at 0x40, just after the header  */
283
284     mark = 0x40;
285
286     /*  ----------------- Low Strings and Abbreviations -------------------- */
287
288     p[mark]=0x80; p[mark+1]=0; mark+=2;        /* Start the low strings pool
289                                          with a useful default string, "   " */
290
291     for (i=0; i+low_strings<low_strings_top; mark++, i++) /* Low strings pool */
292         p[0x42+i]=low_strings[i];
293
294     abbrevs_at = mark;
295     for (i=0; i<3*32; i++)                       /* Initially all 96 entries */
296     {   p[mark++]=0; p[mark++]=0x20;                     /* are set to "   " */
297     }
298     for (i=0; i<no_abbreviations; i++)            /* Write any abbreviations */
299     {   j=abbrev_values[i];                            /* into banks 2 and 3 */
300         p[abbrevs_at+64+2*i]=j/256;               /* (bank 1 is reserved for */
301         p[abbrevs_at+65+2*i]=j%256;                   /* "variable strings") */
302     }
303
304     /*  ------------------- Header extension table ------------------------- */
305
306     headerext_at = mark;
307     headerext_length = ZCODE_HEADER_EXT_WORDS;
308     if (zscii_defn_modified) {
309         /* Need at least 3 words for unicode table address */
310         if (headerext_length < 3)
311             headerext_length = 3;
312     }
313     if (ZCODE_HEADER_FLAGS_3) {
314         /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
315         if (headerext_length < 4)
316             headerext_length = 4;
317     }
318     p[mark++] = 0; p[mark++] = headerext_length;
319     for (i=0; i<headerext_length; i++)
320     {   p[mark++] = 0; p[mark++] = 0;
321     }
322
323     /*  -------------------- Z-character set table ------------------------- */
324
325     if (alphabet_modified)
326     {   charset_at = mark;
327         for (i=0;i<3;i++) for (j=0;j<26;j++)
328         {   if (alphabet[i][j] == '~') p[mark++] = '\"';
329             else p[mark++] = alphabet[i][j];
330         }
331     }
332
333     /*  ------------------ Unicode translation table ----------------------- */
334
335     unicode_at = 0;
336     if (zscii_defn_modified)
337     {   unicode_at = mark;
338         p[mark++] = zscii_high_water_mark;
339         for (i=0;i<zscii_high_water_mark;i++)
340         {   j = zscii_to_unicode(155 + i);
341             if (j < 0 || j > 0xFFFF) {
342                 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
343             }
344             p[mark++] = j/256; p[mark++] = j%256;
345         }
346     }
347
348     /*  -------------------- Objects and Properties ------------------------ */
349
350     /* The object table must be word-aligned. The Z-machine spec does not
351        require this, but the RA__Pr() veneer routine does. See 
352        http://inform7.com/mantis/view.php?id=1712.
353     */
354     while ((mark%2) != 0) p[mark++]=0;
355
356     prop_defaults_at = mark;
357
358     p[mark++]=0; p[mark++]=0;
359
360     for (i=2; i< ((version_number==3)?32:64); i++)
361     {   p[mark++]=prop_default_value[i]/256;
362         p[mark++]=prop_default_value[i]%256;
363     }
364
365     object_tree_at = mark;
366
367     mark += ((version_number==3)?9:14)*no_objects;
368
369     object_props_at = mark;
370
371     for (i=0; i<properties_table_size; i++)
372         p[mark+i]=properties_table[i];
373
374     for (i=0, objs=object_tree_at; i<no_objects; i++)
375     {
376         if (version_number == 3)
377         {   p[objs]=objectsz[i].atts[0];
378             p[objs+1]=objectsz[i].atts[1];
379             p[objs+2]=objectsz[i].atts[2];
380             p[objs+3]=objectsz[i].atts[3];
381             p[objs+4]=objectsz[i].parent;
382             p[objs+5]=objectsz[i].next;
383             p[objs+6]=objectsz[i].child;
384             p[objs+7]=mark/256;
385             p[objs+8]=mark%256;
386             objs+=9;
387         }
388         else
389         {   p[objs]=objectsz[i].atts[0];
390             p[objs+1]=objectsz[i].atts[1];
391             p[objs+2]=objectsz[i].atts[2];
392             p[objs+3]=objectsz[i].atts[3];
393             p[objs+4]=objectsz[i].atts[4];
394             p[objs+5]=objectsz[i].atts[5];
395             p[objs+6]=(objectsz[i].parent)/256;
396             p[objs+7]=(objectsz[i].parent)%256;
397             p[objs+8]=(objectsz[i].next)/256;
398             p[objs+9]=(objectsz[i].next)%256;
399             p[objs+10]=(objectsz[i].child)/256;
400             p[objs+11]=(objectsz[i].child)%256;
401             if (!module_switch)
402             {   p[objs+12]=mark/256;
403                 p[objs+13]=mark%256;
404             }
405             else
406             {   p[objs+12]=objectsz[i].propsize/256;
407                 p[objs+13]=objectsz[i].propsize%256;
408             }
409             objs+=14;
410         }
411         mark+=objectsz[i].propsize;
412     }
413
414     /*  ----------- Table of Class Prototype Object Numbers ---------------- */
415
416     class_numbers_offset = mark;
417     for (i=0; i<no_classes; i++)
418     {   p[mark++] = class_object_numbers[i]/256;
419         p[mark++] = class_object_numbers[i]%256;
420         if (module_switch)
421         {   p[mark++] = class_begins_at[i]/256;
422             p[mark++] = class_begins_at[i]%256;
423         }
424     }
425     p[mark++] = 0;
426     p[mark++] = 0;
427
428     /*  ------------------- Table of Identifier Names ---------------------- */
429
430     identifier_names_offset = mark;
431
432     if (!module_switch)
433     {   p[mark++] = no_individual_properties/256;
434         p[mark++] = no_individual_properties%256;
435         for (i=1; i<no_individual_properties; i++)
436         {   p[mark++] = individual_name_strings[i]/256;
437             p[mark++] = individual_name_strings[i]%256;
438         }
439
440         attribute_names_offset = mark;
441         for (i=0; i<48; i++)
442         {   p[mark++] = attribute_name_strings[i]/256;
443             p[mark++] = attribute_name_strings[i]%256;
444         }
445
446         action_names_offset = mark;
447         fake_action_names_offset = mark + 2*no_actions;
448         for (i=0; i<no_actions + no_fake_actions; i++)
449         {   p[mark++] = action_name_strings[i]/256;
450             p[mark++] = action_name_strings[i]%256;
451         }
452
453         array_names_offset = mark;
454         global_names_offset = mark + 2*no_arrays;
455         routine_names_offset = global_names_offset + 2*no_globals;
456         constant_names_offset = routine_names_offset + 2*no_named_routines;
457         for (i=0; i<no_arrays + no_globals
458                     + no_named_routines + no_named_constants; i++)
459         {   if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
460             p[mark++] = array_name_strings[i]/256;
461             p[mark++] = array_name_strings[i]%256;
462         }
463
464         id_names_length = (mark - identifier_names_offset)/2;
465     }
466     routine_flags_array_offset = mark;
467
468     if (define_INFIX_switch)
469     {   for (i=0, k=1, l=0; i<no_named_routines; i++)
470         {   if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
471             k=k*2;
472             if (k==256) { p[mark++] = l; k=1; l=0; }
473         }
474         if (k!=1) p[mark++]=l;
475     }
476
477     /*  ---------------- Table of Indiv Property Values -------------------- */
478
479     individuals_offset = mark;
480     for (i=0; i<individuals_length; i++)
481         p[mark++] = individuals_table[i];
482
483     /*  ----------------- Variables and Dynamic Arrays --------------------- */
484
485     globals_at = mark;
486
487     for (i=0; i<dynamic_array_area_size; i++)
488         p[mark++] = dynamic_array_area[i];
489
490     for (i=0; i<240; i++)
491     {   j=global_initial_value[i];
492         p[globals_at+i*2]   = j/256; p[globals_at+i*2+1] = j%256;
493     }
494
495     /*  ------------------ Terminating Characters Table -------------------- */
496
497     if (version_number >= 5)
498     {   terminating_chars_at = mark;
499         for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
500         p[mark++] = 0;
501     }
502
503     /*  ------------------------ Grammar Table ----------------------------- */
504
505     if (grammar_version_number > 2)
506     {   warning("This version of Inform is unable to produce the grammar \
507 table format requested (producing number 2 format instead)");
508         grammar_version_number = 2;
509     }
510
511     grammar_table_at = mark;
512
513     mark = mark + no_Inform_verbs*2;
514
515     for (i=0; i<no_Inform_verbs; i++)
516     {   p[grammar_table_at + i*2] = (mark/256);
517         p[grammar_table_at + i*2 + 1] = (mark%256);
518         p[mark++] = Inform_verbs[i].lines;
519         for (j=0; j<Inform_verbs[i].lines; j++)
520         {   k = Inform_verbs[i].l[j];
521             if (grammar_version_number == 1)
522             {   int m, n;
523                 p[mark+7] = grammar_lines[k+1];
524                 for (m=1;m<=6;m++) p[mark + m] = 0;
525                 k = k + 2; m = 1; n = 0;
526                 while ((grammar_lines[k] != 15) && (m<=6))
527                 {   p[mark + m] = grammar_lines[k];
528                     if (grammar_lines[k] < 180) n++;
529                     m++; k = k + 3;
530                 }
531                 p[mark] = n;
532                 mark = mark + 8;
533             }
534             else
535             {   int tok;
536                 p[mark++] = grammar_lines[k++];
537                 p[mark++] = grammar_lines[k++];
538                 for (;;)
539                 {   tok = grammar_lines[k++];
540                     p[mark++] = tok;
541                     if (tok == 15) break;
542                     p[mark++] = grammar_lines[k++];
543                     p[mark++] = grammar_lines[k++];
544                 }
545             }
546         }
547     }
548
549     /*  ------------------- Actions and Preactions ------------------------- */
550     /*  (The term "preactions" is traditional: Inform uses the preactions    */
551     /*  table for a different purpose than Infocom used to.)                 */
552     /*  The values are written later, when the Z-code offset is known.       */
553     /*  -------------------------------------------------------------------- */
554
555     actions_at = mark;
556     mark += no_actions*2;
557
558     preactions_at = mark;
559     if (grammar_version_number == 1)
560         mark += no_grammar_token_routines*2;
561
562     /*  ----------------------- Adjectives Table --------------------------- */
563
564     if (grammar_version_number == 1)
565     {   p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
566         adjectives_offset = mark;
567         dictionary_offset = mark + 4*no_adjectives;
568
569         for (i=0; i<no_adjectives; i++)
570         {   j = final_dict_order[adjectives[no_adjectives-i-1]]
571                 *((version_number==3)?7:9)
572                 + dictionary_offset + 7;
573             p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
574             p[mark++]=(256-no_adjectives+i);
575         }
576     }
577     else
578     {   p[mark]=0; p[mark+1]=0; mark+=2;
579         adjectives_offset = mark;
580         dictionary_offset = mark;
581     }
582
583     /*  ------------------------- Dictionary ------------------------------- */
584
585     dictionary_at=mark;
586
587     dictionary[0]=3; dictionary[1]='.';        /* Non-space characters which */
588                      dictionary[2]=',';                 /* force words apart */
589                      dictionary[3]='"';
590
591     dictionary[4]=(version_number==3)?7:9;           /* Length of each entry */
592     dictionary[5]=(dict_entries/256);                   /* Number of entries */
593     dictionary[6]=(dict_entries%256);
594
595     for (i=0; i<7; i++) p[mark++] = dictionary[i];
596
597     for (i=0; i<dict_entries; i++)
598     {   k = 7 + i*((version_number==3)?7:9);
599         j = mark + final_dict_order[i]*((version_number==3)?7:9);
600         for (l = 0; l<((version_number==3)?7:9); l++)
601             p[j++] = dictionary[k++];
602     }
603     mark += dict_entries * ((version_number==3)?7:9);
604
605     /*  ------------------------- Module Map ------------------------------- */
606
607     if (module_switch)
608     {   map_of_module = mark;                             /* Filled in below */
609         mark += 30;
610     }
611
612     /*  ----------------- A gap before the code area ----------------------- */
613     /*  (so that it will start at an exact packed address and so that all    */
614     /*  routine packed addresses are >= 256, hence long constants)           */
615     /*  -------------------------------------------------------------------- */
616
617     while ((mark%length_scale_factor) != 0) p[mark++]=0;
618     while (mark < (scale_factor*0x100)) p[mark++]=0;
619     if (oddeven_packing_switch)
620         while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
621
622     if (mark > 0x0FFFE)
623     {   error("This program has overflowed the maximum readable-memory \
624 size of the Z-machine format. See the memory map below: the start \
625 of the area marked \"above readable memory\" must be brought down to $FFFE \
626 or less.");
627         memory_map_switch = TRUE;
628         /* Backpatching the grammar tables requires us to trust some of the */
629         /* addresses we've written into Z-machine memory, but they may have */
630         /* been truncated to 16 bits, so we can't do it.                    */
631         skip_backpatching = TRUE;
632     }
633
634     /*  -------------------------- Code Area ------------------------------- */
635     /*  (From this point on we don't write any more into the "p" buffer.)    */
636     /*  -------------------------------------------------------------------- */
637
638     Write_Code_At = mark;
639     if (!OMIT_UNUSED_ROUTINES) {
640         code_length = zmachine_pc;
641     }
642     else {
643         if (zmachine_pc != df_total_size_before_stripping)
644             compiler_error("Code size does not match (zmachine_pc and df_total_size).");
645         code_length = df_total_size_after_stripping;
646     }
647     mark += code_length;
648
649     /*  ------------------ Another synchronising gap ----------------------- */
650
651     if (oddeven_packing_switch)
652     {   if (module_switch)
653              while ((mark%(scale_factor*2)) != 0) mark++;
654         else
655              while ((mark%(scale_factor*2)) != scale_factor) mark++;
656     }
657     else
658         while ((mark%scale_factor) != 0) mark++;
659
660     /*  ------------------------- Strings Area ----------------------------- */
661
662     Write_Strings_At = mark;
663     strings_length = static_strings_extent;
664     mark += strings_length;
665
666     /*  --------------------- Module Linking Data -------------------------- */
667
668     if (module_switch)
669     {   link_table_at = mark; mark += link_data_size;
670         mark += zcode_backpatch_size;
671         mark += zmachine_backpatch_size;
672     }
673
674     /*  --------------------- Is the file too big? ------------------------- */
675
676     Out_Size = mark;
677
678     switch(version_number)
679     {   case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
680         case 4:
681         case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
682         case 6:
683         case 7:
684         case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
685     }
686
687     if (module_switch)
688     {   excess = Out_Size-((int32) 0x10000L); limit=64;
689     }
690
691     if (excess > 0)
692     {   char memory_full_error[80];
693         sprintf(memory_full_error,
694             "The %s exceeds version-%d limit (%dK) by %d bytes",
695              output_called, version_number, limit, excess);
696         fatalerror(memory_full_error);
697     }
698
699     /*  --------------------------- Offsets -------------------------------- */
700
701     dictionary_offset = dictionary_at;
702     variables_offset = globals_at;
703     actions_offset = actions_at;
704     preactions_offset = preactions_at;
705     prop_defaults_offset = prop_defaults_at;
706     prop_values_offset = object_props_at;
707     static_memory_offset = grammar_table_at;
708     grammar_table_offset = grammar_table_at;
709
710     if (extend_memory_map)
711     {   extend_offset=256;
712         if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
713         while ((extend_offset%length_scale_factor) != 0) extend_offset++;
714         /* Not sure why above line is necessary, but oddeven_packing
715          * will need extend_offset to be even */
716         code_offset = extend_offset*scale_factor;
717         if (oddeven_packing_switch)
718             strings_offset = code_offset + scale_factor;
719         else
720             strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
721
722         /* With the extended memory model, need to specifically check that we
723          * haven't overflowed the packed address range for routines or strings.
724          * With the standard memory model, we only need the earlier total size
725          * check.
726          */
727         excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
728         if (excess > 0)
729         {   char code_full_error[80];
730             sprintf(code_full_error,
731                 "The code area limit has been exceeded by %d bytes",
732                  excess);
733             fatalerror(code_full_error);
734         }
735
736         excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
737         if (excess > 0)
738         {   char strings_full_error[140];
739             if (oddeven_packing_switch)
740                 sprintf(strings_full_error,
741                     "The strings area limit has been exceeded by %d bytes",
742                      excess);
743             else
744                 sprintf(strings_full_error,
745                     "The code+strings area limit has been exceeded by %d bytes. \
746  Try running Inform again with -B on the command line.",
747                      excess);
748             fatalerror(strings_full_error);
749         }
750     }
751     else
752     {   code_offset = Write_Code_At;
753         strings_offset = Write_Strings_At;
754     }
755
756     /*  --------------------------- The Header ----------------------------- */
757
758     for (i=0; i<=0x3f; i++) p[i]=0;             /* Begin with 64 blank bytes */
759
760     p[0] = version_number;                                 /* Version number */
761     p[1] = statusline_flag*2;          /* Bit 1 of Flags 1: statusline style */
762     p[2] = (release_number/256);
763     p[3] = (release_number%256);                                  /* Release */
764     p[4] = (Write_Code_At/256);
765     p[5] = (Write_Code_At%256);                       /* End of paged memory */
766     if (version_number==6)
767     {   j=code_offset/scale_factor;            /* Packed address of "Main__" */
768         p[6]=(j/256); p[7]=(j%256);
769     }
770     else
771     {   j=Write_Code_At+1;                       /* Initial PC value (bytes) */
772         p[6]=(j/256); p[7]=(j%256);            /* (first opcode in "Main__") */
773     }
774     p[8] = (dictionary_at/256); p[9]=(dictionary_at%256);      /* Dictionary */
775     p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256;       /* Objects */
776     p[12]=(globals_at/256); p[13]=(globals_at%256);          /* Dynamic area */
777     p[14]=(grammar_table_at/256);
778     p[15]=(grammar_table_at%256);                                 /* Grammar */
779     for (i=0, j=0, k=1;i<16;i++, k=k*2)         /* Flags 2 as needed for any */
780         j+=k*flags2_requirements[i];            /* unusual opcodes assembled */
781     p[16]=j/256; p[17]=j%256;
782     write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
783     p[24]=abbrevs_at/256;
784     p[25]=abbrevs_at%256;                             /* Abbreviations table */
785     p[26]=0; p[27]=0;            /* Length of file to be filled in "files.c" */
786     p[28]=0; p[29]=0;                  /* Checksum to be filled in "files.c" */
787
788     if (extend_memory_map)
789     {   j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
790         p[40]=j/256; p[41]=j%256;                         /* Routines offset */
791         if (oddeven_packing_switch)
792             j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
793         p[42]=j/256; p[43]=j%256;                        /* = Strings offset */
794     }
795
796     if (version_number >= 5)
797     {   p[46] = terminating_chars_at/256;    /* Terminating characters table */
798         p[47] = terminating_chars_at%256;
799     }
800
801     if (alphabet_modified)
802     {   j = charset_at;
803         p[52]=j/256; p[53]=j%256; }           /* Character set table address */
804
805     j = headerext_at;
806     p[54] = j/256; p[55] = j%256;          /* Header extension table address */
807
808     p[60] = '0' + ((RELEASE_NUMBER/100)%10);
809     p[61] = '.';
810     p[62] = '0' + ((RELEASE_NUMBER/10)%10);
811     p[63] = '0' + RELEASE_NUMBER%10;
812
813     /*  ------------------------ Header Extension -------------------------- */
814
815     /* The numbering in the spec is a little weird -- it's headerext_length
816        words *after* the initial length word. We follow the spec numbering
817        in this switch statement, so the count is 1-based. */
818     for (i=1; i<=headerext_length; i++) {
819         switch (i) {
820         case 3:
821             j = unicode_at;             /* Unicode translation table address */
822             break;
823         case 4:
824             j = ZCODE_HEADER_FLAGS_3;                        /* Flags 3 word */
825             break;
826         default:
827             j = 0;
828             break;
829         }
830         p[headerext_at+2*i+0] = j / 256;
831         p[headerext_at+2*i+1] = j % 256;
832     }
833
834     /*  ----------------- The Header: Extras for modules ------------------- */
835
836     if (module_switch)
837     {   p[0]=p[0]+64;
838         p[1]=MODULE_VERSION_NUMBER;
839         p[6]=map_of_module/256;
840         p[7]=map_of_module%256;
841
842         mark = map_of_module;                       /*  Module map format:   */
843
844         p[mark++]=object_tree_at/256;               /*  0: Object tree addr  */
845         p[mark++]=object_tree_at%256;
846         p[mark++]=object_props_at/256;              /*  2: Prop values addr  */
847         p[mark++]=object_props_at%256;
848         p[mark++]=(Write_Strings_At/scale_factor)/256;  /*  4: Static strs   */
849         p[mark++]=(Write_Strings_At/scale_factor)%256;
850         p[mark++]=class_numbers_offset/256;         /*  6: Class nos addr    */
851         p[mark++]=class_numbers_offset%256;
852         p[mark++]=individuals_offset/256;           /*  8: Indiv prop values */
853         p[mark++]=individuals_offset%256;
854         p[mark++]=individuals_length/256;           /*  10: Length of table  */
855         p[mark++]=individuals_length%256;
856         p[mark++]=no_symbols/256;                   /*  12: No of symbols    */
857         p[mark++]=no_symbols%256;
858         p[mark++]=no_individual_properties/256;     /*  14: Max property no  */
859         p[mark++]=no_individual_properties%256;
860         p[mark++]=no_objects/256;                   /*  16: No of objects    */
861         p[mark++]=no_objects%256;
862         i = link_table_at;
863         p[mark++]=i/256;                            /*  18: Import/exports   */
864         p[mark++]=i%256;
865         p[mark++]=link_data_size/256;               /*  20: Size of          */
866         p[mark++]=link_data_size%256;
867         i += link_data_size;
868         p[mark++]=i/256;                            /*  22: Code backpatch   */
869         p[mark++]=i%256;
870         p[mark++]=zcode_backpatch_size/256;         /*  24: Size of          */
871         p[mark++]=zcode_backpatch_size%256;
872         i += zcode_backpatch_size;
873         p[mark++]=i/256;                            /*  26: Image backpatch  */
874         p[mark++]=i%256;
875         p[mark++]=zmachine_backpatch_size/256;      /*  28: Size of          */
876         p[mark++]=zmachine_backpatch_size%256;
877
878         /*  Further space in this table is reserved for future use  */
879     }
880
881     /*  ---- Backpatch the Z-machine, now that all information is in ------- */
882
883     if (!module_switch && !skip_backpatching)
884     {   backpatch_zmachine_image_z();
885         for (i=1; i<id_names_length; i++)
886         {   int32 v = 256*p[identifier_names_offset + i*2]
887                       + p[identifier_names_offset + i*2 + 1];
888             if (v!=0) v += strings_offset/scale_factor;
889             p[identifier_names_offset + i*2] = v/256;
890             p[identifier_names_offset + i*2 + 1] = v%256;
891         }
892
893         mark = actions_at;
894         for (i=0; i<no_actions; i++)
895         {   j=action_byte_offset[i];
896             if (OMIT_UNUSED_ROUTINES)
897                 j = df_stripped_address_for_address(j);
898             j += code_offset/scale_factor;
899             p[mark++]=j/256; p[mark++]=j%256;
900         }
901
902         if (grammar_version_number == 1)
903         {   mark = preactions_at;
904             for (i=0; i<no_grammar_token_routines; i++)
905             {   j=grammar_token_routine[i];
906                 if (OMIT_UNUSED_ROUTINES)
907                     j = df_stripped_address_for_address(j);
908                 j += code_offset/scale_factor;
909                 p[mark++]=j/256; p[mark++]=j%256;
910             }
911         }
912         else
913         {   for (l = 0; l<no_Inform_verbs; l++)
914             {   k = grammar_table_at + 2*l;
915                 i = p[k]*256 + p[k+1];
916                 for (j = p[i++]; j>0; j--)
917                 {   int topbits; int32 value;
918                     i = i + 2;
919                     while (p[i] != 15)
920                     {   topbits = (p[i]/0x40) & 3;
921                         value = p[i+1]*256 + p[i+2];
922                         switch(topbits)
923                         {   case 1:
924                                 value = final_dict_order[value]
925                                         *((version_number==3)?7:9)
926                                         + dictionary_offset + 7;
927                                 break;
928                             case 2:
929                                 if (OMIT_UNUSED_ROUTINES)
930                                     value = df_stripped_address_for_address(value);
931                                 value += code_offset/scale_factor;
932                                 break;
933                         }
934                         p[i+1] = value/256; p[i+2] = value%256;
935                         i = i + 3;
936                     }
937                     i++;
938                 }
939             }
940         }
941     }
942
943     /*  ---- From here on, it's all reportage: construction is finished ---- */
944
945     if (statistics_switch)
946     {   int32 k_long, rate; char *k_str="";
947         k_long=(Out_Size/1024);
948         if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
949         else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
950         if (total_bytes_trans == 0) rate = 0;
951         else rate=total_bytes_trans*1000/total_chars_trans;
952
953         {   printf("In:\
954 %3d source code files            %6d syntactic lines\n\
955 %6d textual lines              %8ld characters ",
956             total_input_files, no_syntax_lines,
957             total_source_line_count, (long int) total_chars_read);
958             if (character_set_unicode) printf("(UTF-8)\n");
959             else if (character_set_setting == 0) printf("(plain ASCII)\n");
960             else
961             {   printf("(ISO 8859-%d %s)\n", character_set_setting,
962                     name_of_iso_set(character_set_setting));
963             }
964
965             printf("Allocated:\n\
966 %6d symbols (maximum %4d)    %8ld bytes of memory\n\
967 Out:   Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
968                  no_symbols, MAX_SYMBOLS,
969                  (long int) malloced_bytes,
970                  version_number,
971                  version_name(version_number),
972                  output_called,
973                  release_number, p[18], p[19], p[20], p[21], p[22], p[23],
974                  (long int) k_long, k_str);
975
976             printf("\
977 %6d classes (maximum %3d)        %6d objects (maximum %3d)\n\
978 %6d global vars (maximum 233)    %6d variable/array space (maximum %d)\n",
979                  no_classes, MAX_CLASSES,
980                  no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
981                  no_globals,
982                  dynamic_array_area_size, MAX_STATIC_DATA);
983
984             printf(
985 "%6d verbs (maximum %3d)          %6d dictionary entries (maximum %d)\n\
986 %6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
987 %6d actions (maximum %3d)        %6d attributes (maximum %2d)\n\
988 %6d common props (maximum %2d)    %6d individual props (unlimited)\n",
989                  no_Inform_verbs, MAX_VERBS,
990                  dict_entries, MAX_DICT_ENTRIES,
991                  no_grammar_lines, grammar_version_number,
992                  no_grammar_tokens,
993                  no_actions, MAX_ACTIONS,
994                  no_attributes, ((version_number==3)?32:48),
995                  no_properties-2, ((version_number==3)?30:62),
996                  no_individual_properties - 64);
997
998             if (track_unused_routines)
999             {
1000                 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1001                 printf(
1002 "%6ld bytes of Z-code              %6ld unused bytes %s (%.1f%%)\n",
1003                  (long int) df_total_size_before_stripping, (long int) diff,
1004                  (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1005                  100 * (float)diff / (float)df_total_size_before_stripping);
1006             }
1007
1008             printf(
1009 "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
1010 %6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
1011 %6ld instructions of Z-code       %6d sequence points\n\
1012 %6ld bytes readable memory used (maximum 65536)\n\
1013 %6ld bytes used in Z-machine      %6ld bytes free in Z-machine\n",
1014                  (long int) total_chars_trans,
1015                  (long int) total_bytes_trans,
1016                  (total_chars_trans>total_bytes_trans)?0:1,
1017                  (long int) rate,
1018                  no_abbreviations, MAX_ABBREVS,
1019                  no_routines,
1020                  (long int) no_instructions, no_sequence_points,
1021                  (long int) Write_Code_At,
1022                  (long int) Out_Size,
1023                  (long int)
1024                       (((long int) (limit*1024L)) - ((long int) Out_Size)));
1025
1026         }
1027     }
1028
1029     if (offsets_switch)
1030     {
1031         {   printf(
1032 "\nOffsets in %s:\n\
1033 %05lx Synonyms     %05lx Defaults     %05lx Objects    %05lx Properties\n\
1034 %05lx Variables    %05lx Parse table  %05lx Actions    %05lx Preactions\n\
1035 %05lx Adjectives   %05lx Dictionary   %05lx Code       %05lx Strings\n",
1036             output_called,
1037             (long int) abbrevs_at,
1038             (long int) prop_defaults_at,
1039             (long int) object_tree_at,
1040             (long int) object_props_at,
1041             (long int) globals_at,
1042             (long int) grammar_table_at,
1043             (long int) actions_at,
1044             (long int) preactions_at,
1045             (long int) adjectives_offset,
1046             (long int) dictionary_at,
1047             (long int) Write_Code_At,
1048             (long int) Write_Strings_At);
1049             if (module_switch)
1050                 printf("%05lx Linking data\n",(long int) link_table_at);
1051         }
1052     }
1053
1054     if (debugfile_switch)
1055     {   begin_writing_debug_sections();
1056         write_debug_section("abbreviations", 64);
1057         write_debug_section("abbreviations table", abbrevs_at);
1058         write_debug_section("header extension", headerext_at);
1059         if (alphabet_modified)
1060         {   write_debug_section("alphabets table", charset_at);
1061         }
1062         if (zscii_defn_modified)
1063         {   write_debug_section("Unicode table", unicode_at);
1064         }
1065         write_debug_section("property defaults", prop_defaults_at);
1066         write_debug_section("object tree", object_tree_at);
1067         write_debug_section("common properties", object_props_at);
1068         write_debug_section("class numbers", class_numbers_offset);
1069         write_debug_section("identifier names", identifier_names_offset);
1070         write_debug_section("individual properties", individuals_offset);
1071         write_debug_section("global variables", globals_at);
1072         write_debug_section("array space", globals_at+480);
1073         write_debug_section("grammar table", grammar_table_at);
1074         write_debug_section("actions table", actions_at);
1075         write_debug_section("parsing routines", preactions_at);
1076         write_debug_section("adjectives table", adjectives_offset);
1077         write_debug_section("dictionary", dictionary_at);
1078         write_debug_section("code area", Write_Code_At);
1079         write_debug_section("strings area", Write_Strings_At);
1080         end_writing_debug_sections(Out_Size);
1081     }
1082
1083     if (memory_map_switch)
1084     {
1085         {
1086 printf("Dynamic +---------------------+   00000\n");
1087 printf("memory  |       header        |\n");
1088 printf("        +---------------------+   00040\n");
1089 printf("        |    abbreviations    |\n");
1090 printf("        + - - - - - - - - - - +   %05lx\n", (long int) abbrevs_at);
1091 printf("        | abbreviations table |\n");
1092 printf("        +---------------------+   %05lx\n", (long int) headerext_at);
1093 printf("        |  header extension   |\n");
1094             if (alphabet_modified)
1095             {
1096 printf("        + - - - - - - - - - - +   %05lx\n", (long int) charset_at);
1097 printf("        |   alphabets table   |\n");
1098             }
1099             if (zscii_defn_modified)
1100             {
1101 printf("        + - - - - - - - - - - +   %05lx\n", (long int) unicode_at);
1102 printf("        |    Unicode table    |\n");
1103             }
1104 printf("        +---------------------+   %05lx\n",
1105                                           (long int) prop_defaults_at);
1106 printf("        |  property defaults  |\n");
1107 printf("        + - - - - - - - - - - +   %05lx\n", (long int) object_tree_at);
1108 printf("        |       objects       |\n");
1109 printf("        + - - - - - - - - - - +   %05lx\n",
1110                                           (long int) object_props_at);
1111 printf("        | object short names, |\n");
1112 printf("        | common prop values  |\n");
1113 printf("        + - - - - - - - - - - +   %05lx\n",
1114                                           (long int) class_numbers_offset);
1115 printf("        | class numbers table |\n");
1116 printf("        + - - - - - - - - - - +   %05lx\n",
1117                                           (long int) identifier_names_offset);
1118 printf("        | symbol names table  |\n");
1119 printf("        + - - - - - - - - - - +   %05lx\n",
1120                                           (long int) individuals_offset);
1121 printf("        | indiv prop values   |\n");
1122 printf("        +---------------------+   %05lx\n", (long int) globals_at);
1123 printf("        |  global variables   |\n");
1124 printf("        + - - - - - - - - - - +   %05lx\n",
1125                                           ((long int) globals_at)+480L);
1126 printf("        |       arrays        |\n");
1127 printf("        +=====================+   %05lx\n",
1128                                           (long int) grammar_table_at);
1129 printf("Readable|    grammar table    |\n");
1130 printf("memory  + - - - - - - - - - - +   %05lx\n", (long int) actions_at);
1131 printf("        |       actions       |\n");
1132 printf("        + - - - - - - - - - - +   %05lx\n", (long int) preactions_at);
1133 printf("        |   parsing routines  |\n");
1134 printf("        + - - - - - - - - - - +   %05lx\n",
1135                                           (long int) adjectives_offset);
1136 printf("        |     adjectives      |\n");
1137 printf("        +---------------------+   %05lx\n", (long int) dictionary_at);
1138 printf("        |     dictionary      |\n");
1139 if (module_switch)
1140 {
1141 printf("        + - - - - - - - - - - +   %05lx\n",
1142                                           (long int) map_of_module);
1143 printf("        | map of module addrs |\n");
1144 }
1145 printf("        +=====================+   %05lx\n", (long int) Write_Code_At);
1146 printf("Above   |       Z-code        |\n");
1147 printf("readable+---------------------+   %05lx\n",
1148                                           (long int) Write_Strings_At);
1149 printf("memory  |       strings       |\n");
1150 if (module_switch)
1151 {
1152 printf("        +=====================+   %05lx\n", (long int) link_table_at);
1153 printf("        | module linking data |\n");
1154 }
1155 printf("        +---------------------+   %05lx\n", (long int) Out_Size);
1156         }
1157     }
1158     if (percentages_switch)
1159     {   printf("Approximate percentage breakdown of %s:\n",
1160                 output_called);
1161         percentage("Z-code",             code_length,Out_Size);
1162         if (module_switch)
1163             percentage("Linking data",   link_data_size,Out_Size);
1164         percentage("Static strings",     strings_length,Out_Size);
1165         percentage("Dictionary",         Write_Code_At-dictionary_at,Out_Size);
1166         percentage("Objects",            globals_at-prop_defaults_at,Out_Size);
1167         percentage("Globals",            grammar_table_at-globals_at,Out_Size);
1168         percentage("Parsing tables",   dictionary_at-grammar_table_at,Out_Size);
1169         percentage("Header and synonyms", prop_defaults_at,Out_Size);
1170         percentage("Total of save area", grammar_table_at,Out_Size);
1171         percentage("Total of text",      total_bytes_trans,Out_Size);
1172     }
1173     if (frequencies_switch)
1174     {
1175         {   printf("How frequently abbreviations were used, and roughly\n");
1176             printf("how many bytes they saved:  ('_' denotes spaces)\n");
1177             for (i=0; i<no_abbreviations; i++)
1178             {   char abbrev_string[MAX_ABBREV_LENGTH];
1179                 strcpy(abbrev_string,
1180                     (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1181                 for (j=0; abbrev_string[j]!=0; j++)
1182                     if (abbrev_string[j]==' ') abbrev_string[j]='_';
1183                 printf("%10s %5d/%5d   ",abbrev_string,abbrev_freqs[i],
1184                     2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1185                 if ((i%3)==2) printf("\n");
1186             }
1187             if ((i%3)!=0) printf("\n");
1188             if (no_abbreviations==0) printf("None were declared.\n");
1189         }
1190     }
1191 }
1192
1193 static void construct_storyfile_g(void)
1194 {   uchar *p;
1195     int32 i, j, k, l, mark, strings_length, limit;
1196     int32 globals_at, dictionary_at, actions_at, preactions_at,
1197           abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1198           grammar_table_at, charset_at, headerext_at,
1199           unicode_at, arrays_at;
1200     int32 threespaces, code_length;
1201     char *output_called = (module_switch)?"module":"story file";
1202
1203     ASSERT_GLULX();
1204
1205     individual_name_strings =
1206         my_calloc(sizeof(int32), no_individual_properties,
1207             "identifier name strings");
1208     action_name_strings =
1209         my_calloc(sizeof(int32), no_actions + no_fake_actions,
1210             "action name strings");
1211     attribute_name_strings =
1212         my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1213             "attribute name strings");
1214     array_name_strings =
1215         my_calloc(sizeof(int32), 
1216             no_symbols,
1217             "array name strings");
1218
1219     write_the_identifier_names();
1220     threespaces = compile_string("   ", FALSE, FALSE);
1221
1222     compress_game_text();
1223
1224     /*  We now know how large the buffer to hold our construction has to be  */
1225
1226     zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1227         "output buffer");
1228
1229     /*  Foolish code to make this routine compile on all ANSI compilers      */
1230
1231     p = (uchar *) zmachine_paged_memory;
1232
1233     /*  In what follows, the "mark" will move upwards in memory: at various
1234         points its value will be recorded for milestones like
1235         "dictionary table start".  It begins at 0x40, just after the header  */
1236
1237     /* Ok, our policy here will be to set the *_at values all relative
1238        to RAM. That's so we can write into zmachine_paged_memory[mark] 
1239        and actually hit what we're aiming at.
1240        All the *_offset values will be set to true Glulx machine
1241        addresses. */
1242
1243     /* To get our bearings, figure out where the strings and code are. */
1244     /* We start with two words, which conventionally identify the 
1245        memory layout. This is why the code starts eight bytes after
1246        the header. */
1247     Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1248     if (!OMIT_UNUSED_ROUTINES) {
1249         code_length = zmachine_pc;
1250     }
1251     else {
1252         if (zmachine_pc != df_total_size_before_stripping)
1253             compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1254         code_length = df_total_size_after_stripping;
1255     }
1256     Write_Strings_At = Write_Code_At + code_length;
1257     strings_length = compression_table_size + compression_string_size;
1258
1259     /* Now figure out where RAM starts. */
1260     Write_RAM_At = Write_Strings_At + strings_length;
1261     /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1262     while (Write_RAM_At % GPAGESIZE)
1263       Write_RAM_At++;
1264
1265     /* Now work out all those RAM positions. */
1266     mark = 0;
1267
1268     /*  ----------------- Variables and Dynamic Arrays --------------------- */
1269
1270     globals_at = mark;
1271     for (i=0; i<no_globals; i++) {
1272       j = global_initial_value[i];
1273       WriteInt32(p+mark, j);
1274       mark += 4;
1275     }
1276
1277     arrays_at = mark;
1278     for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1279         p[mark++] = dynamic_array_area[i];
1280
1281     /* -------------------------- Dynamic Strings -------------------------- */
1282
1283     abbrevs_at = mark;
1284     WriteInt32(p+mark, no_dynamic_strings);
1285     mark += 4;
1286     for (i=0; i<no_dynamic_strings; i++) {
1287       j = Write_Strings_At + compressed_offsets[threespaces-1];
1288       WriteInt32(p+mark, j);
1289       mark += 4;
1290     }
1291
1292     /* ---------------- Various Things I'm Not Sure About ------------------ */
1293     /* Actually, none of these are relevant to Glulx. */
1294     headerext_at = mark;
1295     charset_at = 0;
1296     if (alphabet_modified)
1297       charset_at = mark;
1298     unicode_at = 0;
1299     if (zscii_defn_modified)
1300       unicode_at = mark;
1301
1302     /*  -------------------- Objects and Properties ------------------------ */
1303
1304     object_tree_at = mark;
1305
1306     object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1307
1308     for (i=0; i<no_objects; i++) {
1309       int32 objmark = mark;
1310       p[mark++] = 0x70; /* type byte -- object */
1311       for (j=0; j<NUM_ATTR_BYTES; j++) {
1312         p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1313       }
1314       for (j=0; j<6; j++) {
1315         int32 val = 0;
1316         switch (j) {
1317         case 0: /* next object in the linked list. */
1318           if (i == no_objects-1)
1319             val = 0;
1320           else
1321             val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1322           break;
1323         case 1: /* hardware name address */
1324           val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1325           break;
1326         case 2: /* property table address */
1327           val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1328           break;
1329         case 3: /* parent */
1330           if (objectsg[i].parent == 0)
1331             val = 0;
1332           else
1333             val = Write_RAM_At + object_tree_at +
1334               (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1335           break;
1336         case 4: /* sibling */
1337           if (objectsg[i].next == 0)
1338             val = 0;
1339           else
1340             val = Write_RAM_At + object_tree_at +
1341               (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1342           break;
1343         case 5: /* child */
1344           if (objectsg[i].child == 0)
1345             val = 0;
1346           else
1347             val = Write_RAM_At + object_tree_at +
1348               (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1349           break;
1350         }
1351         p[mark++] = (val >> 24) & 0xFF;
1352         p[mark++] = (val >> 16) & 0xFF;
1353         p[mark++] = (val >> 8) & 0xFF;
1354         p[mark++] = (val) & 0xFF;
1355       }
1356
1357       for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1358         p[mark++] = 0;
1359       }
1360     }
1361
1362     if (object_props_at != mark)
1363       error("*** Object table was impossible length ***");
1364
1365     for (i=0; i<properties_table_size; i++)
1366       p[mark+i]=properties_table[i];
1367
1368     for (i=0; i<no_objects; i++) { 
1369       int32 tableaddr = object_props_at + objectsg[i].propaddr;
1370       int32 tablelen = ReadInt32(p+tableaddr);
1371       tableaddr += 4;
1372       for (j=0; j<tablelen; j++) {
1373         k = ReadInt32(p+tableaddr+4);
1374         k += (Write_RAM_At + object_props_at);
1375         WriteInt32(p+tableaddr+4, k);
1376         tableaddr += 10;
1377       }
1378     }
1379
1380     mark += properties_table_size;
1381
1382     prop_defaults_at = mark;
1383     for (i=0; i<no_properties; i++) {
1384       k = prop_default_value[i];
1385       WriteInt32(p+mark, k);
1386       mark += 4;
1387     }
1388
1389     /*  ----------- Table of Class Prototype Object Numbers ---------------- */
1390     
1391     class_numbers_offset = mark;
1392     for (i=0; i<no_classes; i++) {
1393       j = Write_RAM_At + object_tree_at +
1394         (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
1395       WriteInt32(p+mark, j);
1396       mark += 4;
1397     }
1398     WriteInt32(p+mark, 0);
1399     mark += 4;
1400
1401     /* -------------------- Table of Property Names ------------------------ */
1402
1403     /* We try to format this bit with some regularity...
1404        address of common properties
1405        number of common properties
1406        address of indiv properties
1407        number of indiv properties (counted from INDIV_PROP_START)
1408        address of attributes
1409        number of attributes (always NUM_ATTR_BYTES*8)
1410        address of actions
1411        number of actions
1412     */
1413
1414     identifier_names_offset = mark;
1415     mark += 32; /* eight pairs of values, to be filled in. */
1416
1417     WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1418     WriteInt32(p+identifier_names_offset+4, no_properties);
1419     for (i=0; i<no_properties; i++) {
1420       j = individual_name_strings[i];
1421       if (j)
1422         j = Write_Strings_At + compressed_offsets[j-1];
1423       WriteInt32(p+mark, j);
1424       mark += 4;
1425     }
1426
1427     WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1428     WriteInt32(p+identifier_names_offset+12, 
1429       no_individual_properties-INDIV_PROP_START);
1430     for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1431       j = individual_name_strings[i];
1432       if (j)
1433         j = Write_Strings_At + compressed_offsets[j-1];
1434       WriteInt32(p+mark, j);
1435       mark += 4;
1436     }
1437
1438     WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1439     WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1440     for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1441       j = attribute_name_strings[i];
1442       if (j)
1443         j = Write_Strings_At + compressed_offsets[j-1];
1444       WriteInt32(p+mark, j);
1445       mark += 4;
1446     }
1447
1448     WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1449     WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1450     action_names_offset = mark;
1451     fake_action_names_offset = mark + 4*no_actions;
1452     for (i=0; i<no_actions + no_fake_actions; i++) {
1453       j = action_name_strings[i];
1454       if (j)
1455         j = Write_Strings_At + compressed_offsets[j-1];
1456       WriteInt32(p+mark, j);
1457       mark += 4;
1458     }
1459
1460     array_names_offset = mark;
1461     WriteInt32(p+mark, no_arrays);
1462     mark += 4;
1463     for (i=0; i<no_arrays; i++) {
1464       j = array_name_strings[i];
1465       if (j)
1466         j = Write_Strings_At + compressed_offsets[j-1];
1467       WriteInt32(p+mark, j);
1468       mark += 4;
1469     }    
1470
1471     individuals_offset = mark;
1472
1473     /*  ------------------------ Grammar Table ----------------------------- */
1474
1475     if (grammar_version_number != 2)
1476     {   warning("This version of Inform is unable to produce the grammar \
1477 table format requested (producing number 2 format instead)");
1478         grammar_version_number = 2;
1479     }
1480
1481     grammar_table_at = mark;
1482
1483     WriteInt32(p+mark, no_Inform_verbs);
1484     mark += 4;
1485
1486     mark += no_Inform_verbs*4;
1487
1488     for (i=0; i<no_Inform_verbs; i++) {
1489       j = mark + Write_RAM_At;
1490       WriteInt32(p+(grammar_table_at+4+i*4), j);
1491       p[mark++] = Inform_verbs[i].lines;
1492       for (j=0; j<Inform_verbs[i].lines; j++) {
1493         int tok;
1494         k = Inform_verbs[i].l[j];
1495         p[mark++] = grammar_lines[k++];
1496         p[mark++] = grammar_lines[k++];
1497         p[mark++] = grammar_lines[k++];
1498         for (;;) {
1499           tok = grammar_lines[k++];
1500           p[mark++] = tok;
1501           if (tok == 15) break;
1502           p[mark++] = grammar_lines[k++];
1503           p[mark++] = grammar_lines[k++];
1504           p[mark++] = grammar_lines[k++];
1505           p[mark++] = grammar_lines[k++];
1506         }
1507       }
1508     }
1509
1510     /*  ------------------- Actions and Preactions ------------------------- */
1511
1512     actions_at = mark;
1513     WriteInt32(p+mark, no_actions);
1514     mark += 4;
1515     mark += no_actions*4;
1516     /* Values to be written in later. */
1517
1518     if (DICT_CHAR_SIZE != 1) {
1519       /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1520       while (mark % 4)
1521         p[mark++]=0;
1522     }
1523
1524     preactions_at = mark;
1525     adjectives_offset = mark;
1526     dictionary_offset = mark;
1527
1528     /*  ------------------------- Dictionary ------------------------------- */
1529
1530     dictionary_at = mark;
1531
1532     WriteInt32(dictionary+0, dict_entries);
1533     for (i=0; i<4; i++) 
1534       p[mark+i] = dictionary[i];
1535
1536     for (i=0; i<dict_entries; i++) {
1537       k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1538       j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1539       for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1540         p[j++] = dictionary[k++];
1541     }
1542     mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1543
1544     /*  -------------------------- All Data -------------------------------- */
1545     
1546     /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1547     while (mark % GPAGESIZE)
1548       p[mark++]=0;
1549
1550     RAM_Size = mark;
1551
1552     Out_Size = Write_RAM_At + RAM_Size;
1553     limit=1024*1024;
1554
1555     /*  --------------------------- Offsets -------------------------------- */
1556
1557     dictionary_offset = Write_RAM_At + dictionary_at;
1558     variables_offset = Write_RAM_At + globals_at;
1559     arrays_offset = Write_RAM_At + arrays_at;
1560     actions_offset = Write_RAM_At + actions_at;
1561     preactions_offset = Write_RAM_At + preactions_at;
1562     prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1563     object_tree_offset = Write_RAM_At + object_tree_at;
1564     prop_values_offset = Write_RAM_At + object_props_at;
1565     static_memory_offset = Write_RAM_At + grammar_table_at;
1566     grammar_table_offset = Write_RAM_At + grammar_table_at;
1567     abbreviations_offset = Write_RAM_At + abbrevs_at;
1568
1569     code_offset = Write_Code_At;
1570     strings_offset = Write_Strings_At;
1571
1572     /*  --------------------------- The Header ----------------------------- */
1573
1574     /*  ------ Backpatch the machine, now that all information is in ------- */
1575
1576     if (!module_switch)
1577     {   backpatch_zmachine_image_g();
1578
1579         mark = actions_at + 4;
1580         for (i=0; i<no_actions; i++) {
1581           j = action_byte_offset[i];
1582           if (OMIT_UNUSED_ROUTINES)
1583             j = df_stripped_address_for_address(j);
1584           j += code_offset;
1585           WriteInt32(p+mark, j);
1586           mark += 4;
1587         }
1588
1589         for (l = 0; l<no_Inform_verbs; l++) {
1590           k = grammar_table_at + 4 + 4*l; 
1591           i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1592           i -= Write_RAM_At;
1593           for (j = p[i++]; j>0; j--) {
1594             int topbits; 
1595             int32 value;
1596             i = i + 3;
1597             while (p[i] != 15) {
1598               topbits = (p[i]/0x40) & 3;
1599               value = ((p[i+1] << 24) | (p[i+2] << 16) 
1600                 | (p[i+3] << 8) | (p[i+4]));
1601               switch(topbits) {
1602               case 1:
1603                 value = dictionary_offset + 4
1604                   + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1605                 break;
1606               case 2:
1607                 if (OMIT_UNUSED_ROUTINES)
1608                   value = df_stripped_address_for_address(value);
1609                 value += code_offset;
1610                 break;
1611               }
1612               WriteInt32(p+(i+1), value);
1613               i = i + 5;
1614             }
1615             i++;
1616           }
1617         }
1618
1619     }
1620
1621     /*  ---- From here on, it's all reportage: construction is finished ---- */
1622
1623     if (statistics_switch)
1624     {   int32 k_long, rate; char *k_str="";
1625         k_long=(Out_Size/1024);
1626         if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1627         else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1628         if (strings_length == 0) rate = 0;
1629         else rate=strings_length*1000/total_chars_trans;
1630
1631         {   printf("In:\
1632 %3d source code files            %6d syntactic lines\n\
1633 %6d textual lines              %8ld characters ",
1634             total_input_files, no_syntax_lines,
1635             total_source_line_count, (long int) total_chars_read);
1636             if (character_set_unicode) printf("(UTF-8)\n");
1637             else if (character_set_setting == 0) printf("(plain ASCII)\n");
1638             else
1639             {   printf("(ISO 8859-%d %s)\n", character_set_setting,
1640                     name_of_iso_set(character_set_setting));
1641             }
1642
1643             {char serialnum[8];
1644             write_serial_number(serialnum);
1645             printf("Allocated:\n\
1646 %6d symbols (maximum %4d)    %8ld bytes of memory\n\
1647 Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1648                  no_symbols, MAX_SYMBOLS,
1649                  (long int) malloced_bytes,
1650                  version_name(version_number),
1651                  output_called,
1652                  release_number,
1653                  serialnum[0], serialnum[1], serialnum[2],
1654                  serialnum[3], serialnum[4], serialnum[5],
1655                  (long int) k_long, k_str);
1656             } 
1657
1658             printf("\
1659 %6d classes (maximum %3d)        %6d objects (maximum %3d)\n\
1660 %6d global vars (maximum %3d)    %6d variable/array space (maximum %d)\n",
1661                  no_classes, MAX_CLASSES,
1662                  no_objects, MAX_OBJECTS,
1663                  no_globals, MAX_GLOBAL_VARIABLES,
1664                  dynamic_array_area_size, MAX_STATIC_DATA);
1665
1666             printf(
1667 "%6d verbs (maximum %3d)          %6d dictionary entries (maximum %d)\n\
1668 %6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
1669 %6d actions (maximum %3d)        %6d attributes (maximum %2d)\n\
1670 %6d common props (maximum %3d)   %6d individual props (unlimited)\n",
1671                  no_Inform_verbs, MAX_VERBS,
1672                  dict_entries, MAX_DICT_ENTRIES,
1673                  no_grammar_lines, grammar_version_number,
1674                  no_grammar_tokens,
1675                  no_actions, MAX_ACTIONS,
1676                  no_attributes, NUM_ATTR_BYTES*8,
1677                  no_properties, INDIV_PROP_START,
1678                  no_individual_properties - INDIV_PROP_START);
1679
1680             if (track_unused_routines)
1681             {
1682                 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1683                 printf(
1684 "%6ld bytes of code                %6ld unused bytes %s (%.1f%%)\n",
1685                  (long int) df_total_size_before_stripping, (long int) diff,
1686                  (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1687                  100 * (float)diff / (float)df_total_size_before_stripping);
1688             }
1689
1690             printf(
1691 "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
1692 %6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
1693 %6ld instructions of code         %6d sequence points\n\
1694 %6ld bytes writable memory used   %6ld bytes read-only memory used\n\
1695 %6ld bytes used in machine    %10ld bytes free in machine\n",
1696                  (long int) total_chars_trans,
1697                  (long int) strings_length,
1698                  (total_chars_trans>strings_length)?0:1,
1699                  (long int) rate,
1700                  no_abbreviations, MAX_ABBREVS,
1701                  no_routines,
1702                  (long int) no_instructions, no_sequence_points,
1703                  (long int) (Out_Size - Write_RAM_At),
1704                  (long int) Write_RAM_At,
1705                  (long int) Out_Size,
1706                  (long int)
1707                       (((long int) (limit*1024L)) - ((long int) Out_Size)));
1708
1709         }
1710     }
1711
1712     if (offsets_switch)
1713     {
1714         {   printf(
1715 "\nOffsets in %s:\n\
1716 %05lx Synonyms     %05lx Defaults     %05lx Objects    %05lx Properties\n\
1717 %05lx Variables    %05lx Parse table  %05lx Actions    %05lx Preactions\n\
1718 %05lx Adjectives   %05lx Dictionary   %05lx Code       %05lx Strings\n",
1719             output_called,
1720             (long int) abbrevs_at,
1721             (long int) prop_defaults_at,
1722             (long int) object_tree_at,
1723             (long int) object_props_at,
1724             (long int) globals_at,
1725             (long int) grammar_table_at,
1726             (long int) actions_at,
1727             (long int) preactions_at,
1728             (long int) adjectives_offset,
1729             (long int) dictionary_at,
1730             (long int) Write_Code_At,
1731             (long int) Write_Strings_At);
1732         }
1733     }
1734
1735     if (debugfile_switch)
1736     {   begin_writing_debug_sections();
1737         write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1738         write_debug_section("code area", Write_Code_At);
1739         write_debug_section("string decoding table", Write_Strings_At);
1740         write_debug_section("strings area",
1741                             Write_Strings_At + compression_table_size);
1742         if (Write_Strings_At + strings_length < Write_RAM_At)
1743         {   write_debug_section
1744                 ("zero padding", Write_Strings_At + strings_length);
1745         }
1746         if (globals_at)
1747         {   compiler_error("Failed assumption that globals are at start of "
1748                            "Glulx RAM");
1749         }
1750         write_debug_section("global variables", Write_RAM_At + globals_at);
1751         write_debug_section("array space", Write_RAM_At + arrays_at);
1752         write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1753         write_debug_section("object tree", Write_RAM_At + object_tree_at);
1754         write_debug_section("common properties",
1755                             Write_RAM_At + object_props_at);
1756         write_debug_section("property defaults",
1757                             Write_RAM_At + prop_defaults_at);
1758         write_debug_section("class numbers",
1759                             Write_RAM_At + class_numbers_offset);
1760         write_debug_section("identifier names",
1761                             Write_RAM_At + identifier_names_offset);
1762         write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1763         write_debug_section("actions table", Write_RAM_At + actions_at);
1764         write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1765         if (MEMORY_MAP_EXTENSION)
1766         {   write_debug_section("zero padding", Out_Size);
1767         }
1768         end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1769     }
1770
1771     if (memory_map_switch)
1772     {
1773
1774         {
1775 printf("        +---------------------+   000000\n");
1776 printf("Read-   |       header        |\n");
1777 printf(" only   +=====================+   %06lx\n", (long int) GLULX_HEADER_SIZE);
1778 printf("memory  |  memory layout id   |\n");
1779 printf("        +---------------------+   %06lx\n", (long int) Write_Code_At);
1780 printf("        |        code         |\n");
1781 printf("        +---------------------+   %06lx\n",
1782   (long int) Write_Strings_At);
1783 printf("        | string decode table |\n");
1784 printf("        + - - - - - - - - - - +   %06lx\n",
1785   (long int) Write_Strings_At + compression_table_size);
1786 printf("        |       strings       |\n");
1787 printf("        +=====================+   %06lx\n", 
1788   (long int) (Write_RAM_At+globals_at));
1789 printf("Dynamic |  global variables   |\n");
1790 printf("memory  + - - - - - - - - - - +   %06lx\n",
1791   (long int) (Write_RAM_At+arrays_at));
1792 printf("        |       arrays        |\n");
1793 printf("        +---------------------+   %06lx\n",
1794   (long int) (Write_RAM_At+abbrevs_at));
1795 printf("        | printing variables  |\n");
1796             if (alphabet_modified)
1797             {
1798 printf("        + - - - - - - - - - - +   %06lx\n", 
1799   (long int) (Write_RAM_At+charset_at));
1800 printf("        |   alphabets table   |\n");
1801             }
1802             if (zscii_defn_modified)
1803             {
1804 printf("        + - - - - - - - - - - +   %06lx\n", 
1805   (long int) (Write_RAM_At+unicode_at));
1806 printf("        |    Unicode table    |\n");
1807             }
1808 printf("        +---------------------+   %06lx\n", 
1809   (long int) (Write_RAM_At+object_tree_at));
1810 printf("        |       objects       |\n");
1811 printf("        + - - - - - - - - - - +   %06lx\n",
1812   (long int) (Write_RAM_At+object_props_at));
1813 printf("        |   property values   |\n");
1814 printf("        + - - - - - - - - - - +   %06lx\n",
1815   (long int) (Write_RAM_At+prop_defaults_at));
1816 printf("        |  property defaults  |\n");
1817 printf("        + - - - - - - - - - - +   %06lx\n",
1818   (long int) (Write_RAM_At+class_numbers_offset));
1819 printf("        | class numbers table |\n");
1820 printf("        + - - - - - - - - - - +   %06lx\n",
1821   (long int) (Write_RAM_At+identifier_names_offset));
1822 printf("        |   id names table    |\n");
1823 printf("        +---------------------+   %06lx\n",
1824   (long int) (Write_RAM_At+grammar_table_at));
1825 printf("        |    grammar table    |\n");
1826 printf("        + - - - - - - - - - - +   %06lx\n", 
1827   (long int) (Write_RAM_At+actions_at));
1828 printf("        |       actions       |\n");
1829 printf("        +---------------------+   %06lx\n", 
1830   (long int) dictionary_offset);
1831 printf("        |     dictionary      |\n");
1832             if (MEMORY_MAP_EXTENSION == 0)
1833             {
1834 printf("        +---------------------+   %06lx\n", (long int) Out_Size);
1835             }
1836             else
1837             {
1838 printf("        +=====================+   %06lx\n", (long int) Out_Size);
1839 printf("Runtime |       (empty)       |\n");
1840 printf("  extn  +---------------------+   %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1841             }
1842
1843         }
1844
1845     }
1846
1847
1848     if (percentages_switch)
1849     {   printf("Approximate percentage breakdown of %s:\n",
1850                 output_called);
1851         percentage("Code",               code_length,Out_Size);
1852         if (module_switch)
1853             percentage("Linking data",   link_data_size,Out_Size);
1854         percentage("Static strings",     strings_length,Out_Size);
1855         percentage("Dictionary",         Write_Code_At-dictionary_at,Out_Size);
1856         percentage("Objects",            globals_at-prop_defaults_at,Out_Size);
1857         percentage("Globals",            grammar_table_at-globals_at,Out_Size);
1858         percentage("Parsing tables",   dictionary_at-grammar_table_at,Out_Size);
1859         percentage("Header and synonyms", prop_defaults_at,Out_Size);
1860         percentage("Total of save area", grammar_table_at,Out_Size);
1861         percentage("Total of text",      strings_length,Out_Size);
1862     }
1863     if (frequencies_switch)
1864     {
1865         {   printf("How frequently abbreviations were used, and roughly\n");
1866             printf("how many bytes they saved:  ('_' denotes spaces)\n");
1867             for (i=0; i<no_abbreviations; i++)
1868             {   char abbrev_string[MAX_ABBREV_LENGTH];
1869                 strcpy(abbrev_string,
1870                     (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1871                 for (j=0; abbrev_string[j]!=0; j++)
1872                     if (abbrev_string[j]==' ') abbrev_string[j]='_';
1873                 printf("%10s %5d/%5d   ",abbrev_string,abbrev_freqs[i],
1874                     2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1875                 if ((i%3)==2) printf("\n");
1876             }
1877             if ((i%3)!=0) printf("\n");
1878             if (no_abbreviations==0) printf("None were declared.\n");
1879         }
1880     }
1881 }
1882
1883 extern void construct_storyfile(void)
1884 {
1885   if (!glulx_mode)
1886     construct_storyfile_z();
1887   else
1888     construct_storyfile_g();
1889 }
1890
1891 /* ========================================================================= */
1892 /*   Data structure management routines                                      */
1893 /* ------------------------------------------------------------------------- */
1894
1895 extern void init_tables_vars(void)
1896 {
1897     release_number = 1;
1898     statusline_flag = SCORE_STYLE;
1899
1900     zmachine_paged_memory = NULL;
1901
1902     if (!glulx_mode) {
1903       code_offset = 0x800;
1904       actions_offset = 0x800;
1905       preactions_offset = 0x800;
1906       dictionary_offset = 0x800;
1907       adjectives_offset = 0x800;
1908       variables_offset = 0;
1909       strings_offset = 0xc00;
1910       individuals_offset=0x800;
1911       identifier_names_offset=0x800;
1912       class_numbers_offset = 0x800;
1913       arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1914     }
1915     else {
1916       code_offset = 0x12345;
1917       actions_offset = 0x12345;
1918       preactions_offset = 0x12345;
1919       dictionary_offset = 0x12345;
1920       adjectives_offset = 0x12345;
1921       variables_offset = 0x12345;
1922       arrays_offset = 0x12345;
1923       strings_offset = 0x12345;
1924       individuals_offset=0x12345;
1925       identifier_names_offset=0x12345;
1926       class_numbers_offset = 0x12345;
1927     }
1928 }
1929
1930 extern void tables_begin_pass(void)
1931 {
1932 }
1933
1934 extern void tables_allocate_arrays(void)
1935 {
1936 }
1937
1938 extern void tables_free_arrays(void)
1939 {
1940     /*  Allocation for this array happens in construct_storyfile() above     */
1941
1942     my_free(&zmachine_paged_memory,"output buffer");
1943 }
1944
1945 /* ========================================================================= */