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