389eb4bca1506a9d4aa99fe161d461717442ea30
[inform.git] / src / 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 /*   Part of Inform 6.40                                                     */
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/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 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)*(module_switch?4: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              + ((module_switch)?30: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, link_table_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           map_of_module=0, 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 = (module_switch)?"module":"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             if (!module_switch)
427             {   p[objs+12]=mark/256;
428                 p[objs+13]=mark%256;
429             }
430             else
431             {   p[objs+12]=objectsz[i].propsize/256;
432                 p[objs+13]=objectsz[i].propsize%256;
433             }
434             objs+=14;
435         }
436         mark+=objectsz[i].propsize;
437     }
438
439     /*  ----------- Table of Class Prototype Object Numbers ---------------- */
440
441     class_numbers_offset = mark;
442     for (i=0; i<no_classes; i++)
443     {   p[mark++] = class_info[i].object_number/256;
444         p[mark++] = class_info[i].object_number%256;
445         if (module_switch)
446         {   p[mark++] = class_info[i].begins_at/256;
447             p[mark++] = class_info[i].begins_at%256;
448         }
449     }
450     p[mark++] = 0;
451     p[mark++] = 0;
452
453     /*  ------------------- Table of Identifier Names ---------------------- */
454
455     identifier_names_offset = mark;
456
457     if (!module_switch)
458     {   p[mark++] = no_individual_properties/256;
459         p[mark++] = no_individual_properties%256;
460         for (i=1; i<no_individual_properties; i++)
461         {   p[mark++] = individual_name_strings[i]/256;
462             p[mark++] = individual_name_strings[i]%256;
463         }
464
465         attribute_names_offset = mark;
466         for (i=0; i<48; i++)
467         {   p[mark++] = attribute_name_strings[i]/256;
468             p[mark++] = attribute_name_strings[i]%256;
469         }
470
471         action_names_offset = mark;
472         fake_action_names_offset = mark + 2*no_actions;
473         for (i=0; i<no_actions + no_fake_actions; i++)
474         {   p[mark++] = action_name_strings[i]/256;
475             p[mark++] = action_name_strings[i]%256;
476         }
477
478         array_names_offset = mark;
479         global_names_offset = mark + 2*no_arrays;
480         routine_names_offset = global_names_offset + 2*no_globals;
481         constant_names_offset = routine_names_offset + 2*no_named_routines;
482         for (i=0; i<no_arrays + no_globals
483                     + no_named_routines + no_named_constants; i++)
484         {   if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
485             p[mark++] = array_name_strings[i]/256;
486             p[mark++] = array_name_strings[i]%256;
487         }
488
489         id_names_length = (mark - identifier_names_offset)/2;
490     }
491     routine_flags_array_offset = mark;
492
493     if (define_INFIX_switch)
494     {   for (i=0, k=1, l=0; i<no_named_routines; i++)
495         {   if (symbols[named_routine_symbols[i]].flags & STAR_SFLAG) l=l+k;
496             k=k*2;
497             if (k==256) { p[mark++] = l; k=1; l=0; }
498         }
499         if (k!=1) p[mark++]=l;
500     }
501
502     /*  ---------------- Table of Indiv Property Values -------------------- */
503
504     individuals_offset = mark;
505     for (i=0; i<individuals_length; i++)
506         p[mark++] = individuals_table[i];
507
508     /*  ----------------- Variables and Dynamic Arrays --------------------- */
509
510     globals_at = mark;
511
512     for (i=0; i<dynamic_array_area_size; i++)
513         p[mark++] = dynamic_array_area[i];
514
515     for (i=0; i<240; i++)
516     {   j=global_initial_value[i];
517         p[globals_at+i*2]   = j/256; p[globals_at+i*2+1] = j%256;
518     }
519
520     /*  ------------------ Terminating Characters Table -------------------- */
521
522     if (version_number >= 5)
523     {   terminating_chars_at = mark;
524         for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
525         p[mark++] = 0;
526     }
527
528     /*  ------------------------ Grammar Table ----------------------------- */
529
530     if (grammar_version_number > 2)
531     {   warning("This version of Inform is unable to produce the grammar \
532 table format requested (producing number 2 format instead)");
533         grammar_version_number = 2;
534     }
535
536     grammar_table_at = mark;
537
538     mark = mark + no_Inform_verbs*2;
539
540     for (i=0; i<no_Inform_verbs; i++)
541     {   p[grammar_table_at + i*2] = (mark/256);
542         p[grammar_table_at + i*2 + 1] = (mark%256);
543         p[mark++] = Inform_verbs[i].lines;
544         for (j=0; j<Inform_verbs[i].lines; j++)
545         {   k = Inform_verbs[i].l[j];
546             if (grammar_version_number == 1)
547             {   int m, n;
548                 p[mark+7] = grammar_lines[k+1];
549                 for (m=1;m<=6;m++) p[mark + m] = 0;
550                 k = k + 2; m = 1; n = 0;
551                 while ((grammar_lines[k] != 15) && (m<=6))
552                 {   p[mark + m] = grammar_lines[k];
553                     if (grammar_lines[k] < 180) n++;
554                     m++; k = k + 3;
555                 }
556                 p[mark] = n;
557                 mark = mark + 8;
558             }
559             else
560             {   int tok;
561                 p[mark++] = grammar_lines[k++];
562                 p[mark++] = grammar_lines[k++];
563                 for (;;)
564                 {   tok = grammar_lines[k++];
565                     p[mark++] = tok;
566                     if (tok == 15) break;
567                     p[mark++] = grammar_lines[k++];
568                     p[mark++] = grammar_lines[k++];
569                 }
570             }
571         }
572     }
573
574     /*  ------------------- Actions and Preactions ------------------------- */
575     /*  (The term "preactions" is traditional: Inform uses the preactions    */
576     /*  table for a different purpose than Infocom used to.)                 */
577     /*  The values are written later, when the Z-code offset is known.       */
578     /*  -------------------------------------------------------------------- */
579
580     actions_at = mark;
581     mark += no_actions*2;
582
583     preactions_at = mark;
584     if (grammar_version_number == 1)
585         mark += no_grammar_token_routines*2;
586
587     /*  ----------------------- Adjectives Table --------------------------- */
588
589     if (grammar_version_number == 1)
590     {   p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
591         adjectives_offset = mark;
592         dictionary_offset = mark + 4*no_adjectives;
593
594         for (i=0; i<no_adjectives; i++)
595         {   j = final_dict_order[adjectives[no_adjectives-i-1]]
596                 *DICT_ENTRY_BYTE_LENGTH
597                 + dictionary_offset + 7;
598             p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
599             p[mark++]=(256-no_adjectives+i);
600         }
601     }
602     else
603     {   p[mark]=0; p[mark+1]=0; mark+=2;
604         adjectives_offset = mark;
605         dictionary_offset = mark;
606     }
607
608     /*  ------------------------- Dictionary ------------------------------- */
609
610     dictionary_at=mark;
611
612     dictionary[0]=3; dictionary[1]='.';        /* Non-space characters which */
613                      dictionary[2]=',';                 /* force words apart */
614                      dictionary[3]='"';
615
616     dictionary[4]=DICT_ENTRY_BYTE_LENGTH;           /* Length of each entry */
617     dictionary[5]=(dict_entries/256);                   /* Number of entries */
618     dictionary[6]=(dict_entries%256);
619
620     for (i=0; i<7; i++) p[mark++] = dictionary[i];
621
622     for (i=0; i<dict_entries; i++)
623     {   k = 7 + i*DICT_ENTRY_BYTE_LENGTH;
624         j = mark + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
625         for (l = 0; l<DICT_ENTRY_BYTE_LENGTH; l++)
626             p[j++] = dictionary[k++];
627     }
628     mark += dict_entries * DICT_ENTRY_BYTE_LENGTH;
629
630     /*  ------------------------- Module Map ------------------------------- */
631
632     if (module_switch)
633     {   map_of_module = mark;                             /* Filled in below */
634         mark += 30;
635     }
636
637     /*  ------------------------ Static Arrays ----------------------------- */
638
639     static_arrays_at = mark;
640     for (i=0; i<static_array_area_size; i++)
641         p[mark++] = static_array_area[i];
642     
643     /*  ----------------- A gap before the code area ----------------------- */
644     /*  (so that it will start at an exact packed address and so that all    */
645     /*  routine packed addresses are >= 256, hence long constants)           */
646     /*  -------------------------------------------------------------------- */
647
648     while ((mark%length_scale_factor) != 0) p[mark++]=0;
649     while (mark < (scale_factor*0x100)) p[mark++]=0;
650     if (oddeven_packing_switch)
651         while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
652
653     if (mark > 0x0FFFE)
654     {   error("This program has overflowed the maximum readable-memory \
655 size of the Z-machine format. See the memory map below: the start \
656 of the area marked \"above readable memory\" must be brought down to $FFFE \
657 or less.");
658         memory_map_setting = 1;
659         /* Backpatching the grammar tables requires us to trust some of the */
660         /* addresses we've written into Z-machine memory, but they may have */
661         /* been truncated to 16 bits, so we can't do it.                    */
662         skip_backpatching = TRUE;
663     }
664
665     /*  -------------------------- Code Area ------------------------------- */
666     /*  (From this point on we don't write any more into the "p" buffer.)    */
667     /*  -------------------------------------------------------------------- */
668
669     Write_Code_At = mark;
670     if (!OMIT_UNUSED_ROUTINES) {
671         code_length = zmachine_pc;
672     }
673     else {
674         if (zmachine_pc != df_total_size_before_stripping)
675             compiler_error("Code size does not match (zmachine_pc and df_total_size).");
676         code_length = df_total_size_after_stripping;
677     }
678     mark += code_length;
679
680     /*  ------------------ Another synchronising gap ----------------------- */
681
682     if (oddeven_packing_switch)
683     {   if (module_switch)
684              while ((mark%(scale_factor*2)) != 0) mark++;
685         else
686              while ((mark%(scale_factor*2)) != scale_factor) mark++;
687     }
688     else
689         while ((mark%scale_factor) != 0) mark++;
690
691     /*  ------------------------- Strings Area ----------------------------- */
692
693     Write_Strings_At = mark;
694     strings_length = static_strings_extent;
695     mark += strings_length;
696
697     /*  --------------------- Module Linking Data -------------------------- */
698
699     if (module_switch)
700     {   link_table_at = mark; mark += link_data_size;
701         mark += zcode_backpatch_size;
702         mark += zmachine_backpatch_size;
703     }
704
705     /*  --------------------- Is the file too big? ------------------------- */
706
707     Out_Size = mark;
708
709     switch(version_number)
710     {   case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
711         case 4:
712         case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
713         case 6:
714         case 7:
715         case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
716     }
717
718     if (module_switch)
719     {   excess = Out_Size-((int32) 0x10000L); limit=64;
720     }
721
722     if (excess > 0)
723     {   char memory_full_error[80];
724         sprintf(memory_full_error,
725             "The %s exceeds version-%d limit (%dK) by %d bytes",
726              output_called, version_number, limit, excess);
727         fatalerror(memory_full_error);
728     }
729
730     /*  --------------------------- Offsets -------------------------------- */
731
732     dictionary_offset = dictionary_at;
733     variables_offset = globals_at;
734     actions_offset = actions_at;
735     preactions_offset = preactions_at;
736     prop_defaults_offset = prop_defaults_at;
737     prop_values_offset = object_props_at;
738     static_memory_offset = grammar_table_at;
739     grammar_table_offset = grammar_table_at;
740     static_arrays_offset = static_arrays_at;
741
742     if (extend_memory_map)
743     {   extend_offset=256;
744         if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
745         while ((extend_offset%length_scale_factor) != 0) extend_offset++;
746         /* Not sure why above line is necessary, but oddeven_packing
747          * will need extend_offset to be even */
748         code_offset = extend_offset*scale_factor;
749         if (oddeven_packing_switch)
750             strings_offset = code_offset + scale_factor;
751         else
752             strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
753
754         /* With the extended memory model, need to specifically check that we
755          * haven't overflowed the packed address range for routines or strings.
756          * With the standard memory model, we only need the earlier total size
757          * check.
758          */
759         excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
760         if (excess > 0)
761         {   char code_full_error[80];
762             sprintf(code_full_error,
763                 "The code area limit has been exceeded by %d bytes",
764                  excess);
765             fatalerror(code_full_error);
766         }
767
768         excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
769         if (excess > 0)
770         {   char strings_full_error[140];
771             if (oddeven_packing_switch)
772                 sprintf(strings_full_error,
773                     "The strings area limit has been exceeded by %d bytes",
774                      excess);
775             else
776                 sprintf(strings_full_error,
777                     "The code+strings area limit has been exceeded by %d bytes. \
778  Try running Inform again with -B on the command line.",
779                      excess);
780             fatalerror(strings_full_error);
781         }
782     }
783     else
784     {   code_offset = Write_Code_At;
785         strings_offset = Write_Strings_At;
786     }
787
788     /*  --------------------------- The Header ----------------------------- */
789
790     for (i=0; i<=0x3f; i++) p[i]=0;             /* Begin with 64 blank bytes */
791
792     p[0] = version_number;                                 /* Version number */
793     p[1] = statusline_flag*2;          /* Bit 1 of Flags 1: statusline style */
794     p[2] = (release_number/256);
795     p[3] = (release_number%256);                                  /* Release */
796     p[4] = (Write_Code_At/256);
797     p[5] = (Write_Code_At%256);                       /* End of paged memory */
798     if (version_number==6)
799     {   j=code_offset/scale_factor;            /* Packed address of "Main__" */
800         p[6]=(j/256); p[7]=(j%256);
801     }
802     else
803     {   j=Write_Code_At+1;                       /* Initial PC value (bytes) */
804         p[6]=(j/256); p[7]=(j%256);            /* (first opcode in "Main__") */
805     }
806     p[8] = (dictionary_at/256); p[9]=(dictionary_at%256);      /* Dictionary */
807     p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256;       /* Objects */
808     p[12]=(globals_at/256); p[13]=(globals_at%256);          /* Dynamic area */
809     p[14]=(grammar_table_at/256);
810     p[15]=(grammar_table_at%256);                                 /* Grammar */
811     for (i=0, j=0, k=1;i<16;i++, k=k*2)         /* Flags 2 as needed for any */
812         j+=k*flags2_requirements[i];            /* unusual opcodes assembled */
813     p[16]=j/256; p[17]=j%256;
814     write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
815     p[24]=abbrevs_at/256;
816     p[25]=abbrevs_at%256;                             /* Abbreviations table */
817     p[26]=0; p[27]=0;            /* Length of file to be filled in "files.c" */
818     p[28]=0; p[29]=0;                  /* Checksum to be filled in "files.c" */
819
820     if (extend_memory_map)
821     {   j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
822         p[40]=j/256; p[41]=j%256;                         /* Routines offset */
823         if (oddeven_packing_switch)
824             j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
825         p[42]=j/256; p[43]=j%256;                        /* = Strings offset */
826     }
827
828     if (version_number >= 5)
829     {   p[46] = terminating_chars_at/256;    /* Terminating characters table */
830         p[47] = terminating_chars_at%256;
831     }
832
833     if (alphabet_modified)
834     {   j = charset_at;
835         p[52]=j/256; p[53]=j%256; }           /* Character set table address */
836
837     j = headerext_at;
838     p[54] = j/256; p[55] = j%256;          /* Header extension table address */
839
840     p[60] = '0' + ((RELEASE_NUMBER/100)%10);
841     p[61] = '.';
842     p[62] = '0' + ((RELEASE_NUMBER/10)%10);
843     p[63] = '0' + RELEASE_NUMBER%10;
844
845     /*  ------------------------ Header Extension -------------------------- */
846
847     /* The numbering in the spec is a little weird -- it's headerext_length
848        words *after* the initial length word. We follow the spec numbering
849        in this switch statement, so the count is 1-based. */
850     for (i=1; i<=headerext_length; i++) {
851         switch (i) {
852         case 3:
853             j = unicode_at;             /* Unicode translation table address */
854             break;
855         case 4:
856             j = ZCODE_HEADER_FLAGS_3;                        /* Flags 3 word */
857             break;
858         default:
859             j = 0;
860             break;
861         }
862         p[headerext_at+2*i+0] = j / 256;
863         p[headerext_at+2*i+1] = j % 256;
864     }
865
866     /*  ----------------- The Header: Extras for modules ------------------- */
867
868     if (module_switch)
869     {   p[0]=p[0]+64;
870         p[1]=MODULE_VERSION_NUMBER;
871         p[6]=map_of_module/256;
872         p[7]=map_of_module%256;
873
874         mark = map_of_module;                       /*  Module map format:   */
875
876         p[mark++]=object_tree_at/256;               /*  0: Object tree addr  */
877         p[mark++]=object_tree_at%256;
878         p[mark++]=object_props_at/256;              /*  2: Prop values addr  */
879         p[mark++]=object_props_at%256;
880         p[mark++]=(Write_Strings_At/scale_factor)/256;  /*  4: Static strs   */
881         p[mark++]=(Write_Strings_At/scale_factor)%256;
882         p[mark++]=class_numbers_offset/256;         /*  6: Class nos addr    */
883         p[mark++]=class_numbers_offset%256;
884         p[mark++]=individuals_offset/256;           /*  8: Indiv prop values */
885         p[mark++]=individuals_offset%256;
886         p[mark++]=individuals_length/256;           /*  10: Length of table  */
887         p[mark++]=individuals_length%256;
888         p[mark++]=no_symbols/256;                   /*  12: No of symbols    */
889         p[mark++]=no_symbols%256;
890         p[mark++]=no_individual_properties/256;     /*  14: Max property no  */
891         p[mark++]=no_individual_properties%256;
892         p[mark++]=no_objects/256;                   /*  16: No of objects    */
893         p[mark++]=no_objects%256;
894         i = link_table_at;
895         p[mark++]=i/256;                            /*  18: Import/exports   */
896         p[mark++]=i%256;
897         p[mark++]=link_data_size/256;               /*  20: Size of          */
898         p[mark++]=link_data_size%256;
899         i += link_data_size;
900         p[mark++]=i/256;                            /*  22: Code backpatch   */
901         p[mark++]=i%256;
902         p[mark++]=zcode_backpatch_size/256;         /*  24: Size of          */
903         p[mark++]=zcode_backpatch_size%256;
904         i += zcode_backpatch_size;
905         p[mark++]=i/256;                            /*  26: Image backpatch  */
906         p[mark++]=i%256;
907         p[mark++]=zmachine_backpatch_size/256;      /*  28: Size of          */
908         p[mark++]=zmachine_backpatch_size%256;
909
910         /*  Further space in this table is reserved for future use  */
911     }
912
913     /*  ---- Backpatch the Z-machine, now that all information is in ------- */
914
915     if (!module_switch && !skip_backpatching)
916     {   backpatch_zmachine_image_z();
917         for (i=1; i<id_names_length; i++)
918         {   int32 v = 256*p[identifier_names_offset + i*2]
919                       + p[identifier_names_offset + i*2 + 1];
920             if (v!=0) v += strings_offset/scale_factor;
921             p[identifier_names_offset + i*2] = v/256;
922             p[identifier_names_offset + i*2 + 1] = v%256;
923         }
924
925         mark = actions_at;
926         for (i=0; i<no_actions; i++)
927         {   j=actions[i].byte_offset;
928             if (OMIT_UNUSED_ROUTINES)
929                 j = df_stripped_address_for_address(j);
930             j += code_offset/scale_factor;
931             p[mark++]=j/256; p[mark++]=j%256;
932         }
933
934         if (grammar_version_number == 1)
935         {   mark = preactions_at;
936             for (i=0; i<no_grammar_token_routines; i++)
937             {   j=grammar_token_routine[i];
938                 if (OMIT_UNUSED_ROUTINES)
939                     j = df_stripped_address_for_address(j);
940                 j += code_offset/scale_factor;
941                 p[mark++]=j/256; p[mark++]=j%256;
942             }
943         }
944         else
945         {   for (l = 0; l<no_Inform_verbs; l++)
946             {   k = grammar_table_at + 2*l;
947                 i = p[k]*256 + p[k+1];
948                 for (j = p[i++]; j>0; j--)
949                 {   int topbits; int32 value;
950                     i = i + 2;
951                     while (p[i] != 15)
952                     {   topbits = (p[i]/0x40) & 3;
953                         value = p[i+1]*256 + p[i+2];
954                         switch(topbits)
955                         {   case 1:
956                                 value = final_dict_order[value]
957                                         *DICT_ENTRY_BYTE_LENGTH
958                                         + dictionary_offset + 7;
959                                 break;
960                             case 2:
961                                 if (OMIT_UNUSED_ROUTINES)
962                                     value = df_stripped_address_for_address(value);
963                                 value += code_offset/scale_factor;
964                                 break;
965                         }
966                         p[i+1] = value/256; p[i+2] = value%256;
967                         i = i + 3;
968                     }
969                     i++;
970                 }
971             }
972         }
973     }
974
975     /*  ---- From here on, it's all reportage: construction is finished ---- */
976
977     if (debugfile_switch)
978     {   begin_writing_debug_sections();
979         write_debug_section("abbreviations", 64);
980         write_debug_section("abbreviations table", abbrevs_at);
981         write_debug_section("header extension", headerext_at);
982         if (alphabet_modified)
983         {   write_debug_section("alphabets table", charset_at);
984         }
985         if (zscii_defn_modified)
986         {   write_debug_section("Unicode table", unicode_at);
987         }
988         write_debug_section("property defaults", prop_defaults_at);
989         write_debug_section("object tree", object_tree_at);
990         write_debug_section("common properties", object_props_at);
991         write_debug_section("class numbers", class_numbers_offset);
992         write_debug_section("identifier names", identifier_names_offset);
993         write_debug_section("individual properties", individuals_offset);
994         write_debug_section("global variables", globals_at);
995         write_debug_section("array space", globals_at+480);
996         write_debug_section("grammar table", grammar_table_at);
997         write_debug_section("actions table", actions_at);
998         write_debug_section("parsing routines", preactions_at);
999         write_debug_section("adjectives table", adjectives_offset);
1000         write_debug_section("dictionary", dictionary_at);
1001         write_debug_section("code area", Write_Code_At);
1002         write_debug_section("strings area", Write_Strings_At);
1003         end_writing_debug_sections(Out_Size);
1004     }
1005
1006     if (memory_map_setting)
1007     {
1008         int32 addr;
1009         {
1010 printf("Dynamic +---------------------+   00000\n");
1011 printf("memory  |       header        |   %s\n",
1012     show_percentage(0x40, Out_Size));
1013 printf("        +---------------------+   00040\n");
1014 printf("        |    abbreviations    |   %s\n",
1015     show_percentage(abbrevs_at-0x40, Out_Size));
1016 printf("        + - - - - - - - - - - +   %05lx\n", (long int) abbrevs_at);
1017 printf("        | abbreviations table |   %s\n",
1018     show_percentage(headerext_at-abbrevs_at, Out_Size));
1019 printf("        +---------------------+   %05lx\n", (long int) headerext_at);
1020 addr = (alphabet_modified ? charset_at : (zscii_defn_modified ? unicode_at : prop_defaults_at));
1021 printf("        |  header extension   |   %s\n",
1022     show_percentage(addr-headerext_at, Out_Size));
1023             if (alphabet_modified)
1024             {
1025 printf("        + - - - - - - - - - - +   %05lx\n", (long int) charset_at);
1026 addr = (zscii_defn_modified ? unicode_at : prop_defaults_at);
1027 printf("        |   alphabets table   |   %s\n",
1028     show_percentage(addr-charset_at, Out_Size));
1029             }
1030             if (zscii_defn_modified)
1031             {
1032 printf("        + - - - - - - - - - - +   %05lx\n", (long int) unicode_at);
1033 printf("        |    Unicode table    |   %s\n",
1034     show_percentage(prop_defaults_at-unicode_at, Out_Size));
1035             }
1036 printf("        +---------------------+   %05lx\n",
1037                                           (long int) prop_defaults_at);
1038 printf("        |  property defaults  |   %s\n",
1039     show_percentage(object_tree_at-prop_defaults_at, Out_Size));
1040 printf("        + - - - - - - - - - - +   %05lx\n", (long int) object_tree_at);
1041 printf("        |       objects       |   %s\n",
1042     show_percentage(object_props_at-object_tree_at, Out_Size));
1043 printf("        + - - - - - - - - - - +   %05lx\n",
1044                                           (long int) object_props_at);
1045 printf("        | object short names, |\n");
1046 printf("        | common prop values  |   %s\n",
1047     show_percentage(class_numbers_offset-object_props_at, Out_Size));
1048 printf("        + - - - - - - - - - - +   %05lx\n",
1049                                           (long int) class_numbers_offset);
1050 printf("        | class numbers table |   %s\n",
1051     show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1052 printf("        + - - - - - - - - - - +   %05lx\n",
1053                                           (long int) identifier_names_offset);
1054 printf("        | symbol names table  |   %s\n",
1055     show_percentage(individuals_offset-identifier_names_offset, Out_Size));
1056 printf("        + - - - - - - - - - - +   %05lx\n",
1057                                           (long int) individuals_offset);
1058 printf("        | indiv prop values   |   %s\n",
1059     show_percentage(globals_at-individuals_offset, Out_Size));
1060 printf("        +---------------------+   %05lx\n", (long int) globals_at);
1061 printf("        |  global variables   |   %s\n",
1062     show_percentage(480, Out_Size));
1063 printf("        + - - - - - - - - - - +   %05lx\n",
1064                                           ((long int) globals_at)+480L);
1065 printf("        |       arrays        |   %s\n",
1066     show_percentage(grammar_table_at-(globals_at+480), Out_Size));
1067 printf("        +=====================+   %05lx\n",
1068                                           (long int) grammar_table_at);
1069 printf("Readable|    grammar table    |   %s\n",
1070     show_percentage(actions_at-grammar_table_at, Out_Size));
1071 printf("memory  + - - - - - - - - - - +   %05lx\n", (long int) actions_at);
1072 printf("        |       actions       |   %s\n",
1073     show_percentage(preactions_at-actions_at, Out_Size));
1074 printf("        + - - - - - - - - - - +   %05lx\n", (long int) preactions_at);
1075 printf("        |   parsing routines  |   %s\n",
1076     show_percentage(adjectives_offset-preactions_at, Out_Size));
1077 printf("        + - - - - - - - - - - +   %05lx\n",
1078                                           (long int) adjectives_offset);
1079 printf("        |     adjectives      |   %s\n",
1080     show_percentage(dictionary_at-adjectives_offset, Out_Size));
1081 printf("        +---------------------+   %05lx\n", (long int) dictionary_at);
1082 addr = (module_switch ? map_of_module : (static_array_area_size ? static_arrays_at : Write_Code_At));
1083 printf("        |     dictionary      |   %s\n",
1084     show_percentage(addr-dictionary_at, Out_Size));
1085 if (module_switch)
1086 {
1087 printf("        + - - - - - - - - - - +   %05lx\n",
1088                                           (long int) map_of_module);
1089 addr = (static_array_area_size ? static_arrays_at : Write_Code_At);
1090 printf("        | map of module addrs |   %s\n",
1091     show_percentage(addr-map_of_module, Out_Size));
1092 }
1093 if (static_array_area_size)
1094 {
1095 printf("        +---------------------+   %05lx\n", (long int) static_arrays_at);
1096 printf("        |    static arrays    |   %s\n",
1097     show_percentage(Write_Code_At-static_arrays_at, Out_Size));
1098 }
1099 printf("        +=====================+   %05lx\n", (long int) Write_Code_At);
1100 printf("Above   |       Z-code        |   %s\n",
1101     show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1102 printf("readable+---------------------+   %05lx\n",
1103                                           (long int) Write_Strings_At);
1104 addr = (module_switch ? link_table_at : Out_Size);
1105 printf("memory  |       strings       |   %s\n",
1106     show_percentage(addr-Write_Strings_At, Out_Size));
1107 if (module_switch)
1108 {
1109 printf("        +=====================+   %05lx\n", (long int) link_table_at);
1110 printf("        | module linking data |   %s\n",
1111     show_percentage(Out_Size-link_table_at, Out_Size));
1112 }
1113 printf("        +---------------------+   %05lx\n", (long int) Out_Size);
1114         }
1115     }
1116 }
1117
1118 static void construct_storyfile_g(void)
1119 {   uchar *p;
1120     int32 i, j, k, l, mark, strings_length;
1121     int32 globals_at, dictionary_at, actions_at, preactions_at,
1122           abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1123           grammar_table_at, arrays_at, static_arrays_at;
1124     int32 threespaces, code_length;
1125
1126     ASSERT_GLULX();
1127
1128     individual_name_strings =
1129         my_calloc(sizeof(int32), no_individual_properties,
1130             "identifier name strings");
1131     action_name_strings =
1132         my_calloc(sizeof(int32), no_actions + no_fake_actions,
1133             "action name strings");
1134     attribute_name_strings =
1135         my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1136             "attribute name strings");
1137     array_name_strings =
1138         my_calloc(sizeof(int32), 
1139             no_symbols,
1140             "array name strings");
1141
1142     write_the_identifier_names();
1143     threespaces = compile_string("   ", STRCTX_GAME);
1144
1145     compress_game_text();
1146
1147     /*  We now know how large the buffer to hold our construction has to be  */
1148
1149     zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1150         "output buffer");
1151
1152     /*  Foolish code to make this routine compile on all ANSI compilers      */
1153
1154     p = (uchar *) zmachine_paged_memory;
1155
1156     /*  In what follows, the "mark" will move upwards in memory: at various
1157         points its value will be recorded for milestones like
1158         "dictionary table start".  It begins at 0x40, just after the header  */
1159
1160     /* Ok, our policy here will be to set the *_at values all relative
1161        to RAM. That's so we can write into zmachine_paged_memory[mark] 
1162        and actually hit what we're aiming at.
1163        All the *_offset values will be set to true Glulx machine
1164        addresses. */
1165
1166     /* To get our bearings, figure out where the strings and code are. */
1167     /* We start with two words, which conventionally identify the 
1168        memory layout. This is why the code starts eight bytes after
1169        the header. */
1170     Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1171     if (!OMIT_UNUSED_ROUTINES) {
1172         code_length = zmachine_pc;
1173     }
1174     else {
1175         if (zmachine_pc != df_total_size_before_stripping)
1176             compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1177         code_length = df_total_size_after_stripping;
1178     }
1179     Write_Strings_At = Write_Code_At + code_length;
1180     strings_length = compression_table_size + compression_string_size;
1181
1182     static_arrays_at = Write_Strings_At + strings_length;
1183
1184     /* Now figure out where RAM starts. */
1185     Write_RAM_At = static_arrays_at + static_array_area_size;
1186     /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1187     while (Write_RAM_At % GPAGESIZE)
1188       Write_RAM_At++;
1189
1190     /* Now work out all those RAM positions. */
1191     mark = 0;
1192
1193     /*  ----------------- Variables and Dynamic Arrays --------------------- */
1194
1195     globals_at = mark;
1196     for (i=0; i<no_globals; i++) {
1197       j = global_initial_value[i];
1198       WriteInt32(p+mark, j);
1199       mark += 4;
1200     }
1201
1202     arrays_at = mark;
1203     for (i=0; i<dynamic_array_area_size; i++)
1204         p[mark++] = dynamic_array_area[i];
1205
1206     /* -------------------------- Dynamic Strings -------------------------- */
1207
1208     abbrevs_at = mark;
1209     WriteInt32(p+mark, no_dynamic_strings);
1210     mark += 4;
1211     for (i=0; i<no_dynamic_strings; i++) {
1212       j = Write_Strings_At + compressed_offsets[threespaces-1];
1213       WriteInt32(p+mark, j);
1214       mark += 4;
1215     }
1216
1217     /*  -------------------- Objects and Properties ------------------------ */
1218
1219     object_tree_at = mark;
1220
1221     object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1222
1223     for (i=0; i<no_objects; i++) {
1224       int32 objmark = mark;
1225       p[mark++] = 0x70; /* type byte -- object */
1226       for (j=0; j<NUM_ATTR_BYTES; j++) {
1227         p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1228       }
1229       for (j=0; j<6; j++) {
1230         int32 val = 0;
1231         switch (j) {
1232         case 0: /* next object in the linked list. */
1233           if (i == no_objects-1)
1234             val = 0;
1235           else
1236             val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1237           break;
1238         case 1: /* hardware name address */
1239           val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1240           break;
1241         case 2: /* property table address */
1242           val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1243           break;
1244         case 3: /* parent */
1245           if (objectsg[i].parent == 0)
1246             val = 0;
1247           else
1248             val = Write_RAM_At + object_tree_at +
1249               (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1250           break;
1251         case 4: /* sibling */
1252           if (objectsg[i].next == 0)
1253             val = 0;
1254           else
1255             val = Write_RAM_At + object_tree_at +
1256               (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1257           break;
1258         case 5: /* child */
1259           if (objectsg[i].child == 0)
1260             val = 0;
1261           else
1262             val = Write_RAM_At + object_tree_at +
1263               (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1264           break;
1265         }
1266         p[mark++] = (val >> 24) & 0xFF;
1267         p[mark++] = (val >> 16) & 0xFF;
1268         p[mark++] = (val >> 8) & 0xFF;
1269         p[mark++] = (val) & 0xFF;
1270       }
1271
1272       for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1273         p[mark++] = 0;
1274       }
1275     }
1276
1277     if (object_props_at != mark)
1278       error("*** Object table was impossible length ***");
1279
1280     for (i=0; i<properties_table_size; i++)
1281       p[mark+i]=properties_table[i];
1282
1283     for (i=0; i<no_objects; i++) { 
1284       int32 tableaddr = object_props_at + objectsg[i].propaddr;
1285       int32 tablelen = ReadInt32(p+tableaddr);
1286       tableaddr += 4;
1287       for (j=0; j<tablelen; j++) {
1288         k = ReadInt32(p+tableaddr+4);
1289         k += (Write_RAM_At + object_props_at);
1290         WriteInt32(p+tableaddr+4, k);
1291         tableaddr += 10;
1292       }
1293     }
1294
1295     mark += properties_table_size;
1296
1297     prop_defaults_at = mark;
1298     for (i=0; i<no_properties; i++) {
1299       k = commonprops[i].default_value;
1300       WriteInt32(p+mark, k);
1301       mark += 4;
1302     }
1303
1304     /*  ----------- Table of Class Prototype Object Numbers ---------------- */
1305     
1306     class_numbers_offset = mark;
1307     for (i=0; i<no_classes; i++) {
1308       j = Write_RAM_At + object_tree_at +
1309         (OBJECT_BYTE_LENGTH*(class_info[i].object_number-1));
1310       WriteInt32(p+mark, j);
1311       mark += 4;
1312     }
1313     WriteInt32(p+mark, 0);
1314     mark += 4;
1315
1316     /* -------------------- Table of Property Names ------------------------ */
1317
1318     /* We try to format this bit with some regularity...
1319        address of common properties
1320        number of common properties
1321        address of indiv properties
1322        number of indiv properties (counted from INDIV_PROP_START)
1323        address of attributes
1324        number of attributes (always NUM_ATTR_BYTES*8)
1325        address of actions
1326        number of actions
1327     */
1328
1329     identifier_names_offset = mark;
1330     mark += 32; /* eight pairs of values, to be filled in. */
1331
1332     WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1333     WriteInt32(p+identifier_names_offset+4, no_properties);
1334     for (i=0; i<no_properties; i++) {
1335       j = individual_name_strings[i];
1336       if (j)
1337         j = Write_Strings_At + compressed_offsets[j-1];
1338       WriteInt32(p+mark, j);
1339       mark += 4;
1340     }
1341
1342     WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1343     WriteInt32(p+identifier_names_offset+12, 
1344       no_individual_properties-INDIV_PROP_START);
1345     for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1346       j = individual_name_strings[i];
1347       if (j)
1348         j = Write_Strings_At + compressed_offsets[j-1];
1349       WriteInt32(p+mark, j);
1350       mark += 4;
1351     }
1352
1353     WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1354     WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1355     for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1356       j = attribute_name_strings[i];
1357       if (j)
1358         j = Write_Strings_At + compressed_offsets[j-1];
1359       WriteInt32(p+mark, j);
1360       mark += 4;
1361     }
1362
1363     WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1364     WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1365     action_names_offset = mark;
1366     fake_action_names_offset = mark + 4*no_actions;
1367     for (i=0; i<no_actions + no_fake_actions; i++) {
1368       j = action_name_strings[i];
1369       if (j)
1370         j = Write_Strings_At + compressed_offsets[j-1];
1371       WriteInt32(p+mark, j);
1372       mark += 4;
1373     }
1374
1375     array_names_offset = mark;
1376     WriteInt32(p+mark, no_arrays);
1377     mark += 4;
1378     for (i=0; i<no_arrays; i++) {
1379       j = array_name_strings[i];
1380       if (j)
1381         j = Write_Strings_At + compressed_offsets[j-1];
1382       WriteInt32(p+mark, j);
1383       mark += 4;
1384     }    
1385
1386     individuals_offset = mark;
1387
1388     /*  ------------------------ Grammar Table ----------------------------- */
1389
1390     if (grammar_version_number != 2)
1391     {   warning("This version of Inform is unable to produce the grammar \
1392 table format requested (producing number 2 format instead)");
1393         grammar_version_number = 2;
1394     }
1395
1396     grammar_table_at = mark;
1397
1398     WriteInt32(p+mark, no_Inform_verbs);
1399     mark += 4;
1400
1401     mark += no_Inform_verbs*4;
1402
1403     for (i=0; i<no_Inform_verbs; i++) {
1404       j = mark + Write_RAM_At;
1405       WriteInt32(p+(grammar_table_at+4+i*4), j);
1406       p[mark++] = Inform_verbs[i].lines;
1407       for (j=0; j<Inform_verbs[i].lines; j++) {
1408         int tok;
1409         k = Inform_verbs[i].l[j];
1410         p[mark++] = grammar_lines[k++];
1411         p[mark++] = grammar_lines[k++];
1412         p[mark++] = grammar_lines[k++];
1413         for (;;) {
1414           tok = grammar_lines[k++];
1415           p[mark++] = tok;
1416           if (tok == 15) break;
1417           p[mark++] = grammar_lines[k++];
1418           p[mark++] = grammar_lines[k++];
1419           p[mark++] = grammar_lines[k++];
1420           p[mark++] = grammar_lines[k++];
1421         }
1422       }
1423     }
1424
1425     /*  ------------------- Actions and Preactions ------------------------- */
1426
1427     actions_at = mark;
1428     WriteInt32(p+mark, no_actions);
1429     mark += 4;
1430     mark += no_actions*4;
1431     /* Values to be written in later. */
1432
1433     if (DICT_CHAR_SIZE != 1) {
1434       /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1435       while (mark % 4)
1436         p[mark++]=0;
1437     }
1438
1439     preactions_at = mark;
1440     adjectives_offset = mark;
1441     dictionary_offset = mark;
1442
1443     /*  ------------------------- Dictionary ------------------------------- */
1444
1445     dictionary_at = mark;
1446
1447     WriteInt32(dictionary+0, dict_entries);
1448     for (i=0; i<4; i++) 
1449       p[mark+i] = dictionary[i];
1450
1451     for (i=0; i<dict_entries; i++) {
1452       k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1453       j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1454       for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1455         p[j++] = dictionary[k++];
1456     }
1457     mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1458
1459     /*  -------------------------- All Data -------------------------------- */
1460     
1461     /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1462     while (mark % GPAGESIZE)
1463       p[mark++]=0;
1464
1465     RAM_Size = mark;
1466
1467     Out_Size = Write_RAM_At + RAM_Size;
1468
1469     /*  --------------------------- Offsets -------------------------------- */
1470
1471     dictionary_offset = Write_RAM_At + dictionary_at;
1472     variables_offset = Write_RAM_At + globals_at;
1473     arrays_offset = Write_RAM_At + arrays_at;
1474     actions_offset = Write_RAM_At + actions_at;
1475     preactions_offset = Write_RAM_At + preactions_at;
1476     prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1477     object_tree_offset = Write_RAM_At + object_tree_at;
1478     prop_values_offset = Write_RAM_At + object_props_at;
1479     static_memory_offset = Write_RAM_At + grammar_table_at;
1480     grammar_table_offset = Write_RAM_At + grammar_table_at;
1481     abbreviations_offset = Write_RAM_At + abbrevs_at;
1482
1483     code_offset = Write_Code_At;
1484     strings_offset = Write_Strings_At;
1485     static_arrays_offset = static_arrays_at;
1486
1487     /*  --------------------------- The Header ----------------------------- */
1488
1489     /*  ------ Backpatch the machine, now that all information is in ------- */
1490
1491     if (!module_switch)
1492     {   backpatch_zmachine_image_g();
1493
1494         mark = actions_at + 4;
1495         for (i=0; i<no_actions; i++) {
1496           j = actions[i].byte_offset;
1497           if (OMIT_UNUSED_ROUTINES)
1498             j = df_stripped_address_for_address(j);
1499           j += code_offset;
1500           WriteInt32(p+mark, j);
1501           mark += 4;
1502         }
1503
1504         for (l = 0; l<no_Inform_verbs; l++) {
1505           k = grammar_table_at + 4 + 4*l; 
1506           i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1507           i -= Write_RAM_At;
1508           for (j = p[i++]; j>0; j--) {
1509             int topbits; 
1510             int32 value;
1511             i = i + 3;
1512             while (p[i] != 15) {
1513               topbits = (p[i]/0x40) & 3;
1514               value = ((p[i+1] << 24) | (p[i+2] << 16) 
1515                 | (p[i+3] << 8) | (p[i+4]));
1516               switch(topbits) {
1517               case 1:
1518                 value = dictionary_offset + 4
1519                   + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1520                 break;
1521               case 2:
1522                 if (OMIT_UNUSED_ROUTINES)
1523                   value = df_stripped_address_for_address(value);
1524                 value += code_offset;
1525                 break;
1526               }
1527               WriteInt32(p+(i+1), value);
1528               i = i + 5;
1529             }
1530             i++;
1531           }
1532         }
1533
1534     }
1535
1536     /*  ---- From here on, it's all reportage: construction is finished ---- */
1537
1538     if (debugfile_switch)
1539     {   begin_writing_debug_sections();
1540         write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1541         write_debug_section("code area", Write_Code_At);
1542         write_debug_section("string decoding table", Write_Strings_At);
1543         write_debug_section("strings area",
1544                             Write_Strings_At + compression_table_size);
1545         write_debug_section("static array space", static_arrays_at);
1546         if (static_arrays_at + static_array_area_size < Write_RAM_At)
1547         {   write_debug_section
1548                 ("zero padding", static_arrays_at + static_array_area_size);
1549         }
1550         if (globals_at)
1551         {   compiler_error("Failed assumption that globals are at start of "
1552                            "Glulx RAM");
1553         }
1554         write_debug_section("global variables", Write_RAM_At + globals_at);
1555         write_debug_section("array space", Write_RAM_At + arrays_at);
1556         write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1557         write_debug_section("object tree", Write_RAM_At + object_tree_at);
1558         write_debug_section("common properties",
1559                             Write_RAM_At + object_props_at);
1560         write_debug_section("property defaults",
1561                             Write_RAM_At + prop_defaults_at);
1562         write_debug_section("class numbers",
1563                             Write_RAM_At + class_numbers_offset);
1564         write_debug_section("identifier names",
1565                             Write_RAM_At + identifier_names_offset);
1566         write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1567         write_debug_section("actions table", Write_RAM_At + actions_at);
1568         write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1569         if (MEMORY_MAP_EXTENSION)
1570         {   write_debug_section("zero padding", Out_Size);
1571         }
1572         end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1573     }
1574
1575     if (memory_map_setting)
1576     {
1577         int32 addr;
1578         {
1579 printf("        +---------------------+   000000\n");
1580 printf("Read-   |       header        |   %s\n",
1581     show_percentage(GLULX_HEADER_SIZE, Out_Size));
1582 printf(" only   +=====================+   %06lx\n", (long int) GLULX_HEADER_SIZE);
1583 printf("memory  |  memory layout id   |   %s\n",
1584     show_percentage(Write_Code_At-GLULX_HEADER_SIZE, Out_Size));
1585 printf("        +---------------------+   %06lx\n", (long int) Write_Code_At);
1586 printf("        |        code         |   %s\n",
1587     show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1588 printf("        +---------------------+   %06lx\n",
1589   (long int) Write_Strings_At);
1590 printf("        | string decode table |   %s\n",
1591     show_percentage(compression_table_size, Out_Size));
1592 printf("        + - - - - - - - - - - +   %06lx\n",
1593   (long int) Write_Strings_At + compression_table_size);
1594 addr = (static_array_area_size ? static_arrays_at : Write_RAM_At+globals_at);
1595 printf("        |       strings       |   %s\n",
1596     show_percentage(addr-(Write_Strings_At + compression_table_size), Out_Size));
1597             if (static_array_area_size)
1598             {
1599 printf("        +---------------------+   %06lx\n", 
1600   (long int) (static_arrays_at));
1601 printf("        |    static arrays    |   %s\n",
1602     show_percentage(Write_RAM_At+globals_at-static_arrays_at, Out_Size));
1603             }
1604 printf("        +=====================+   %06lx\n", 
1605   (long int) (Write_RAM_At+globals_at));
1606 printf("Dynamic |  global variables   |   %s\n",
1607     show_percentage(arrays_at-globals_at, Out_Size));
1608 printf("memory  + - - - - - - - - - - +   %06lx\n",
1609   (long int) (Write_RAM_At+arrays_at));
1610 printf("        |       arrays        |   %s\n",
1611     show_percentage(abbrevs_at-arrays_at, Out_Size));
1612 printf("        +---------------------+   %06lx\n",
1613   (long int) (Write_RAM_At+abbrevs_at));
1614 printf("        | printing variables  |   %s\n",
1615     show_percentage(object_tree_at-abbrevs_at, Out_Size));
1616 printf("        +---------------------+   %06lx\n", 
1617   (long int) (Write_RAM_At+object_tree_at));
1618 printf("        |       objects       |   %s\n",
1619     show_percentage(object_props_at-object_tree_at, Out_Size));
1620 printf("        + - - - - - - - - - - +   %06lx\n",
1621   (long int) (Write_RAM_At+object_props_at));
1622 printf("        |   property values   |   %s\n",
1623     show_percentage(prop_defaults_at-object_props_at, Out_Size));
1624 printf("        + - - - - - - - - - - +   %06lx\n",
1625   (long int) (Write_RAM_At+prop_defaults_at));
1626 printf("        |  property defaults  |   %s\n",
1627     show_percentage(class_numbers_offset-prop_defaults_at, Out_Size));
1628 printf("        + - - - - - - - - - - +   %06lx\n",
1629   (long int) (Write_RAM_At+class_numbers_offset));
1630 printf("        | class numbers table |   %s\n",
1631     show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1632 printf("        + - - - - - - - - - - +   %06lx\n",
1633   (long int) (Write_RAM_At+identifier_names_offset));
1634 printf("        |   id names table    |   %s\n",
1635     show_percentage(grammar_table_at-identifier_names_offset, Out_Size));
1636 printf("        +---------------------+   %06lx\n",
1637   (long int) (Write_RAM_At+grammar_table_at));
1638 printf("        |    grammar table    |   %s\n",
1639     show_percentage(actions_at-grammar_table_at, Out_Size));
1640 printf("        + - - - - - - - - - - +   %06lx\n", 
1641   (long int) (Write_RAM_At+actions_at));
1642 printf("        |       actions       |   %s\n",
1643     show_percentage(dictionary_offset-(Write_RAM_At+actions_at), Out_Size));
1644 printf("        +---------------------+   %06lx\n", 
1645   (long int) dictionary_offset);
1646 printf("        |     dictionary      |   %s\n",
1647     show_percentage(Out_Size-dictionary_offset, Out_Size));
1648             if (MEMORY_MAP_EXTENSION == 0)
1649             {
1650 printf("        +---------------------+   %06lx\n", (long int) Out_Size);
1651             }
1652             else
1653             {
1654 printf("        +=====================+   %06lx\n", (long int) Out_Size);
1655 printf("Runtime |       (empty)       |\n");   /* no percentage */
1656 printf("  extn  +---------------------+   %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1657             }
1658
1659         }
1660
1661     }
1662 }
1663
1664 static void display_frequencies()
1665 {
1666     int i, j;
1667     
1668     printf("How frequently abbreviations were used, and roughly\n");
1669     printf("how many bytes they saved:  ('_' denotes spaces)\n");
1670     
1671     for (i=0; i<no_abbreviations; i++) {
1672         int32 saving;
1673         if (!glulx_mode)
1674             saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
1675         else
1676             saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
1677         
1678         char abbrev_string[MAX_ABBREV_LENGTH];
1679         strcpy(abbrev_string,
1680                (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1681         for (j=0; abbrev_string[j]!=0; j++)
1682             if (abbrev_string[j]==' ') abbrev_string[j]='_';
1683         
1684         printf("%10s %5d/%5d   ",abbrev_string,abbreviations[i].freq, saving);
1685         
1686         if ((i%3)==2) printf("\n");
1687     }
1688     if ((i%3)!=0) printf("\n");
1689     
1690     if (no_abbreviations==0) printf("None were declared.\n");
1691 }
1692
1693 static void display_statistics_z()
1694 {
1695     int32 k_long, rate;
1696     char *k_str = "";
1697     uchar *p = (uchar *) zmachine_paged_memory;
1698     char *output_called = (module_switch)?"module":"story file";
1699     int limit = 0;
1700
1701     /* Yeah, we're repeating this calculation from construct_storyfile_z() */
1702     switch(version_number)
1703     {   case 3: limit = 128; break;
1704         case 4:
1705         case 5: limit = 256; break;
1706         case 6:
1707         case 7:
1708         case 8: limit = 512; break;
1709     }
1710
1711     k_long=(Out_Size/1024);
1712     if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1713     else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1714     if (total_bytes_trans == 0) rate = 0;
1715     else rate=total_bytes_trans*1000/total_chars_trans;
1716     
1717     {   printf("In:\
1718 %3d source code files            %6d syntactic lines\n\
1719 %6d textual lines              %8ld characters ",
1720                total_input_files, no_syntax_lines,
1721                total_source_line_count, (long int) total_chars_read);
1722         if (character_set_unicode) printf("(UTF-8)\n");
1723         else if (character_set_setting == 0) printf("(plain ASCII)\n");
1724         else
1725             {   printf("(ISO 8859-%d %s)\n", character_set_setting,
1726                        name_of_iso_set(character_set_setting));
1727             }
1728
1729         printf("Allocated:\n\
1730 %6d symbols                    %8ld bytes of memory\n\
1731 Out:   Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1732                no_symbols,
1733                (long int) malloced_bytes,
1734                version_number,
1735                version_name(version_number),
1736                output_called,
1737                release_number, p[18], p[19], p[20], p[21], p[22], p[23],
1738                (long int) k_long, k_str);
1739
1740         printf("\
1741 %6d classes                      %6d objects\n\
1742 %6d global vars (maximum 233)    %6d variable/array space\n",
1743                no_classes,
1744                no_objects,
1745                no_globals,
1746                dynamic_array_area_size);
1747
1748         printf(
1749                "%6d verbs                        %6d dictionary entries\n\
1750 %6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
1751 %6d actions                      %6d attributes (maximum %2d)\n\
1752 %6d common props (maximum %2d)    %6d individual props (unlimited)\n",
1753                no_Inform_verbs,
1754                dict_entries,
1755                no_grammar_lines, grammar_version_number,
1756                no_grammar_tokens,
1757                no_actions,
1758                no_attributes, ((version_number==3)?32:48),
1759                no_properties-3, ((version_number==3)?29:61),
1760                no_individual_properties - 64);
1761
1762         if (track_unused_routines)
1763             {
1764                 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1765                 printf(
1766                        "%6ld bytes of Z-code              %6ld unused bytes %s (%.1f%%)\n",
1767                        (long int) df_total_size_before_stripping, (long int) diff,
1768                        (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1769                        100 * (float)diff / (float)df_total_size_before_stripping);
1770             }
1771
1772         printf(
1773                "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
1774 %6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
1775 %6ld instructions of Z-code       %6d sequence points\n\
1776 %6ld bytes readable memory used (maximum 65536)\n\
1777 %6ld bytes used in Z-machine      %6ld bytes free in Z-machine\n",
1778                (long int) total_chars_trans,
1779                (long int) total_bytes_trans,
1780                (total_chars_trans>total_bytes_trans)?0:1,
1781                (long int) rate,
1782                no_abbreviations, MAX_ABBREVS,
1783                no_routines,
1784                (long int) no_instructions, no_sequence_points,
1785                (long int) Write_Code_At,
1786                (long int) Out_Size,
1787                (long int)
1788                (((long int) (limit*1024L)) - ((long int) Out_Size)));
1789
1790     }
1791 }
1792
1793 static void display_statistics_g()
1794 {
1795     int32 k_long, rate;
1796     char *k_str = "";
1797     int32 limit = 1024*1024;
1798     int32 strings_length = compression_table_size + compression_string_size;
1799     char *output_called = (module_switch)?"module":"story file";
1800     
1801     k_long=(Out_Size/1024);
1802     if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1803     else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1804     
1805     if (strings_length == 0) rate = 0;
1806     else rate=strings_length*1000/total_chars_trans;
1807
1808     {   printf("In:\
1809 %3d source code files            %6d syntactic lines\n\
1810 %6d textual lines              %8ld characters ",
1811                total_input_files, no_syntax_lines,
1812                total_source_line_count, (long int) total_chars_read);
1813         if (character_set_unicode) printf("(UTF-8)\n");
1814         else if (character_set_setting == 0) printf("(plain ASCII)\n");
1815         else
1816             {   printf("(ISO 8859-%d %s)\n", character_set_setting,
1817                        name_of_iso_set(character_set_setting));
1818             }
1819
1820         {char serialnum[8];
1821             write_serial_number(serialnum);
1822             printf("Allocated:\n\
1823 %6d symbols                    %8ld bytes of memory\n\
1824 Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1825                    no_symbols,
1826                    (long int) malloced_bytes,
1827                    version_name(version_number),
1828                    output_called,
1829                    release_number,
1830                    serialnum[0], serialnum[1], serialnum[2],
1831                    serialnum[3], serialnum[4], serialnum[5],
1832                    (long int) k_long, k_str);
1833         } 
1834
1835         printf("\
1836 %6d classes                      %6d objects\n\
1837 %6d global vars                  %6d variable/array space\n",
1838                no_classes,
1839                no_objects,
1840                no_globals,
1841                dynamic_array_area_size);
1842
1843         printf(
1844                "%6d verbs                        %6d dictionary entries\n\
1845 %6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
1846 %6d actions                      %6d attributes (maximum %2d)\n\
1847 %6d common props (maximum %3d)   %6d individual props (unlimited)\n",
1848                no_Inform_verbs,
1849                dict_entries,
1850                no_grammar_lines, grammar_version_number,
1851                no_grammar_tokens,
1852                no_actions,
1853                no_attributes, NUM_ATTR_BYTES*8,
1854                no_properties-3, INDIV_PROP_START-3,
1855                no_individual_properties - INDIV_PROP_START);
1856
1857         if (track_unused_routines)
1858             {
1859                 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1860                 printf(
1861                        "%6ld bytes of code                %6ld unused bytes %s (%.1f%%)\n",
1862                        (long int) df_total_size_before_stripping, (long int) diff,
1863                        (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1864                        100 * (float)diff / (float)df_total_size_before_stripping);
1865             }
1866
1867         printf(
1868                "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
1869 %6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
1870 %6ld instructions of code         %6d sequence points\n\
1871 %6ld bytes writable memory used   %6ld bytes read-only memory used\n\
1872 %6ld bytes used in machine    %10ld bytes free in machine\n",
1873                (long int) total_chars_trans,
1874                (long int) strings_length,
1875                (total_chars_trans>strings_length)?0:1,
1876                (long int) rate,
1877                no_abbreviations, MAX_ABBREVS,
1878                no_routines,
1879                (long int) no_instructions, no_sequence_points,
1880                (long int) (Out_Size - Write_RAM_At),
1881                (long int) Write_RAM_At,
1882                (long int) Out_Size,
1883                (long int)
1884                (((long int) (limit*1024L)) - ((long int) Out_Size)));
1885
1886     }
1887 }
1888
1889
1890 extern void construct_storyfile(void)
1891 {
1892     if (!glulx_mode)
1893         construct_storyfile_z();
1894     else
1895         construct_storyfile_g();
1896
1897     /* Display all the trace/stats info that came out of compilation.
1898
1899        (Except for the memory map, which uses a bunch of local variables
1900        from construct_storyfile_z/g(), so it's easier to do that inside
1901        that function.)
1902     */
1903     
1904     if (frequencies_setting)
1905         display_frequencies();
1906
1907     if (list_symbols_setting)
1908         list_symbols(list_symbols_setting);
1909     
1910     if (list_dict_setting)
1911         show_dictionary(list_dict_setting);
1912     
1913     if (list_verbs_setting)
1914         list_verb_table();
1915
1916     if (list_objects_setting)
1917         list_object_tree();
1918     
1919     if (statistics_switch) {
1920         if (!glulx_mode)
1921             display_statistics_z();
1922         else
1923             display_statistics_g();
1924     }
1925 }
1926
1927 /* ========================================================================= */
1928 /*   Data structure management routines                                      */
1929 /* ------------------------------------------------------------------------- */
1930
1931 extern void init_tables_vars(void)
1932 {
1933     release_number = 1;
1934     statusline_flag = SCORE_STYLE;
1935
1936     zmachine_paged_memory = NULL;
1937
1938     if (!glulx_mode) {
1939       code_offset = 0x800;
1940       actions_offset = 0x800;
1941       preactions_offset = 0x800;
1942       dictionary_offset = 0x800;
1943       adjectives_offset = 0x800;
1944       variables_offset = 0;
1945       strings_offset = 0xc00;
1946       individuals_offset=0x800;
1947       identifier_names_offset=0x800;
1948       class_numbers_offset = 0x800;
1949       arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1950       static_arrays_offset = 0x0800;
1951     }
1952     else {
1953       code_offset = 0x12345;
1954       actions_offset = 0x12345;
1955       preactions_offset = 0x12345;
1956       dictionary_offset = 0x12345;
1957       adjectives_offset = 0x12345;
1958       variables_offset = 0x12345;
1959       arrays_offset = 0x12345;
1960       strings_offset = 0x12345;
1961       individuals_offset=0x12345;
1962       identifier_names_offset=0x12345;
1963       class_numbers_offset = 0x12345;
1964       static_arrays_offset = 0x12345;
1965     }
1966 }
1967
1968 extern void tables_begin_pass(void)
1969 {
1970 }
1971
1972 extern void tables_allocate_arrays(void)
1973 {
1974 }
1975
1976 extern void tables_free_arrays(void)
1977 {
1978     /*  Allocation for this array happens in construct_storyfile() above     */
1979
1980     my_free(&zmachine_paged_memory,"output buffer");
1981 }
1982
1983 /* ========================================================================= */