inform.c: Update the copyright year that gets printed out in light of the change...
[inform.git] / arrays.c
1 /* ------------------------------------------------------------------------- */
2 /*   "arrays" :  Parses array declarations and constructs arrays from them;  */
3 /*               likewise global variables, which are in some ways a         */
4 /*               simpler form of the same thing.                             */
5 /*                                                                           */
6 /* Copyright (c) Graham Nelson 1993 - 2016                                   */
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 /* ------------------------------------------------------------------------- */
28 /*   Arrays defined below:                                                   */
29 /*                                                                           */
30 /*    int    dynamic_array_area[]         Initial values for the bytes of    */
31 /*                                        the dynamic array area             */
32 /*    int32  global_initial_value[n]      The initialised value of the nth   */
33 /*                                        global variable (counting 0 - 239) */
34 /*                                                                           */
35 /*   The "dynamic array area" is the Z-machine area holding the current      */
36 /*   values of the global variables (in 240x2 = 480 bytes) followed by any   */
37 /*   (dynamic) arrays which may be defined.  Owing to a poor choice of name  */
38 /*   some years ago, this is also called the "static data area", which is    */
39 /*   why the memory setting for its maximum extent is "MAX_STATIC_DATA".     */
40 /*                                                                           */
41 /*   In Glulx, that 240 is changed to MAX_GLOBAL_VAR_NUMBER, and we take     */
42 /*   correspondingly more space for the globals. This *really* ought to be   */
43 /*   split into two segments.                                                */
44 /* ------------------------------------------------------------------------- */
45 int     *dynamic_array_area;           /* See above                          */
46 int32   *global_initial_value;
47
48 int no_globals;                        /* Number of global variables used
49                                           by the programmer (Inform itself
50                                           uses the top seven -- but these do
51                                           not count)                         */
52                                        /* In Glulx, Inform uses the bottom 
53                                           ten.                               */
54
55 int dynamic_array_area_size;           /* Size in bytes                      */
56
57 int no_arrays;
58 int32   *array_symbols;
59 int     *array_sizes, *array_types;
60
61 static int array_entry_size,           /* 1 for byte array, 2 for word array */
62            array_base;                 /* Offset in dynamic array area of the
63                                           array being constructed.  During the
64                                           same time, dynamic_array_area_size
65                                           is the offset of the initial entry
66                                           in the array: so for "table" and
67                                           "string" arrays, these numbers are
68                                           different (by 2 and 1 bytes resp)  */
69
70                                        /* In Glulx, of course, that will be
71                                           4 instead of 2.                    */
72
73 extern void finish_array(int32 i)
74 {
75     /*  Write the array size into the 0th byte/word of the array, if it's
76         a "table" or "string" array                                          */
77   if (!glulx_mode) {
78
79     if (array_base!=dynamic_array_area_size)
80     {   if (dynamic_array_area_size-array_base==2)
81         {   dynamic_array_area[array_base]   = i/256;
82             dynamic_array_area[array_base+1] = i%256;
83         }
84         else
85         {   if (i>=256)
86                 error("A 'string' array can have at most 256 entries");
87             dynamic_array_area[array_base] = i;
88         }
89     }
90
91   }
92   else {
93     if (array_base!=dynamic_array_area_size)
94     {   if (dynamic_array_area_size-array_base==4)
95         {   
96             dynamic_array_area[array_base]   = (i >> 24) & 0xFF;
97             dynamic_array_area[array_base+1] = (i >> 16) & 0xFF;
98             dynamic_array_area[array_base+2] = (i >> 8) & 0xFF;
99             dynamic_array_area[array_base+3] = (i) & 0xFF;
100         }
101         else
102         {   if (i>=256)
103                 error("A 'string' array can have at most 256 entries");
104             dynamic_array_area[array_base] = i;
105         }
106     }
107     
108   }
109
110   /*  Move on the dynamic array size so that it now points to the next
111       available free space                                                   */
112
113   dynamic_array_area_size += i*array_entry_size;
114
115 }
116
117 extern void array_entry(int32 i, assembly_operand VAL)
118 {
119   if (!glulx_mode) {
120     /*  Array entry i (initial entry has i=0) is set to Z-machine value j    */
121
122     if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
123         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
124
125     if (array_entry_size==1)
126     {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value)%256;
127
128         if (VAL.marker != 0)
129            error("Entries in byte arrays and strings must be known constants");
130
131         /*  If the entry is too large for a byte array, issue a warning
132             and truncate the value                                           */
133         else
134         if (VAL.value >= 256)
135             warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
136     }
137     else
138     {   dynamic_array_area[dynamic_array_area_size + 2*i]   = (VAL.value)/256;
139         dynamic_array_area[dynamic_array_area_size + 2*i+1] = (VAL.value)%256;
140         if (VAL.marker != 0)
141             backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA,
142                 dynamic_array_area_size + 2*i);
143     }
144   }
145   else {
146     /*  Array entry i (initial entry has i=0) is set to value j              */
147
148     if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
149         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
150
151     if (array_entry_size==1)
152     {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value) & 0xFF;
153
154         if (VAL.marker != 0)
155            error("Entries in byte arrays and strings must be known constants");
156
157         /*  If the entry is too large for a byte array, issue a warning
158             and truncate the value                                           */
159         else
160         if (VAL.value >= 256)
161             warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
162     }
163     else if (array_entry_size==4)
164     {   dynamic_array_area[dynamic_array_area_size + 4*i]   = (VAL.value >> 24) & 0xFF;
165         dynamic_array_area[dynamic_array_area_size + 4*i+1] = (VAL.value >> 16) & 0xFF;
166         dynamic_array_area[dynamic_array_area_size + 4*i+2] = (VAL.value >> 8) & 0xFF;
167         dynamic_array_area[dynamic_array_area_size + 4*i+3] = (VAL.value) & 0xFF;
168         if (VAL.marker != 0)
169             backpatch_zmachine(VAL.marker, ARRAY_ZA,
170                 dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES + 4*i);
171     }
172     else
173     {
174         error("Somehow created an array of shorts");
175     }
176   }
177 }
178
179 /* ------------------------------------------------------------------------- */
180 /*   Global and Array directives.                                            */
181 /*                                                                           */
182 /*      Global <variablename> |                                              */
183 /*                            | = <value>                                    */
184 /*                            | <array specification>                        */
185 /*                                                                           */
186 /*      Array <arrayname> <array specification>                              */
187 /*                                                                           */
188 /*   where an array specification is:                                        */
189 /*                                                                           */
190 /*      | ->       |  <number-of-entries>                                    */
191 /*      | -->      |  <entry-1> ... <entry-n>                                */
192 /*      | string   |  [ <entry-1> [,] [;] <entry-2> ... <entry-n> ];         */
193 /*      | table                                                              */
194 /*                                                                           */
195 /* ------------------------------------------------------------------------- */
196
197 extern void set_variable_value(int i, int32 v)
198 {   global_initial_value[i]=v;
199 }
200
201 /*  There are four ways to initialise arrays:                                */
202
203 #define UNSPECIFIED_AI  -1
204 #define NULLS_AI        0
205 #define DATA_AI         1
206 #define ASCII_AI        2
207 #define BRACKET_AI      3
208
209 extern void make_global(int array_flag, int name_only)
210 {
211     /*  array_flag is TRUE for an Array directive, FALSE for a Global;
212         name_only is only TRUE for parsing an imported variable name, so
213         array_flag is always FALSE in that case.                             */
214
215     int32 i;
216     int array_type, data_type;
217     assembly_operand AO;
218
219     int32 global_symbol;
220     const char *global_name;
221     debug_location_beginning beginning_debug_location =
222         get_token_location_beginning();
223
224     directive_keywords.enabled = FALSE;
225     get_next_token();
226     i = token_value;
227     global_symbol = i;
228     global_name = token_text;
229
230     if (!glulx_mode) {
231         if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T)
232             && (svals[i] >= LOWEST_SYSTEM_VAR_NUMBER))
233             goto RedefinitionOfSystemVar;
234     }
235     else {
236         if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T))
237             goto RedefinitionOfSystemVar;
238     }
239
240     if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
241     {   discard_token_location(beginning_debug_location);
242         if (array_flag)
243             ebf_error("new array name", token_text);
244         else ebf_error("new global variable name", token_text);
245         panic_mode_error_recovery(); return;
246     }
247
248     if ((!array_flag) && (sflags[i] & USED_SFLAG))
249         error_named("Variable must be defined before use:", token_text);
250
251     if (array_flag)
252     {   
253         if (!glulx_mode)
254             assign_symbol(i, dynamic_array_area_size, ARRAY_T);
255         else
256             assign_symbol(i, 
257                 dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES, ARRAY_T);
258         if (no_arrays == MAX_ARRAYS)
259             memoryerror("MAX_ARRAYS", MAX_ARRAYS);
260         array_symbols[no_arrays] = i;
261     }
262     else
263     {   if (!glulx_mode && no_globals==233)
264         {   discard_token_location(beginning_debug_location);
265             error("All 233 global variables already declared");
266             panic_mode_error_recovery();
267             return;
268         }
269         if (glulx_mode && no_globals==MAX_GLOBAL_VARIABLES)
270         {   discard_token_location(beginning_debug_location);
271             memoryerror("MAX_GLOBAL_VARIABLES", MAX_GLOBAL_VARIABLES);
272             panic_mode_error_recovery();
273             return;
274         }
275
276         variable_tokens[MAX_LOCAL_VARIABLES+no_globals] = i;
277         assign_symbol(i, MAX_LOCAL_VARIABLES+no_globals, GLOBAL_VARIABLE_T);
278         variable_tokens[svals[i]] = i;
279
280         if (name_only) import_symbol(i);
281         else global_initial_value[no_globals++]=0;
282     }
283
284     directive_keywords.enabled = TRUE;
285
286     RedefinitionOfSystemVar:
287
288     if (name_only)
289     {   discard_token_location(beginning_debug_location);
290         return;
291     }
292
293     get_next_token();
294
295     if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
296     {   if (array_flag)
297         {   discard_token_location(beginning_debug_location);
298             ebf_error("array definition", token_text);
299         }
300         put_token_back();
301         if (debugfile_switch && !array_flag)
302         {   debug_file_printf("<global-variable>");
303             debug_file_printf("<identifier>%s</identifier>", global_name);
304             debug_file_printf("<address>");
305             write_debug_global_backpatch(svals[global_symbol]);
306             debug_file_printf("</address>");
307             write_debug_locations
308                 (get_token_location_end(beginning_debug_location));
309             debug_file_printf("</global-variable>");
310         }
311         return;
312     }
313
314     if (!array_flag)
315     {
316         if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
317         {   AO = parse_expression(CONSTANT_CONTEXT);
318             if (!glulx_mode) {
319                 if (AO.marker != 0)
320                     backpatch_zmachine(AO.marker, DYNAMIC_ARRAY_ZA,
321                         2*(no_globals-1));
322             }
323             else {
324             if (AO.marker != 0)
325                 backpatch_zmachine(AO.marker, GLOBALVAR_ZA,
326                 4*(no_globals-1));
327             }
328             global_initial_value[no_globals-1] = AO.value;
329             if (debugfile_switch)
330             {   debug_file_printf("<global-variable>");
331                 debug_file_printf("<identifier>%s</identifier>", global_name);
332                 debug_file_printf("<address>");
333                 write_debug_global_backpatch(svals[global_symbol]);
334                 debug_file_printf("</address>");
335                 write_debug_locations
336                     (get_token_location_end(beginning_debug_location));
337                 debug_file_printf("</global-variable>");
338             }
339             return;
340         }
341
342         obsolete_warning("more modern to use 'Array', not 'Global'");
343
344         if (!glulx_mode) {
345             backpatch_zmachine(ARRAY_MV, DYNAMIC_ARRAY_ZA, 2*(no_globals-1));
346             global_initial_value[no_globals-1]
347                 = dynamic_array_area_size+variables_offset;
348         }
349         else {
350             backpatch_zmachine(ARRAY_MV, GLOBALVAR_ZA, 4*(no_globals-1));
351             global_initial_value[no_globals-1]
352                 = dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES;
353         }
354     }
355
356     array_type = BYTE_ARRAY; data_type = UNSPECIFIED_AI;
357
358          if ((!array_flag) &&
359              ((token_type==DIR_KEYWORD_TT)&&(token_value==DATA_DK)))
360                  data_type=NULLS_AI;
361     else if ((!array_flag) &&
362              ((token_type==DIR_KEYWORD_TT)&&(token_value==INITIAL_DK)))
363                  data_type=DATA_AI;
364     else if ((!array_flag) &&
365              ((token_type==DIR_KEYWORD_TT)&&(token_value==INITSTR_DK)))
366                  data_type=ASCII_AI;
367
368     else if ((token_type==SEP_TT)&&(token_value==ARROW_SEP))
369              array_type = BYTE_ARRAY;
370     else if ((token_type==SEP_TT)&&(token_value==DARROW_SEP))
371              array_type = WORD_ARRAY;
372     else if ((token_type==DIR_KEYWORD_TT)&&(token_value==STRING_DK))
373              array_type = STRING_ARRAY;
374     else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TABLE_DK))
375              array_type = TABLE_ARRAY;
376     else if ((token_type==DIR_KEYWORD_TT)&&(token_value==BUFFER_DK))
377              array_type = BUFFER_ARRAY;
378     else
379     {   discard_token_location(beginning_debug_location);
380         if (array_flag)
381             ebf_error
382               ("'->', '-->', 'string', 'table' or 'buffer'", token_text);
383         else
384             ebf_error
385               ("'=', '->', '-->', 'string', 'table' or 'buffer'", token_text);
386         panic_mode_error_recovery();
387         return;
388     }
389
390     array_entry_size=1;
391     if ((array_type==WORD_ARRAY) || (array_type==TABLE_ARRAY))
392         array_entry_size=WORDSIZE;
393
394     get_next_token();
395     if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
396     {   discard_token_location(beginning_debug_location);
397         error("No array size or initial values given");
398         put_token_back();
399         return;
400     }
401
402     switch(data_type)
403     {   case UNSPECIFIED_AI:
404             if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
405                 data_type = BRACKET_AI;
406             else
407             {   data_type = NULLS_AI;
408                 if (token_type == DQ_TT) data_type = ASCII_AI;
409                 get_next_token();
410                 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
411                     data_type = DATA_AI;
412                 put_token_back();
413                 put_token_back();
414             }
415             break;
416         case NULLS_AI: obsolete_warning("use '->' instead of 'data'"); break;
417         case DATA_AI:  obsolete_warning("use '->' instead of 'initial'"); break;
418         case ASCII_AI: obsolete_warning("use '->' instead of 'initstr'"); break;
419     }
420
421     array_base = dynamic_array_area_size;
422
423     /*  Leave room to write the array size in later, if string/table array   */
424
425     if ((array_type==STRING_ARRAY) || (array_type==TABLE_ARRAY))
426         dynamic_array_area_size += array_entry_size;
427     if (array_type==BUFFER_ARRAY)
428         dynamic_array_area_size += WORDSIZE;
429     array_types[no_arrays] = array_type;
430
431     switch(data_type)
432     {
433         case NULLS_AI:
434
435             AO = parse_expression(CONSTANT_CONTEXT);
436
437             CalculatedArraySize:
438
439             if (module_switch && (AO.marker != 0))
440             {   error("Array sizes must be known now, not externally defined");
441                 break;
442             }
443
444             if (!glulx_mode) {
445                 if ((AO.value <= 0) || (AO.value >= 32768))
446                 {   error("An array must have between 1 and 32767 entries");
447                     AO.value = 1;
448                 }
449             }
450             else {
451                 if (AO.value <= 0 || (AO.value & 0x80000000))
452                 {   error("An array may not have 0 or fewer entries");
453                     AO.value = 1;
454                 }
455             }
456
457             {   for (i=0; i<AO.value; i++) array_entry(i, zero_operand);
458             }
459             break;
460
461         case DATA_AI:
462
463             /*  In this case the array is initialised to the sequence of
464                 constant values supplied on the same line                    */
465
466             i=0;
467             do
468             {   get_next_token();
469                 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
470                     break;
471
472                 if ((token_type == SEP_TT)
473                     && ((token_value == OPEN_SQUARE_SEP)
474                         || (token_value == CLOSE_SQUARE_SEP)))
475                 {   discard_token_location(beginning_debug_location);
476                     error("Missing ';' to end the initial array values "
477                           "before \"[\" or \"]\"");
478                     return;
479                 }
480                 put_token_back();
481
482                 AO = parse_expression(ARRAY_CONTEXT);
483
484                 if (i == 0)
485                 {   get_next_token();
486                     put_token_back();
487                     if ((token_type == SEP_TT)
488                         && (token_value == SEMICOLON_SEP))
489                     {   data_type = NULLS_AI;
490                         goto CalculatedArraySize;
491                     }
492                 }
493
494                 array_entry(i, AO);
495                 i++;
496             } while (TRUE);
497             put_token_back();
498             break;
499
500         case ASCII_AI:
501
502             /*  In this case the array is initialised to the ASCII values of
503                 the characters of a given "quoted string"                    */
504
505             get_next_token();
506             if (token_type != DQ_TT)
507             {   ebf_error("literal text in double-quotes", token_text);
508                 token_text = "error";
509             }
510
511             {   assembly_operand chars;
512
513                 int j;
514                 INITAO(&chars);
515                 for (i=0,j=0; token_text[j]!=0; i++,j+=textual_form_length)
516                 {
517                     int32 unicode; int zscii;
518                     unicode = text_to_unicode(token_text+j);
519                     if (glulx_mode)
520                     {
521                         if (array_entry_size == 1 && (unicode < 0 || unicode >= 256))
522                         {
523                             error("Unicode characters beyond Latin-1 cannot be used in a byte array");
524                         }
525                         else
526                         {
527                             chars.value = unicode;
528                         }
529                     }
530                     else  /* Z-code */
531                     {                          
532                         zscii = unicode_to_zscii(unicode);
533                         if ((zscii != 5) && (zscii < 0x100)) chars.value = zscii;
534                         else
535                         {   unicode_char_error("Character can only be used if declared in \
536 advance as part of 'Zcharacter table':", unicode);
537                             chars.value = '?';
538                         }
539                     }
540                     chars.marker = 0;
541                     set_constant_ot(&chars);
542                     array_entry(i, chars);
543                 }
544             }
545             break;
546
547         case BRACKET_AI:
548
549             /*  In this case the array is initialised to the sequence of
550                 constant values given over a whole range of compiler-lines,
551                 between square brackets [ and ]                              */
552
553             i = 0;
554             while (TRUE)
555             {   get_next_token();
556                 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
557                     continue;
558                 if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP))
559                     break;
560                 if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
561                 {   /*  Minimal error recovery: we assume that a ] has
562                         been missed, and the programmer is now starting
563                         a new routine                                        */
564
565                     ebf_error("']'", token_text);
566                     put_token_back(); break;
567                 }
568                 put_token_back();
569                 array_entry(i, parse_expression(ARRAY_CONTEXT));
570                 i++;
571             }
572     }
573
574     finish_array(i);
575
576     if (debugfile_switch)
577     {   debug_file_printf("<array>");
578         debug_file_printf("<identifier>%s</identifier>", global_name);
579         debug_file_printf("<value>");
580         write_debug_array_backpatch(svals[global_symbol]);
581         debug_file_printf("</value>");
582         debug_file_printf
583             ("<byte-count>%d</byte-count>",
584              dynamic_array_area_size - array_base);
585         debug_file_printf
586             ("<bytes-per-element>%d</bytes-per-element>",
587              array_entry_size);
588         debug_file_printf
589             ("<zeroth-element-holds-length>%s</zeroth-element-holds-length>",
590              (array_type == STRING_ARRAY || array_type == TABLE_ARRAY) ?
591                  "true" : "false");
592         get_next_token();
593         write_debug_locations(get_token_location_end(beginning_debug_location));
594         put_token_back();
595         debug_file_printf("</array>");
596     }
597
598     if ((array_type==BYTE_ARRAY) || (array_type==WORD_ARRAY)) i--;
599     if (array_type==BUFFER_ARRAY) i+=WORDSIZE-1;
600     array_sizes[no_arrays++] = i;
601 }
602
603 extern int32 begin_table_array(void)
604 {
605     /*  The "box" statement needs to be able to construct (static) table
606         arrays of strings like this                                          */
607
608     array_base = dynamic_array_area_size;
609     array_entry_size = WORDSIZE;
610
611     /*  Leave room to write the array size in later                          */
612
613     dynamic_array_area_size += array_entry_size;
614
615     if (!glulx_mode)
616         return array_base;
617     else
618         return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES;
619 }
620
621 extern int32 begin_word_array(void)
622 {
623     /*  The "random(a, b, ...)" function needs to be able to construct
624         (static) word arrays like this                                       */
625
626     array_base = dynamic_array_area_size;
627     array_entry_size = WORDSIZE;
628
629     if (!glulx_mode)
630         return array_base;
631     else
632         return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES;
633 }
634
635 /* ========================================================================= */
636 /*   Data structure management routines                                      */
637 /* ------------------------------------------------------------------------- */
638
639 extern void init_arrays_vars(void)
640 {   dynamic_array_area = NULL;
641     global_initial_value = NULL;
642     array_sizes = NULL; array_symbols = NULL; array_types = NULL;
643 }
644
645 extern void arrays_begin_pass(void)
646 {   no_arrays = 0; 
647     if (!glulx_mode)
648         no_globals=0; 
649     else
650         no_globals=11;
651     dynamic_array_area_size = WORDSIZE * MAX_GLOBAL_VARIABLES;
652 }
653
654 extern void arrays_allocate_arrays(void)
655 {   dynamic_array_area = my_calloc(sizeof(int), MAX_STATIC_DATA, 
656         "static data");
657     array_sizes = my_calloc(sizeof(int), MAX_ARRAYS, "array sizes");
658     array_types = my_calloc(sizeof(int), MAX_ARRAYS, "array types");
659     array_symbols = my_calloc(sizeof(int32), MAX_ARRAYS, "array symbols");
660     global_initial_value = my_calloc(sizeof(int32), MAX_GLOBAL_VARIABLES, 
661         "global values");
662 }
663
664 extern void arrays_free_arrays(void)
665 {   my_free(&dynamic_array_area, "static data");
666     my_free(&global_initial_value, "global values");
667     my_free(&array_sizes, "array sizes");
668     my_free(&array_types, "array sizes");
669     my_free(&array_symbols, "array sizes");
670 }
671
672 /* ========================================================================= */