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