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