Implement a Makefile for Inform.
[inform.git] / expressp.c
diff --git a/expressp.c b/expressp.c
deleted file mode 100644 (file)
index 79f7c7a..0000000
+++ /dev/null
@@ -1,2080 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "expressp" :  The expression parser                                     */
-/*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
-/*                                                                           */
-/* This file is part of Inform.                                              */
-/*                                                                           */
-/* Inform is free software: you can redistribute it and/or modify            */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation, either version 3 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Inform is distributed in the hope that it will be useful,                 */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with Inform. If not, see https://gnu.org/licenses/                  */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-#include "header.h"
-
-/* --- Interface to lexer -------------------------------------------------- */
-
-static char separators_to_operators[103];
-static char conditionals_to_operators[7];
-static char token_type_allowable[301];
-
-#define NOT_AN_OPERATOR (char) 0x7e
-
-static void make_lexical_interface_tables(void)
-{   int i;
-    for (i=0;i<103;i++)
-        separators_to_operators[i] = NOT_AN_OPERATOR;
-    for (i=0;i<NUM_OPERATORS;i++)
-        if (operators[i].token_type == SEP_TT)
-            separators_to_operators[operators[i].token_value] = i;
-
-    for (i=0;i<7;i++)  /*  7 being the size of keyword_group "conditions"  */
-        conditionals_to_operators[i] = NOT_AN_OPERATOR;
-    for (i=0;i<NUM_OPERATORS;i++)
-        if (operators[i].token_type == CND_TT)
-            conditionals_to_operators[operators[i].token_value] = i;
-
-    for (i=0;i<301;i++) token_type_allowable[i] = 0;
-
-    token_type_allowable[VARIABLE_TT] = 1;
-    token_type_allowable[SYSFUN_TT] = 1;
-    token_type_allowable[DQ_TT] = 1;
-    token_type_allowable[DICTWORD_TT] = 1;
-    token_type_allowable[SUBOPEN_TT] = 1;
-    token_type_allowable[SUBCLOSE_TT] = 1;
-    token_type_allowable[SMALL_NUMBER_TT] = 1;
-    token_type_allowable[LARGE_NUMBER_TT] = 1;
-    token_type_allowable[ACTION_TT] = 1;
-    token_type_allowable[SYSTEM_CONSTANT_TT] = 1;
-    token_type_allowable[OP_TT] = 1;
-}
-
-static token_data current_token, previous_token, heldback_token;
-
-static int comma_allowed, arrow_allowed, superclass_allowed,
-           bare_prop_allowed,
-           array_init_ambiguity, action_ambiguity,
-           etoken_count, inserting_token, bracket_level;
-
-extern int *variable_usage;
-
-int system_function_usage[32];
-
-static int get_next_etoken(void)
-{   int v, symbol = 0, mark_symbol_as_used = FALSE,
-        initial_bracket_level = bracket_level;
-
-    etoken_count++;
-
-    if (inserting_token)
-    {   current_token = heldback_token;
-        inserting_token = FALSE;
-    }
-    else
-    {   get_next_token();
-        current_token.text = token_text;
-        current_token.value = token_value;
-        current_token.type = token_type;
-        current_token.marker = 0;
-        current_token.symtype = 0;
-        current_token.symflags = -1;
-    }
-
-    switch(current_token.type)
-    {   case LOCAL_VARIABLE_TT:
-            current_token.type = VARIABLE_TT;
-            variable_usage[current_token.value] = TRUE;
-            break;
-
-        case DQ_TT:
-            current_token.marker = STRING_MV;
-            break;
-
-        case SQ_TT:
-            {   int32 unicode = text_to_unicode(token_text);
-                if (token_text[textual_form_length] == 0)
-                {
-                    if (!glulx_mode) {
-                        current_token.value = unicode_to_zscii(unicode);
-                        if (current_token.value == 5)
-                        {   unicode_char_error("Character can be printed \
-but not used as a value:", unicode);
-                            current_token.value = '?';
-                        }
-                        if (current_token.value >= 0x100)
-                            current_token.type = LARGE_NUMBER_TT;
-                        else current_token.type = SMALL_NUMBER_TT;
-                    }
-                    else {
-                        current_token.value = unicode;
-                        if (current_token.value >= 0x8000
-                          || current_token.value < -0x8000) 
-                            current_token.type = LARGE_NUMBER_TT;
-                        else current_token.type = SMALL_NUMBER_TT;
-                    }
-                }
-                else
-                {   current_token.type = DICTWORD_TT;
-                    current_token.marker = DWORD_MV;
-                }
-            }
-            break;
-
-        case SYMBOL_TT:
-        ReceiveSymbol:
-            symbol = current_token.value;
-
-            mark_symbol_as_used = TRUE;
-
-            v = svals[symbol];
-
-            current_token.symtype = stypes[symbol];
-            current_token.symflags = sflags[symbol];
-            switch(stypes[symbol])
-            {   case ROUTINE_T:
-                    /* Replaced functions must always be backpatched
-                       because there could be another definition coming. */
-                    if (sflags[symbol] & REPLACE_SFLAG)
-                    {   current_token.marker = SYMBOL_MV;
-                        if (module_switch) import_symbol(symbol);
-                        v = symbol;
-                        break;
-                    }
-                    current_token.marker = IROUTINE_MV;
-                    break;
-                case GLOBAL_VARIABLE_T:
-                    current_token.marker = VARIABLE_MV;
-                    break;
-                case OBJECT_T:
-                case CLASS_T:
-                    /* All objects must be backpatched in Glulx. */
-                    if (module_switch || glulx_mode)
-                        current_token.marker = OBJECT_MV;
-                    break;
-                case ARRAY_T:
-                    current_token.marker = ARRAY_MV;
-                    break;
-                case INDIVIDUAL_PROPERTY_T:
-                    if (module_switch) current_token.marker = IDENT_MV;
-                    break;
-                case CONSTANT_T:
-                    if (sflags[symbol] & (UNKNOWN_SFLAG + CHANGE_SFLAG))
-                    {   current_token.marker = SYMBOL_MV;
-                        if (module_switch) import_symbol(symbol);
-                        v = symbol;
-                    }
-                    else current_token.marker = 0;
-                    break;
-                case LABEL_T:
-                    error_named("Label name used as value:", token_text);
-                    break;
-                default:
-                    current_token.marker = 0;
-                    break;
-            }
-            if (sflags[symbol] & SYSTEM_SFLAG)
-                current_token.marker = 0;
-
-            current_token.value = v;
-
-            if (!glulx_mode) {
-                if (((current_token.marker != 0)
-                  && (current_token.marker != VARIABLE_MV))
-                  || (v < 0) || (v > 255))
-                    current_token.type = LARGE_NUMBER_TT;
-                else current_token.type = SMALL_NUMBER_TT;
-            }
-            else {
-                if (((current_token.marker != 0)
-                  && (current_token.marker != VARIABLE_MV))
-                  || (v < -0x8000) || (v >= 0x8000)) 
-                    current_token.type = LARGE_NUMBER_TT;
-                else current_token.type = SMALL_NUMBER_TT;
-            }
-
-            if (stypes[symbol] == GLOBAL_VARIABLE_T)
-            {   current_token.type = VARIABLE_TT;
-                variable_usage[current_token.value] = TRUE;
-            }
-            break;
-
-        case NUMBER_TT:
-            if (!glulx_mode) {
-                if (current_token.value >= 256)
-                    current_token.type = LARGE_NUMBER_TT;
-                else
-                    current_token.type = SMALL_NUMBER_TT;
-            }
-            else {
-                if (current_token.value < -0x8000 
-                  || current_token.value >= 0x8000)
-                    current_token.type = LARGE_NUMBER_TT;
-                else
-                    current_token.type = SMALL_NUMBER_TT;
-            }
-            break;
-
-        case SEP_TT:
-            switch(current_token.value)
-            {   case ARROW_SEP:
-                    if (!arrow_allowed)
-                        current_token.type = ENDEXP_TT;
-                    break;
-
-                case COMMA_SEP:
-                    if ((bracket_level==0) && (!comma_allowed))
-                        current_token.type = ENDEXP_TT;
-                    break;
-
-                case SUPERCLASS_SEP:
-                    if ((bracket_level==0) && (!superclass_allowed))
-                        current_token.type = ENDEXP_TT;
-                    break;
-
-                case GREATER_SEP:
-                    get_next_token();
-                    if ((token_type == SEP_TT)
-                        &&((token_value == SEMICOLON_SEP)
-                           || (token_value == GREATER_SEP)))
-                        current_token.type = ENDEXP_TT;
-                    put_token_back();
-                    break;
-
-                case OPENB_SEP:
-                    bracket_level++;
-                    if (expr_trace_level>=3)
-                    { printf("Previous token type = %d\n",previous_token.type);
-                      printf("Previous token val  = %d\n",previous_token.value);
-                    }
-                    if ((previous_token.type == OP_TT)
-                        || (previous_token.type == SUBOPEN_TT)
-                        || (previous_token.type == ENDEXP_TT)
-                        || (array_init_ambiguity)
-                        || ((bracket_level == 1) && (action_ambiguity)))
-                        current_token.type = SUBOPEN_TT;
-                    else
-                    {   inserting_token = TRUE;
-                        heldback_token = current_token;
-                        current_token.text = "<call>";
-                        bracket_level--;
-                    }
-                    break;
-
-                case CLOSEB_SEP:
-                    bracket_level--;
-                    if (bracket_level < 0)
-                        current_token.type = ENDEXP_TT;
-                    else current_token.type = SUBCLOSE_TT;
-                    break;
-
-                case SEMICOLON_SEP:
-                    current_token.type = ENDEXP_TT; break;
-
-                case MINUS_SEP:
-                    if ((previous_token.type == OP_TT)
-                        || (previous_token.type == SUBOPEN_TT)
-                        || (previous_token.type == ENDEXP_TT))
-                    current_token.value = UNARY_MINUS_SEP; break;
-
-                case INC_SEP:
-                    if ((previous_token.type == VARIABLE_TT)
-                        || (previous_token.type == SUBCLOSE_TT)
-                        || (previous_token.type == LARGE_NUMBER_TT)
-                        || (previous_token.type == SMALL_NUMBER_TT))
-                    current_token.value = POST_INC_SEP; break;
-
-                case DEC_SEP:
-                    if ((previous_token.type == VARIABLE_TT)
-                        || (previous_token.type == SUBCLOSE_TT)
-                        || (previous_token.type == LARGE_NUMBER_TT)
-                        || (previous_token.type == SMALL_NUMBER_TT))
-                    current_token.value = POST_DEC_SEP; break;
-
-                case HASHHASH_SEP:
-                    token_text = current_token.text + 2;
-
-                    ActionUsedAsConstant:
-
-                    current_token.type = ACTION_TT;
-                    current_token.text = token_text;
-                    current_token.value = 0;
-                    current_token.marker = ACTION_MV;
-
-                    break;
-
-                case HASHADOLLAR_SEP:
-                obsolete_warning("'#a$Act' is now superseded by '##Act'");
-                    token_text = current_token.text + 3;
-                    goto ActionUsedAsConstant;
-
-                case HASHGDOLLAR_SEP:
-
-                /* This form generates the position of a global variable
-                   in the global variables array. So Glob is the same as
-                   #globals_array --> #g$Glob                                */
-
-                    current_token.text += 3;
-                    current_token.type = SYMBOL_TT;
-                    symbol = symbol_index(current_token.text, -1);
-                    if (stypes[symbol] != GLOBAL_VARIABLE_T) {
-                        ebf_error(
-                        "global variable name after '#g$'",
-                        current_token.text);
-                        current_token.value = 0;
-                        current_token.type = SMALL_NUMBER_TT;
-                        current_token.marker = 0;
-                        break;
-                    }
-                    mark_symbol_as_used = TRUE;
-                    current_token.value = svals[symbol] - MAX_LOCAL_VARIABLES;
-                    current_token.marker = 0;
-                    if (!glulx_mode) {
-                        if (current_token.value >= 0x100)
-                            current_token.type = LARGE_NUMBER_TT;
-                        else current_token.type = SMALL_NUMBER_TT;
-                    }
-                    else {
-                        if (current_token.value >= 0x8000
-                          || current_token.value < -0x8000) 
-                            current_token.type = LARGE_NUMBER_TT;
-                        else current_token.type = SMALL_NUMBER_TT;
-                    }
-                    break;
-
-                case HASHNDOLLAR_SEP:
-
-                /* This form is still needed for constants like #n$a (the
-                   dictionary address of the word "a"), since 'a' means
-                   the ASCII value of 'a'                                    */
-
-                    if (strlen(token_text) > 4)
-                        obsolete_warning(
-                            "'#n$word' is now superseded by ''word''");
-                    current_token.type  = DICTWORD_TT;
-                    current_token.value = 0;
-                    current_token.text  = token_text + 3;
-                    current_token.marker = DWORD_MV;
-                    break;
-
-                case HASHRDOLLAR_SEP:
-
-                /*  This form -- #r$Routinename, to return the routine's     */
-                /*  packed address -- is needed far less often in Inform 6,  */
-                /*  where just giving the name Routine returns the packed    */
-                /*  address.  But it's used in a lot of Inform 5 code.       */
-
-                    obsolete_warning(
-                        "'#r$Routine' can now be written just 'Routine'");
-                    current_token.text += 3;
-                    current_token.type = SYMBOL_TT;
-                    current_token.value = symbol_index(current_token.text, -1);
-                    goto ReceiveSymbol;
-
-                case HASHWDOLLAR_SEP:
-                    error("The obsolete '#w$word' construct has been removed");
-                    break;
-
-                case HASH_SEP:
-                    system_constants.enabled = TRUE;
-                    get_next_token();
-                    system_constants.enabled = FALSE;
-                    if (token_type != SYSTEM_CONSTANT_TT)
-                    {   ebf_error(
-                        "'r$', 'n$', 'g$' or internal Inform constant name after '#'",
-                        token_text);
-                        break;
-                    }
-                    else
-                    {   current_token.type   = token_type;
-                        current_token.value  = token_value;
-                        current_token.text   = token_text;
-                        current_token.marker = INCON_MV;
-                    }
-                    break;
-            }
-            break;
-
-        case CND_TT:
-            v = conditionals_to_operators[current_token.value];
-            if (v != NOT_AN_OPERATOR)
-            {   current_token.type = OP_TT; current_token.value = v;
-            }
-            break;
-    }
-
-    if (current_token.type == SEP_TT)
-    {   v = separators_to_operators[current_token.value];
-        if (v != NOT_AN_OPERATOR)
-        {   if ((veneer_mode)
-                || ((v!=MESSAGE_OP) && (v!=MPROP_NUM_OP) && (v!=MPROP_NUM_OP)))
-            {   current_token.type = OP_TT; current_token.value = v;
-                if (array_init_ambiguity &&
-                    ((v==MINUS_OP) || (v==UNARY_MINUS_OP)) &&
-                    (initial_bracket_level == 0) &&
-                    (etoken_count != 1))
-                warning("Without bracketing, the minus sign '-' is ambiguous");
-            }
-        }
-    }
-
-    /*  A feature of Inform making it annoyingly hard to parse left-to-right
-        is that there is no clear delimiter for expressions; that is, the
-        legal syntax often includes sequences of expressions with no
-        intervening markers such as commas.  We therefore need to use some
-        internal context to determine whether an end is in sight...          */
-
-    if (token_type_allowable[current_token.type]==0)
-    {   if (expr_trace_level >= 3)
-        {   printf("Discarding as not allowable: '%s' ", current_token.text);
-            describe_token(current_token);
-            printf("\n");
-        }
-        current_token.type = ENDEXP_TT;
-    }
-    else
-    if ((!((initial_bracket_level > 0)
-           || (previous_token.type == ENDEXP_TT)
-           || ((previous_token.type == OP_TT)
-               && (operators[previous_token.value].usage != POST_U))
-           || (previous_token.type == SYSFUN_TT)))
-        && ((current_token.type != OP_TT)
-            || (operators[current_token.value].usage == PRE_U)))
-    {   if (expr_trace_level >= 3)
-        {   printf("Discarding as no longer part: '%s' ", current_token.text);
-            describe_token(current_token);
-            printf("\n");
-        }
-        current_token.type = ENDEXP_TT;
-    }
-    else
-    {   if (mark_symbol_as_used) sflags[symbol] |= USED_SFLAG;
-        if (expr_trace_level >= 3)
-        {   printf("Expr token = '%s' ", current_token.text);
-            describe_token(current_token);
-            printf("\n");
-        }
-    }
-
-    if ((previous_token.type == ENDEXP_TT)
-        && (current_token.type == ENDEXP_TT)) return FALSE;
-
-    previous_token = current_token;
-
-    return TRUE;
-}
-
-/* --- Operator precedences ------------------------------------------------ */
-
-#define LOWER_P   101
-#define EQUAL_P   102
-#define GREATER_P 103
-
-#define e1        1       /* Missing operand error                */
-#define e2        2       /* Unexpected close bracket             */
-#define e3        3       /* Missing operator error               */
-#define e4        4       /* Expression ends with an open bracket */
-#define e5        5       /* Associativity illegal error          */
-
-const int prec_table[] = {
-
-/* a .......... (         )           end       op          term             */
-
-/* b  (    */   LOWER_P,  e3,         LOWER_P,  LOWER_P,    e3,
-/* .  )    */   EQUAL_P,  GREATER_P,  e2,       GREATER_P,  GREATER_P,
-/* .  end  */   e4,       GREATER_P,  e1,       GREATER_P,  GREATER_P,
-/* .  op   */   LOWER_P,  GREATER_P,  LOWER_P,  -1,         GREATER_P,
-/* .  term */   LOWER_P,  e3,         LOWER_P,  LOWER_P,    e3
-
-};
-
-static int find_prec(token_data a, token_data b)
-{
-    /*  We are comparing the precedence of tokens  a  and  b
-        (where a occurs to the left of b).  If the expression is correct,
-        the only possible values are GREATER_P, LOWER_P or EQUAL_P;
-        if it is malformed then one of e1 to e5 results.
-
-        Note that this routine is not symmetrical and that the relation
-        is not trichotomous.
-
-        If a and b are equal (and aren't brackets), then
-
-            a LOWER_P a     if a right-associative
-            a GREATER_P a   if a left-associative
-    */
-
-    int i, j, l1, l2;
-
-    switch(a.type)
-    {   case SUBOPEN_TT:  i=0; break;
-        case SUBCLOSE_TT: i=1; break;
-        case ENDEXP_TT:   i=2; break;
-        case OP_TT:       i=3; break;
-        default:          i=4; break;
-    }
-    switch(b.type)
-    {   case SUBOPEN_TT:  i+=0; break;
-        case SUBCLOSE_TT: i+=5; break;
-        case ENDEXP_TT:   i+=10; break;
-        case OP_TT:       i+=15; break;
-        default:          i+=20; break;
-    }
-
-    j = prec_table[i]; if (j != -1) return j;
-
-    l1 = operators[a.value].precedence;
-    l2 = operators[b.value].precedence;
-    if (operators[b.value].usage == PRE_U) return LOWER_P;
-    if (operators[a.value].usage == POST_U) return GREATER_P;
-
-    /*  Anomalous rule to resolve the function call precedence, which is
-        different on the right from on the left, e.g., in:
-
-                 alpha.beta(gamma)
-                 beta(gamma).alpha
-    */
-
-    if ((l1 == 11) && (l2 > 11)) return GREATER_P;
-
-    if (l1 < l2)  return LOWER_P;
-    if (l1 > l2)  return GREATER_P;
-    switch(operators[a.value].associativity)
-    {   case L_A: return GREATER_P;
-        case R_A: return LOWER_P;
-        case 0:   return e5;
-    }
-    return GREATER_P;
-}
-
-/* --- Converting token to operand ----------------------------------------- */
-
-/* Must match the switch statement below */
-int z_system_constant_list[] =
-    { adjectives_table_SC,
-      actions_table_SC,
-      classes_table_SC,
-      identifiers_table_SC,
-      preactions_table_SC,
-      largest_object_SC,
-      strings_offset_SC,
-      code_offset_SC,
-      actual_largest_object_SC,
-      static_memory_offset_SC,
-      array_names_offset_SC,
-      readable_memory_offset_SC,
-      cpv__start_SC,
-      cpv__end_SC,
-      ipv__start_SC,
-      ipv__end_SC,
-      array__start_SC,
-      array__end_SC,
-      highest_attribute_number_SC,
-      attribute_names_array_SC,
-      highest_property_number_SC,
-      property_names_array_SC,
-      highest_action_number_SC,
-      action_names_array_SC,
-      highest_fake_action_number_SC,
-      fake_action_names_array_SC,
-      highest_routine_number_SC,
-      routine_names_array_SC,
-      routines_array_SC,
-      routine_flags_array_SC,
-      highest_global_number_SC,
-      global_names_array_SC,
-      globals_array_SC,
-      global_flags_array_SC,
-      highest_array_number_SC,
-      array_names_array_SC,
-      array_flags_array_SC,
-      highest_constant_number_SC,
-      constant_names_array_SC,
-      highest_class_number_SC,
-      class_objects_array_SC,
-      highest_object_number_SC,
-      -1 };
-
-static int32 value_of_system_constant_z(int t)
-{   switch(t)
-    {   case adjectives_table_SC:
-            return adjectives_offset;
-        case actions_table_SC:
-            return actions_offset;
-        case classes_table_SC:
-            return class_numbers_offset;
-        case identifiers_table_SC:
-            return identifier_names_offset;
-        case preactions_table_SC:
-            return preactions_offset;
-        case largest_object_SC:
-            return 256 + no_objects - 1;
-        case strings_offset_SC:
-            return strings_offset/scale_factor;
-        case code_offset_SC:
-            return code_offset/scale_factor;
-        case actual_largest_object_SC:
-            return no_objects;
-        case static_memory_offset_SC:
-            return static_memory_offset;
-        case array_names_offset_SC:
-            return array_names_offset;
-        case readable_memory_offset_SC:
-            return Write_Code_At;
-        case cpv__start_SC:
-            return prop_values_offset;
-        case cpv__end_SC:
-            return class_numbers_offset;
-        case ipv__start_SC:
-            return individuals_offset;
-        case ipv__end_SC:
-            return variables_offset;
-        case array__start_SC:
-            return variables_offset + (MAX_GLOBAL_VARIABLES*WORDSIZE);
-        case array__end_SC:
-            return static_memory_offset;
-
-        case highest_attribute_number_SC:
-            return no_attributes-1;
-        case attribute_names_array_SC:
-            return attribute_names_offset;
-
-        case highest_property_number_SC:
-            return no_individual_properties-1;
-        case property_names_array_SC:
-            return identifier_names_offset + 2;
-
-        case highest_action_number_SC:
-            return no_actions-1;
-        case action_names_array_SC:
-            return action_names_offset;
-
-        case highest_fake_action_number_SC:
-            return ((grammar_version_number==1)?256:4096) + no_fake_actions-1;
-        case fake_action_names_array_SC:
-            return fake_action_names_offset;
-
-        case highest_routine_number_SC:
-            return no_named_routines-1;
-        case routine_names_array_SC:
-            return routine_names_offset;
-        case routines_array_SC:
-            return routines_array_offset;
-        case routine_flags_array_SC:
-            return routine_flags_array_offset;
-        case highest_global_number_SC:
-            return 16 + no_globals-1;
-        case global_names_array_SC:
-            return global_names_offset;
-        case globals_array_SC:
-            return variables_offset;
-        case global_flags_array_SC:
-            return global_flags_array_offset;
-        case highest_array_number_SC:
-            return no_arrays-1;
-        case array_names_array_SC:
-            return array_names_offset;
-        case array_flags_array_SC:
-            return array_flags_array_offset;
-        case highest_constant_number_SC:
-            return no_named_constants-1;
-        case constant_names_array_SC:
-            return constant_names_offset;
-        case highest_class_number_SC:
-            return no_classes-1;
-        case class_objects_array_SC:
-            return class_numbers_offset;
-        case highest_object_number_SC:
-            return no_objects-1;
-    }
-
-    error_named("System constant not implemented in Z-code",
-        system_constants.keywords[t]);
-
-    return(0);
-}
-
-/* Must match the switch statement below */
-int glulx_system_constant_list[] =
-    { classes_table_SC,
-      identifiers_table_SC,
-      array_names_offset_SC,
-      cpv__start_SC,
-      cpv__end_SC,
-      dictionary_table_SC,
-      dynam_string_table_SC,
-      grammar_table_SC,
-      actions_table_SC,
-      globals_array_SC,
-      highest_class_number_SC,
-      highest_object_number_SC,
-      -1 };
-
-static int32 value_of_system_constant_g(int t)
-{ 
-  switch (t) {
-  case classes_table_SC:
-    return Write_RAM_At + class_numbers_offset;
-  case identifiers_table_SC:
-    return Write_RAM_At + identifier_names_offset;
-  case array_names_offset_SC:
-    return Write_RAM_At + array_names_offset;
-  case cpv__start_SC:
-    return prop_defaults_offset;
-  case cpv__end_SC:
-    return Write_RAM_At + class_numbers_offset;
-  case dictionary_table_SC:
-    return dictionary_offset;
-  case dynam_string_table_SC:
-    return abbreviations_offset;
-  case grammar_table_SC:
-    return grammar_table_offset;
-  case actions_table_SC:
-    return actions_offset;
-  case globals_array_SC:
-    return variables_offset;
-  case highest_class_number_SC:
-    return no_classes-1;
-  case highest_object_number_SC:
-    return no_objects-1;
-  }
-
-  error_named("System constant not implemented in Glulx",
-    system_constants.keywords[t]);
-
-  return 0;
-}
-
-extern int32 value_of_system_constant(int t)
-{
-  if (!glulx_mode)
-    return value_of_system_constant_z(t);
-  else
-    return value_of_system_constant_g(t);    
-}
-
-static int evaluate_term(token_data t, assembly_operand *o)
-{
-    /*  If the given token is a constant, evaluate it into the operand.
-        For now, the identifiers are considered variables.
-
-        Returns FALSE if it fails to understand type. */
-
-    int32 v;
-
-    o->marker = t.marker;
-    o->symtype = t.symtype;
-    o->symflags = t.symflags;
-
-    switch(t.type)
-    {   case LARGE_NUMBER_TT:
-             v = t.value;
-             if (!glulx_mode) {
-                 if (v < 0) v = v + 0x10000;
-                 o->type = LONG_CONSTANT_OT;
-                 o->value = v;
-             }
-             else {
-                 o->value = v;
-                 o->type = CONSTANT_OT;
-             }
-             return(TRUE);
-        case SMALL_NUMBER_TT:
-             v = t.value;
-             if (!glulx_mode) {
-                 if (v < 0) v = v + 0x10000;
-                 o->type = SHORT_CONSTANT_OT;
-                 o->value = v;
-             }
-             else {
-                 o->value = v;
-                 set_constant_ot(o);
-             }
-             return(TRUE);
-        case DICTWORD_TT:
-             /*  Find the dictionary address, adding to dictionary if absent */
-             if (!glulx_mode) 
-                 o->type = LONG_CONSTANT_OT;
-             else
-                 o->type = CONSTANT_OT;
-             o->value = dictionary_add(t.text, 0x80, 0, 0);
-             return(TRUE);
-        case DQ_TT:
-             /*  Create as a static string  */
-             if (!glulx_mode) 
-                 o->type = LONG_CONSTANT_OT;
-             else
-                 o->type = CONSTANT_OT;
-             o->value = compile_string(t.text, FALSE, FALSE);
-             return(TRUE);
-        case VARIABLE_TT:
-             if (!glulx_mode) {
-                 o->type = VARIABLE_OT;
-             }
-             else {
-                 if (t.value >= MAX_LOCAL_VARIABLES) {
-                     o->type = GLOBALVAR_OT;
-                 }
-                 else {
-                     /* This includes "local variable zero", which is really
-                        the stack-pointer magic variable. */
-                     o->type = LOCALVAR_OT;
-                 }
-             }
-             o->value = t.value;
-             return(TRUE);
-        case SYSFUN_TT:
-             if (!glulx_mode) {
-                 o->type = VARIABLE_OT;
-                 o->value = t.value + 256;
-             }
-             else {
-                 o->type = SYSFUN_OT;
-                 o->value = t.value;
-             }
-             system_function_usage[t.value] = 1;
-             return(TRUE);
-        case ACTION_TT:
-             *o = action_of_name(t.text);
-             return(TRUE);
-        case SYSTEM_CONSTANT_TT:
-             /*  Certain system constants depend only on the
-                 version number and need no backpatching, as they
-                 are known in advance.  We can therefore evaluate
-                 them immediately.  */
-             if (!glulx_mode) {
-                 o->type = LONG_CONSTANT_OT;
-                 switch(t.value)
-                 {   
-                 case version_number_SC:
-                     o->type = SHORT_CONSTANT_OT;
-                     o->marker = 0;
-                     v = version_number; break;
-                 case dict_par1_SC:
-                     o->type = SHORT_CONSTANT_OT;
-                     o->marker = 0;
-                     v = (version_number==3)?4:6; break;
-                 case dict_par2_SC:
-                     o->type = SHORT_CONSTANT_OT;
-                     o->marker = 0;
-                     v = (version_number==3)?5:7; break;
-                 case dict_par3_SC:
-                     o->type = SHORT_CONSTANT_OT;
-                     o->marker = 0;
-                     v = (version_number==3)?6:8; break;
-                 case lowest_attribute_number_SC:
-                 case lowest_action_number_SC:
-                 case lowest_routine_number_SC:
-                 case lowest_array_number_SC:
-                 case lowest_constant_number_SC:
-                 case lowest_class_number_SC:
-                     o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 0; break;
-                 case lowest_object_number_SC:
-                 case lowest_property_number_SC:
-                     o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 1; break;
-                 case lowest_global_number_SC:
-                     o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 16; break;
-                 case lowest_fake_action_number_SC:
-                     o->type = LONG_CONSTANT_OT; o->marker = 0;
-                     v = ((grammar_version_number==1)?256:4096); break;
-                 case oddeven_packing_SC:
-                     o->type = SHORT_CONSTANT_OT; o->marker = 0;
-                     v = oddeven_packing_switch; break;
-                 default:
-                     v = t.value;
-                     o->marker = INCON_MV;
-                     break;
-                 }
-                 o->value = v;
-             }
-             else {
-                 o->type = CONSTANT_OT;
-                 switch(t.value)
-                 {
-                 /* The three dict_par flags point at the lower byte
-                    of the flag field, because the library is written
-                    to expect one-byte fields, even though the compiler
-                    generates a dictionary with room for two. */
-                 case dict_par1_SC:
-                     o->type = BYTECONSTANT_OT;
-                     o->marker = 0;
-                     v = DICT_ENTRY_FLAG_POS+1;
-                     break;
-                 case dict_par2_SC:
-                     o->type = BYTECONSTANT_OT;
-                     o->marker = 0;
-                     v = DICT_ENTRY_FLAG_POS+3;
-                     break;
-                 case dict_par3_SC:
-                     o->type = BYTECONSTANT_OT;
-                     o->marker = 0;
-                     v = DICT_ENTRY_FLAG_POS+5;
-                     break;
-
-                 case lowest_attribute_number_SC:
-                 case lowest_action_number_SC:
-                 case lowest_routine_number_SC:
-                 case lowest_array_number_SC:
-                 case lowest_constant_number_SC:
-                 case lowest_class_number_SC:
-                     o->type = BYTECONSTANT_OT;
-                     o->marker = 0;
-                     v = 0;
-                     break;
-                 case lowest_object_number_SC:
-                 case lowest_property_number_SC:
-                     o->type = BYTECONSTANT_OT;
-                     o->marker = 0;
-                     v = 1;
-                     break;
-                 /* ###fix: need to fill more of these in! */
-
-                 default:
-                     v = t.value;
-                     o->marker = INCON_MV;
-                     break;
-                 }
-                 o->value = v;
-             }
-             return(TRUE);
-        default:
-             return(FALSE);
-    }
-}
-
-/* --- Emitter ------------------------------------------------------------- */
-
-expression_tree_node *ET;
-static int ET_used;
-
-extern void clear_expression_space(void)
-{   ET_used = 0;
-}
-
-static assembly_operand *emitter_stack;
-static int *emitter_markers;
-static int *emitter_bracket_counts;
-
-#define FUNCTION_VALUE_MARKER 1
-#define ARGUMENT_VALUE_MARKER 2
-#define OR_VALUE_MARKER 3
-
-static int emitter_sp;
-
-static int is_property_t(int symbol_type)
-{   return ((symbol_type == PROPERTY_T) || (symbol_type == INDIVIDUAL_PROPERTY_T));
-}
-
-static void mark_top_of_emitter_stack(int marker, token_data t)
-{   if (emitter_sp < 1)
-    {   compiler_error("SR error: Attempt to add a marker to the top of an empty emitter stack");
-        return;
-    }
-    if (expr_trace_level >= 2)
-    {   printf("Marking top of emitter stack (which is ");
-        print_operand(emitter_stack[emitter_sp-1]);
-        printf(") as ");
-        switch(marker)
-        {
-            case FUNCTION_VALUE_MARKER:
-                printf("FUNCTION");
-                break;
-            case ARGUMENT_VALUE_MARKER:
-                printf("ARGUMENT");
-                break;
-            case OR_VALUE_MARKER:
-                printf("OR_VALUE");
-                break;
-            default:
-                printf("UNKNOWN");
-                break;
-        }
-        printf("\n");
-    }
-    if (emitter_markers[emitter_sp-1])
-    {   if (marker == ARGUMENT_VALUE_MARKER)
-        {
-            warning("Ignoring spurious leading comma");
-            return;
-        }
-        error_named("Missing operand for", t.text);
-        if (emitter_sp == MAX_EXPRESSION_NODES)
-            memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-        emitter_markers[emitter_sp] = 0;
-        emitter_bracket_counts[emitter_sp] = 0;
-        emitter_stack[emitter_sp] = zero_operand;
-        emitter_sp++;
-    }
-    emitter_markers[emitter_sp-1] = marker;
-}
-
-static void add_bracket_layer_to_emitter_stack(int depth)
-{   /* There's no point in tracking bracket layers that don't fence off any values. */
-    if (emitter_sp < depth + 1) return;
-    if (expr_trace_level >= 2)
-        printf("Adding bracket layer\n");
-    ++emitter_bracket_counts[emitter_sp-depth-1];
-}
-
-static void remove_bracket_layer_from_emitter_stack()
-{   /* Bracket layers that don't fence off any values will not have been tracked. */
-    if (emitter_sp < 2) return;
-    if (expr_trace_level >= 2)
-        printf("Removing bracket layer\n");
-    if (emitter_bracket_counts[emitter_sp-2] <= 0)
-    {   compiler_error("SR error: Attempt to remove a nonexistent bracket layer from the emitter stack");
-        return;
-    }
-    --emitter_bracket_counts[emitter_sp-2];
-}
-
-static void emit_token(token_data t)
-{   assembly_operand o1, o2; int arity, stack_size, i;
-    int op_node_number, operand_node_number, previous_node_number;
-    int32 x = 0;
-
-    if (expr_trace_level >= 2)
-    {   printf("Output: %-19s%21s ", t.text, "");
-        for (i=0; i<emitter_sp; i++)
-        {   print_operand(emitter_stack[i]); printf(" ");
-            if (emitter_markers[i] == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
-            if (emitter_markers[i] == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
-            if (emitter_markers[i] == OR_VALUE_MARKER) printf(":OR ");
-            if (emitter_bracket_counts[i]) printf(":BRACKETS(%d) ", emitter_bracket_counts[i]);
-        }
-        printf("\n");
-    }
-
-    if (t.type == SUBOPEN_TT) return;
-
-    stack_size = 0;
-    while ((stack_size < emitter_sp) &&
-           !emitter_markers[emitter_sp-stack_size-1] &&
-           !emitter_bracket_counts[emitter_sp-stack_size-1])
-        stack_size++;
-
-    if (t.type == SUBCLOSE_TT)
-    {   if (stack_size < emitter_sp && emitter_bracket_counts[emitter_sp-stack_size-1])
-        {   if (stack_size == 0)
-            {   error("No expression between brackets '(' and ')'");
-                emitter_stack[emitter_sp] = zero_operand;
-                emitter_markers[emitter_sp] = 0;
-                emitter_bracket_counts[emitter_sp] = 0;
-                ++emitter_sp;
-            }
-            else if (stack_size < 1)
-                compiler_error("SR error: emitter stack empty in subexpression");
-            else if (stack_size > 1)
-                compiler_error("SR error: emitter stack overfull in subexpression");
-            remove_bracket_layer_from_emitter_stack();
-        }
-        return;
-    }
-
-    if (t.type != OP_TT)
-    {   emitter_markers[emitter_sp] = 0;
-        emitter_bracket_counts[emitter_sp] = 0;
-
-        if (emitter_sp == MAX_EXPRESSION_NODES)
-            memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-        if (!evaluate_term(t, &(emitter_stack[emitter_sp++])))
-            compiler_error_named("Emit token error:", t.text);
-        return;
-    }
-
-    /* A comma is argument-separating if it follows an argument (or a function
-       call, since we ignore spurious leading commas in function argument lists)
-       with no intervening brackets.  Function calls are variadic, so we don't
-       apply argument-separating commas. */
-    if (t.value == COMMA_OP &&
-        stack_size < emitter_sp &&
-        (emitter_markers[emitter_sp-stack_size-1] == ARGUMENT_VALUE_MARKER ||
-         emitter_markers[emitter_sp-stack_size-1] == FUNCTION_VALUE_MARKER) &&
-        !emitter_bracket_counts[emitter_sp-stack_size-1])
-    {   if (expr_trace_level >= 2)
-            printf("Treating comma as argument-separating\n");
-        return;
-    }
-
-    if (t.value == OR_OP)
-        return;
-
-    arity = 1;
-    if (t.value == FCALL_OP)
-    {   if (expr_trace_level >= 3)
-        {   printf("FCALL_OP finds marker stack: ");
-            for (x=0; x<emitter_sp; x++) printf("%d ", emitter_markers[x]);
-            printf("\n");
-        }
-        if (emitter_markers[emitter_sp-1] == ARGUMENT_VALUE_MARKER)
-            warning("Ignoring spurious trailing comma");
-        while (emitter_markers[emitter_sp-arity] != FUNCTION_VALUE_MARKER)
-        {
-            if ((glulx_mode &&
-                 emitter_stack[emitter_sp-arity].type == SYSFUN_OT) ||
-                (!glulx_mode &&
-                 emitter_stack[emitter_sp-arity].type == VARIABLE_OT &&
-                 emitter_stack[emitter_sp-arity].value >= 256 &&
-                 emitter_stack[emitter_sp-arity].value < 288))
-            {   int index = emitter_stack[emitter_sp-arity].value;
-                if(!glulx_mode)
-                    index -= 256;
-                if(index >= 0 && index < NUMBER_SYSTEM_FUNCTIONS)
-                    error_named("System function name used as a value:", system_functions.keywords[index]);
-                else
-                    compiler_error("Found unnamed system function used as a value");
-                emitter_stack[emitter_sp-arity] = zero_operand;
-            }
-            ++arity;
-        }
-    }
-    else
-    {   arity = 1;
-        if (operators[t.value].usage == IN_U) arity = 2;
-
-        if (operators[t.value].precedence == 3)
-        {   arity = 2;
-            x = emitter_sp-1;
-            if(!emitter_markers[x] && !emitter_bracket_counts[x])
-            {   for (--x; emitter_markers[x] == OR_VALUE_MARKER && !emitter_bracket_counts[x]; --x)
-                {   ++arity;
-                    ++stack_size;
-                }
-                for (;x >= 0 && !emitter_markers[x] && !emitter_bracket_counts[x]; --x)
-                    ++stack_size;
-            }
-        }
-
-        if (arity > stack_size)
-        {   error_named("Missing operand for", t.text);
-            while (arity > stack_size)
-            {   if (emitter_sp == MAX_EXPRESSION_NODES)
-                    memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-                emitter_markers[emitter_sp] = 0;
-                emitter_bracket_counts[emitter_sp] = 0;
-                emitter_stack[emitter_sp] = zero_operand;
-                emitter_sp++;
-                stack_size++;
-            }
-        }
-    }
-
-    /* pseudo-typecheck in 6.30 */
-    for (i = 1; i <= arity; i++)
-    {
-        o1 = emitter_stack[emitter_sp - i];
-        if (is_property_t(o1.symtype) ) {
-            switch(t.value) 
-            {
-                case FCALL_OP:
-                case SETEQUALS_OP: case NOTEQUAL_OP: 
-                case CONDEQUALS_OP: 
-                case PROVIDES_OP: case NOTPROVIDES_OP:
-                case PROP_ADD_OP: case PROP_NUM_OP:
-                case SUPERCLASS_OP:
-                case MPROP_ADD_OP: case MESSAGE_OP:
-                case PROPERTY_OP:
-                    if (i < arity) break;
-                case GE_OP: case LE_OP:
-                    if ((i < arity) && (o1.symflags & STAR_SFLAG)) break;
-                default:
-                    warning("Property name in expression is not qualified by object");
-            }
-        } /* if (is_property_t */
-    }
-
-    switch(arity)
-    {   case 1:
-            o1 = emitter_stack[emitter_sp - 1];
-            if ((o1.marker == 0) && is_constant_ot(o1.type))
-            {   switch(t.value)
-                {   case UNARY_MINUS_OP: x = -o1.value; goto FoldConstant;
-                    case ARTNOT_OP: 
-                         if (!glulx_mode)
-                             x = (~o1.value) & 0xffff;
-                         else
-                             x = (~o1.value) & 0xffffffff;
-                         goto FoldConstant;
-                    case LOGNOT_OP:
-                        if (o1.value != 0) x=0; else x=1;
-                        goto FoldConstant;
-                }
-            }
-            break;
-
-        case 2:
-            o1 = emitter_stack[emitter_sp - 2];
-            o2 = emitter_stack[emitter_sp - 1];
-
-            if ((o1.marker == 0) && (o2.marker == 0)
-                && is_constant_ot(o1.type) && is_constant_ot(o2.type))
-            {
-                int32 ov1, ov2;
-                if (glulx_mode)
-                { ov1 = o1.value;
-                  ov2 = o2.value;
-                }
-                else
-                { ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value;
-                  ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
-                }
-
-                switch(t.value)
-                {
-                    case PLUS_OP: x = ov1 + ov2; goto FoldConstantC;
-                    case MINUS_OP: x = ov1 - ov2; goto FoldConstantC;
-                    case TIMES_OP: x = ov1 * ov2; goto FoldConstantC;
-                    case DIVIDE_OP:
-                    case REMAINDER_OP:
-                        if (ov2 == 0)
-                          error("Division of constant by zero");
-                        else
-                        if (t.value == DIVIDE_OP) {
-                          if (ov2 < 0) {
-                            ov1 = -ov1;
-                            ov2 = -ov2;
-                          }
-                          if (ov1 >= 0) 
-                            x = ov1 / ov2;
-                          else
-                            x = -((-ov1) / ov2);
-                        }
-                        else {
-                          if (ov2 < 0) {
-                            ov2 = -ov2;
-                          }
-                          if (ov1 >= 0) 
-                            x = ov1 % ov2;
-                          else
-                            x = -((-ov1) % ov2);
-                        }
-                        goto FoldConstant;
-                    case ARTAND_OP: x = o1.value & o2.value; goto FoldConstant;
-                    case ARTOR_OP: x = o1.value | o2.value; goto FoldConstant;
-                    case CONDEQUALS_OP:
-                        if (o1.value == o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case NOTEQUAL_OP:
-                        if (o1.value != o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case GE_OP:
-                        if (o1.value >= o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case GREATER_OP:
-                        if (o1.value > o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case LE_OP:
-                        if (o1.value <= o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case LESS_OP:
-                        if (o1.value < o2.value) x = 1; else x = 0;
-                        goto FoldConstant;
-                    case LOGAND_OP:
-                        if ((o1.value != 0) && (o2.value != 0)) x=1; else x=0;
-                        goto FoldConstant;
-                    case LOGOR_OP:
-                        if ((o1.value != 0) || (o2.value != 0)) x=1; else x=0;
-                        goto FoldConstant;
-                }
-
-            }
-    }
-
-    op_node_number = ET_used++;
-    if (op_node_number == MAX_EXPRESSION_NODES)
-        memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-
-    ET[op_node_number].operator_number = t.value;
-    ET[op_node_number].up = -1;
-    ET[op_node_number].down = -1;
-    ET[op_node_number].right = -1;
-
-    /*  This statement is redundant, but prevents compilers from wrongly
-        issuing a "used before it was assigned a value" error:  */
-    previous_node_number = 0;
-
-    for (i = emitter_sp-arity; i != emitter_sp; i++)
-    {
-        if (expr_trace_level >= 3)
-            printf("i=%d, emitter_sp=%d, arity=%d, ETU=%d\n",
-                i, emitter_sp, arity, ET_used);
-        if (emitter_stack[i].type == EXPRESSION_OT)
-            operand_node_number = emitter_stack[i].value;
-        else
-        {   operand_node_number = ET_used++;
-            if (operand_node_number == MAX_EXPRESSION_NODES)
-                memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-            ET[operand_node_number].down = -1;
-            ET[operand_node_number].value = emitter_stack[i];
-        }
-        ET[operand_node_number].up = op_node_number;
-        ET[operand_node_number].right = -1;
-        if (i == emitter_sp - arity)
-        {   ET[op_node_number].down = operand_node_number;
-        }
-        else
-        {   ET[previous_node_number].right = operand_node_number;
-        }
-        previous_node_number = operand_node_number;
-    }
-
-    emitter_sp = emitter_sp - arity + 1;
-
-    emitter_stack[emitter_sp - 1].type = EXPRESSION_OT;
-    emitter_stack[emitter_sp - 1].value = op_node_number;
-    emitter_stack[emitter_sp - 1].marker = 0;
-    emitter_markers[emitter_sp - 1] = 0;
-    emitter_bracket_counts[emitter_sp - 1] = 0;
-    /* Remove the marker for the brackets implied by operator precedence */
-    remove_bracket_layer_from_emitter_stack();
-
-    return;
-
-    FoldConstantC:
-
-    /* In Glulx, skip this test; we can't check out-of-range errors 
-       for 32-bit arithmetic. */
-
-    if (!glulx_mode && ((x<-32768) || (x > 32767)))
-    {   char folding_error[40];
-        int32 ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value;
-        int32 ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
-        switch(t.value)
-        {
-            case PLUS_OP:
-                sprintf(folding_error, "%d + %d = %d", ov1, ov2, x);
-                break;
-            case MINUS_OP:
-                sprintf(folding_error, "%d - %d = %d", ov1, ov2, x);
-                break;
-            case TIMES_OP:
-                sprintf(folding_error, "%d * %d = %d", ov1, ov2, x);
-                break;
-        }
-        error_named("Signed arithmetic on compile-time constants overflowed \
-the range -32768 to +32767:", folding_error);
-    }
-
-    FoldConstant:
-
-    if (!glulx_mode) {
-        while (x < 0) x = x + 0x10000;
-        x = x & 0xffff;
-    }
-    else {
-        x = x & 0xffffffff;
-    }
-
-    emitter_sp = emitter_sp - arity + 1;
-
-    if (!glulx_mode) {
-        if (x<256)
-            emitter_stack[emitter_sp - 1].type = SHORT_CONSTANT_OT;
-        else emitter_stack[emitter_sp - 1].type = LONG_CONSTANT_OT;
-    }
-    else {
-        if (x == 0)
-            emitter_stack[emitter_sp - 1].type = ZEROCONSTANT_OT;
-        else if (x >= -128 && x <= 127) 
-            emitter_stack[emitter_sp - 1].type = BYTECONSTANT_OT;
-        else if (x >= -32768 && x <= 32767) 
-            emitter_stack[emitter_sp - 1].type = HALFCONSTANT_OT;
-        else
-            emitter_stack[emitter_sp - 1].type = CONSTANT_OT;
-    }
-
-    emitter_stack[emitter_sp - 1].value = x;
-    emitter_stack[emitter_sp - 1].marker = 0;
-    emitter_markers[emitter_sp - 1] = 0;
-    emitter_bracket_counts[emitter_sp - 1] = 0;
-
-    if (expr_trace_level >= 2)
-    {   printf("Folding constant to: ");
-        print_operand(emitter_stack[emitter_sp - 1]);
-        printf("\n");
-    }
-
-    /* Remove the marker for the brackets implied by operator precedence */
-    remove_bracket_layer_from_emitter_stack();
-    return;
-}
-
-/* --- Pretty printing ----------------------------------------------------- */
-
-static void show_node(int n, int depth, int annotate)
-{   int j;
-    for (j=0; j<2*depth+2; j++) printf(" ");
-
-    if (ET[n].down == -1)
-    {   print_operand(ET[n].value);
-        if (annotate && (ET[n].value.marker != 0))
-            printf(" [%s]", describe_mv(ET[n].value.marker));
-        printf("\n");
-    }
-    else
-    {   printf("%s ", operators[ET[n].operator_number].description);
-        j = operators[ET[n].operator_number].precedence;
-        if ((annotate) && ((j==2) || (j==3)))
-        {   printf(" %d|%d ", ET[n].true_label, ET[n].false_label);
-            if (ET[n].label_after != -1) printf(" def %d after ",
-                ET[n].label_after);
-            if (ET[n].to_expression) printf(" con to expr ");
-        }
-        printf("\n");
-        show_node(ET[n].down, depth+1, annotate);
-    }
-
-    if (ET[n].right != -1) show_node(ET[n].right, depth, annotate);
-}
-
-extern void show_tree(assembly_operand AO, int annotate)
-{   if (AO.type == EXPRESSION_OT) show_node(AO.value, 0, annotate);
-    else
-    {   printf("Constant: "); print_operand(AO);
-        if (annotate && (AO.marker != 0))
-            printf(" [%s]", describe_mv(AO.marker));
-        printf("\n");
-    }
-}
-
-/* --- Lvalue transformations ---------------------------------------------- */
-
-/* This only gets called in Z-code, since Glulx doesn't distinguish
-   individual property operators from general ones. */
-static void check_property_operator(int from_node)
-{   int below = ET[from_node].down;
-    int opnum = ET[from_node].operator_number;
-
-    ASSERT_ZCODE();
-
-    if (veneer_mode) return;
-
-    if ((below != -1) && (ET[below].right != -1))
-    {   int n = ET[below].right, flag = FALSE;
-
-        if ((ET[n].down == -1)
-                && ((ET[n].value.type == LONG_CONSTANT_OT)
-                    || (ET[n].value.type == SHORT_CONSTANT_OT))
-                && ((ET[n].value.value > 0) && (ET[n].value.value < 64))
-                && ((!module_switch) || (ET[n].value.marker == 0)))
-            flag = TRUE;
-
-        if (!flag)
-        {   switch(opnum)
-            {   case PROPERTY_OP: opnum = MESSAGE_OP; break;
-                case PROP_ADD_OP: opnum = MPROP_ADD_OP; break;
-                case PROP_NUM_OP: opnum = MPROP_NUM_OP; break;
-            }
-        }
-
-        ET[from_node].operator_number = opnum;
-    }
-
-    if (below != -1)
-        check_property_operator(below);
-    if (ET[from_node].right != -1)
-        check_property_operator(ET[from_node].right);
-}
-
-static void check_lvalues(int from_node)
-{   int below = ET[from_node].down;
-    int opnum = ET[from_node].operator_number, opnum_below;
-    int lvalue_form, i, j = 0;
-
-    if (below != -1)
-    {
-        if ((opnum == FCALL_OP) && (ET[below].down != -1))
-        {   opnum_below = ET[below].operator_number;
-            if ((opnum_below == PROPERTY_OP) || (opnum_below == MESSAGE_OP))
-            {   i = ET[ET[from_node].down].right;
-                ET[from_node].down = ET[below].down;
-                ET[ET[below].down].up = from_node;
-                ET[ET[ET[below].down].right].up = from_node;
-                ET[ET[ET[below].down].right].right = i;
-                opnum = PROP_CALL_OP;
-                ET[from_node].operator_number = opnum;
-            }
-        }
-
-        if (operators[opnum].requires_lvalue)
-        {   opnum_below = ET[below].operator_number;
-
-            if (ET[below].down == -1)
-            {   if (!is_variable_ot(ET[below].value.type))
-                {   error("'=' applied to undeclared variable");
-                    goto LvalueError;
-                }
-            }
-            else
-            { lvalue_form=0;
-              switch(opnum)
-              { case SETEQUALS_OP:
-                switch(opnum_below)
-                { case ARROW_OP:    lvalue_form = ARROW_SETEQUALS_OP; break;
-                  case DARROW_OP:   lvalue_form = DARROW_SETEQUALS_OP; break;
-                  case MESSAGE_OP:  lvalue_form = MESSAGE_SETEQUALS_OP; break;
-                  case PROPERTY_OP: lvalue_form = PROPERTY_SETEQUALS_OP; break;
-                }
-                break;
-                case INC_OP:
-                switch(opnum_below)
-                { case ARROW_OP:    lvalue_form = ARROW_INC_OP; break;
-                  case DARROW_OP:   lvalue_form = DARROW_INC_OP; break;
-                  case MESSAGE_OP:  lvalue_form = MESSAGE_INC_OP; break;
-                  case PROPERTY_OP: lvalue_form = PROPERTY_INC_OP; break;
-                }
-                break;
-                case POST_INC_OP:
-                switch(opnum_below)
-                { case ARROW_OP:    lvalue_form = ARROW_POST_INC_OP; break;
-                  case DARROW_OP:   lvalue_form = DARROW_POST_INC_OP; break;
-                  case MESSAGE_OP:  lvalue_form = MESSAGE_POST_INC_OP; break;
-                  case PROPERTY_OP: lvalue_form = PROPERTY_POST_INC_OP; break;
-                }
-                break;
-                case DEC_OP:
-                switch(opnum_below)
-                { case ARROW_OP:    lvalue_form = ARROW_DEC_OP; break;
-                  case DARROW_OP:   lvalue_form = DARROW_DEC_OP; break;
-                  case MESSAGE_OP:  lvalue_form = MESSAGE_DEC_OP; break;
-                  case PROPERTY_OP: lvalue_form = PROPERTY_DEC_OP; break;
-                }
-                break;
-                case POST_DEC_OP:
-                switch(opnum_below)
-                { case ARROW_OP:    lvalue_form = ARROW_POST_DEC_OP; break;
-                  case DARROW_OP:   lvalue_form = DARROW_POST_DEC_OP; break;
-                  case MESSAGE_OP:  lvalue_form = MESSAGE_POST_DEC_OP; break;
-                  case PROPERTY_OP: lvalue_form = PROPERTY_POST_DEC_OP; break;
-                }
-                break;
-              }
-              if (lvalue_form == 0)
-              {   error_named("'=' applied to",
-                      (char *) operators[opnum_below].description);
-                  goto LvalueError;
-              }
-
-              /*  Transform  from_node                     from_node
-                               |      \                       | \\\  \
-                             below    value       to                 value
-                               | \\\
-              */
-
-              ET[from_node].operator_number = lvalue_form;
-              i = ET[below].down;
-              ET[from_node].down = i;
-              while (i != -1)
-              {   ET[i].up = from_node;
-                  j = i;
-                  i = ET[i].right;
-              }
-              ET[j].right = ET[below].right;
-            }
-        }
-        check_lvalues(below);
-    }
-    if (ET[from_node].right != -1)
-        check_lvalues(ET[from_node].right);
-    return;
-
-    LvalueError:
-    ET[from_node].down = -1;
-    ET[from_node].value = zero_operand;
-    if (ET[from_node].right != -1)
-        check_lvalues(ET[from_node].right);
-}
-
-/* --- Tree surgery for conditionals --------------------------------------- */
-
-static void negate_condition(int n)
-{   int i;
-
-    if (ET[n].right != -1) negate_condition(ET[n].right);
-    if (ET[n].down == -1) return;
-    i = operators[ET[n].operator_number].negation;
-    if (i!=0) ET[n].operator_number = i;
-    if (operators[i].precedence==2) negate_condition(ET[n].down);
-}
-
-static void delete_negations(int n, int context)
-{
-    /*  Recursively apply
-
-            ~~(x && y)   =   ~~x || ~~y
-            ~~(x || y)   =   ~~x && ~~y
-            ~~(x == y)   =   x ~= y
-
-        (etc) to delete the ~~ operator from the tree.  Since this is
-        depth first, the ~~ being deleted has no ~~s beneath it, which
-        is important to make "negate_condition" work.                        */
-
-    int i;
-
-    if (ET[n].right != -1) delete_negations(ET[n].right, context);
-    if (ET[n].down == -1) return;
-    delete_negations(ET[n].down, context);
-
-    if (ET[n].operator_number == LOGNOT_OP)
-    {   negate_condition(ET[n].down);
-        ET[n].operator_number
-            = ET[ET[n].down].operator_number;
-        ET[n].down = ET[ET[n].down].down;
-        i = ET[n].down;
-        while(i != -1) { ET[i].up = n; i = ET[i].right; }
-    }
-}
-
-static void insert_exp_to_cond(int n, int context)
-{
-    /*  Insert a ~= test when an expression is used as a condition.
-
-        Check for possible confusion over = and ==, e.g. "if (a = 1) ..."    */
-
-    int new, i;
-
-    if (ET[n].right != -1) insert_exp_to_cond(ET[n].right, context);
-
-    if (ET[n].down == -1)
-    {   if (context==CONDITION_CONTEXT)
-        {   new = ET_used++;
-            if (new == MAX_EXPRESSION_NODES)
-                memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-            ET[new] = ET[n];
-            ET[n].down = new; ET[n].operator_number = NONZERO_OP;
-            ET[new].up = n; ET[new].right = -1;
-        }
-        return;
-    }
-
-    switch(operators[ET[n].operator_number].precedence)
-    {   case 3:                                 /* Conditionals have level 3 */
-            context = QUANTITY_CONTEXT;
-            break;
-        case 2:                                 /* Logical operators level 2 */
-            context = CONDITION_CONTEXT;
-            break;
-        case 1:                                 /* Forms of '=' have level 1 */
-            if (context == CONDITION_CONTEXT)
-                warning("'=' used as condition: '==' intended?");
-        default:
-            if (context != CONDITION_CONTEXT) break;
-
-            new = ET_used++;
-            if (new == MAX_EXPRESSION_NODES)
-                memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-            ET[new] = ET[n];
-            ET[n].down = new; ET[n].operator_number = NONZERO_OP;
-            ET[new].up = n; ET[new].right = -1;
-
-            i = ET[new].down;
-            while (i!= -1) { ET[i].up = new; i = ET[i].right; }
-            context = QUANTITY_CONTEXT; n = new;
-    }
-
-    insert_exp_to_cond(ET[n].down, context);
-}
-
-static unsigned int etoken_num_children(int n)
-{
-    int count = 0;
-    int i;
-    i = ET[n].down;
-    if (i == -1) { return 0; }
-    do {
-        count++;
-        i = ET[i].right;
-    } while (i!=-1);
-    return count;
-}
-
-static void func_args_on_stack(int n, int context)
-{
-  /* Make sure that the arguments of every function-call expression
-     are stored to the stack. If any aren't (ie, if any arguments are
-     constants or variables), cover them with push operators. 
-     (The very first argument does not need to be so treated, because
-     it's the function address, not a function argument. We also
-     skip the treatment for most system functions.) */
-
-  int new, pn, fnaddr, opnum;
-
-  ASSERT_GLULX();
-
-  if (ET[n].right != -1) 
-    func_args_on_stack(ET[n].right, context);
-  if (ET[n].down == -1) {
-    pn = ET[n].up;
-    if (pn != -1) {
-      opnum = ET[pn].operator_number;
-      if (opnum == FCALL_OP
-        || opnum == MESSAGE_CALL_OP
-        || opnum == PROP_CALL_OP) {
-        /* If it's an FCALL, get the operand which contains the function 
-           address (or system-function number) */
-        if (opnum == MESSAGE_CALL_OP 
-          || opnum == PROP_CALL_OP
-          || ((fnaddr=ET[pn].down) != n
-            && (ET[fnaddr].value.type != SYSFUN_OT
-              || ET[fnaddr].value.value == INDIRECT_SYSF
-              || ET[fnaddr].value.value == GLK_SYSF))) {
-        if (etoken_num_children(pn) > (unsigned int)(opnum == FCALL_OP ? 4:3)) {
-          new = ET_used++;
-          if (new == MAX_EXPRESSION_NODES)
-            memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-          ET[new] = ET[n];
-          ET[n].down = new; 
-          ET[n].operator_number = PUSH_OP;
-          ET[new].up = n; 
-          ET[new].right = -1;
-        }
-        }
-      }
-    }
-    return;
-  }
-
-  func_args_on_stack(ET[n].down, context);
-}
-
-static assembly_operand check_conditions(assembly_operand AO, int context)
-{   int n;
-
-    if (AO.type != EXPRESSION_OT)
-    {   if (context != CONDITION_CONTEXT) return AO;
-        n = ET_used++;
-        if (n == MAX_EXPRESSION_NODES)
-            memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-        ET[n].down = -1;
-        ET[n].up = -1;
-        ET[n].right = -1;
-        ET[n].value = AO;
-        INITAOT(&AO, EXPRESSION_OT);
-        AO.value = n;
-    }
-
-    insert_exp_to_cond(AO.value, context);
-    delete_negations(AO.value, context);
-
-    if (glulx_mode)
-        func_args_on_stack(AO.value, context);
-
-    return AO;
-}
-
-/* --- Shift-reduce parser ------------------------------------------------- */
-
-static int sr_sp;
-static token_data *sr_stack;
-
-extern assembly_operand parse_expression(int context)
-{
-    /*  Parses an expression, evaluating it as a constant if possible.
-
-        Possible contexts are:
-
-            VOID_CONTEXT        the expression is used as a statement, so that
-                                its value will be thrown away and it only
-                                needs to exist for any resulting side-effects
-                                (function calls and assignments)
-
-            CONDITION_CONTEXT   the result must be a condition
-
-            CONSTANT_CONTEXT    there is required to be a constant result
-                                (so that, for instance, comma becomes illegal)
-
-            QUANTITY_CONTEXT    the default: a quantity is to be specified
-
-            ACTION_Q_CONTEXT    like QUANTITY_CONTEXT, but postfixed brackets
-                                at the top level do not indicate function call:
-                                used for e.g.
-                                   <Insert button (random(pocket1, pocket2))>
-
-            RETURN_Q_CONTEXT    like QUANTITY_CONTEXT, but a single property
-                                name does not generate a warning
-
-            ASSEMBLY_CONTEXT    a quantity which cannot use the '->' operator
-                                (needed for assembly language to indicate
-                                store destinations)
-
-            FORINIT_CONTEXT     a quantity which cannot use an (unbracketed)
-                                '::' operator
-
-            ARRAY_CONTEXT       like CONSTANT_CONTEXT, but where an unbracketed
-                                minus sign is ambiguous, and brackets always
-                                indicate subexpressions, not function calls
-
-        Return value: an assembly operand.
-
-        If the type is OMITTED_OT, then the expression has no resulting value.
-
-        If the type is EXPRESSION_OT, then the value will need to be
-        calculated at run-time by code compiled from the expression tree
-        whose root node-number is the operand value.
-
-        Otherwise the assembly operand is the value of the expression, which
-        is constant and thus known at compile time.
-
-        If an error has occurred in the expression, which recovery from was
-        not possible, then the return is (short constant) 0.  This should
-        minimise the chance of a cascade of further error messages.
-    */
-
-    token_data a, b, pop; int i;
-    assembly_operand AO;
-
-    superclass_allowed = (context != FORINIT_CONTEXT);
-    if (context == FORINIT_CONTEXT) context = VOID_CONTEXT;
-
-    comma_allowed = (context == VOID_CONTEXT);
-    arrow_allowed = (context != ASSEMBLY_CONTEXT);
-    bare_prop_allowed = (context == RETURN_Q_CONTEXT);
-    array_init_ambiguity = ((context == ARRAY_CONTEXT) ||
-        (context == ASSEMBLY_CONTEXT));
-
-    action_ambiguity = (context == ACTION_Q_CONTEXT);
-
-    if (context == ASSEMBLY_CONTEXT) context = QUANTITY_CONTEXT;
-    if (context == ACTION_Q_CONTEXT) context = QUANTITY_CONTEXT;
-    if (context == RETURN_Q_CONTEXT) context = QUANTITY_CONTEXT;
-    if (context == ARRAY_CONTEXT) context = CONSTANT_CONTEXT;
-
-    etoken_count = 0;
-    inserting_token = FALSE;
-
-    emitter_sp = 0;
-    bracket_level = 0;
-
-    previous_token.text = "$";
-    previous_token.type = ENDEXP_TT;
-    previous_token.value = 0;
-
-    sr_sp = 1;
-    sr_stack[0] = previous_token;
-
-    AO = zero_operand;
-
-    statements.enabled = FALSE;
-    directives.enabled = FALSE;
-
-    if (get_next_etoken() == FALSE)
-    {   ebf_error("expression", token_text);
-        return AO;
-    }
-
-    do
-    {   if (expr_trace_level >= 2)
-        {   printf("Input: %-20s", current_token.text);
-            for (i=0; i<sr_sp; i++) printf("%s ", sr_stack[i].text);
-            printf("\n");
-        }
-        if (expr_trace_level >= 3) printf("ET_used = %d\n", ET_used);
-
-        if (sr_sp == 0)
-        {   compiler_error("SR error: stack empty");
-            return(AO);
-        }
-
-        a = sr_stack[sr_sp-1]; b = current_token;
-
-        if ((a.type == ENDEXP_TT) && (b.type == ENDEXP_TT))
-        {   if (emitter_sp == 0)
-            {   error("No expression between brackets '(' and ')'");
-                put_token_back();
-                return AO;
-            }
-            if (emitter_sp > 1)
-            {   compiler_error("SR error: emitter stack overfull");
-                return AO;
-            }
-
-            AO = emitter_stack[0];
-            if (AO.type == EXPRESSION_OT)
-            {   if (expr_trace_level >= 3)
-                {   printf("Tree before lvalue checking:\n");
-                    show_tree(AO, FALSE);
-                }
-                if (!glulx_mode)
-                    check_property_operator(AO.value);
-                check_lvalues(AO.value);
-                ET[AO.value].up = -1;
-            }
-            else {
-                if ((context != CONSTANT_CONTEXT) && is_property_t(AO.symtype) 
-                    && (arrow_allowed) && (!bare_prop_allowed))
-                    warning("Bare property name found. \"self.prop\" intended?");
-            }
-
-            check_conditions(AO, context);
-
-            if (context == CONSTANT_CONTEXT)
-                if (!is_constant_ot(AO.type))
-                {   AO = zero_operand;
-                    ebf_error("constant", "<expression>");
-                }
-            put_token_back();
-
-            return(AO);
-        }
-
-        switch(find_prec(a,b))
-        {
-            case e5:                 /* Associativity error                  */
-                error_named("Brackets mandatory to clarify order of:",
-                    a.text);
-
-            case LOWER_P:
-            case EQUAL_P:
-                if (sr_sp == MAX_EXPRESSION_NODES)
-                    memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
-                sr_stack[sr_sp++] = b;
-                switch(b.type)
-                {
-                    case SUBOPEN_TT:
-                        if (sr_sp >= 2 && sr_stack[sr_sp-2].type == OP_TT && sr_stack[sr_sp-2].value == FCALL_OP)
-                            mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, b);
-                        else
-                            add_bracket_layer_to_emitter_stack(0);
-                        break;
-                    case OP_TT:
-                        switch(b.value){
-                            case OR_OP:
-                                if (sr_stack[sr_sp-2].type == OP_TT &&
-                                    operators[sr_stack[sr_sp-2].value].precedence == 3)
-                                    mark_top_of_emitter_stack(OR_VALUE_MARKER, b);
-                                else
-                                {   error("'or' not between values to the right of a condition");
-                                    /* Convert to + for error recovery purposes */
-                                    sr_stack[sr_sp-1].value = PLUS_OP;
-                                }
-                                break;
-                            case COMMA_OP:
-                                {
-                                    /* A comma separates arguments only if the shallowest open bracket belongs to a function call. */
-                                    int shallowest_open_bracket_index = sr_sp - 2;
-                                    while (shallowest_open_bracket_index > 0 && sr_stack[shallowest_open_bracket_index].type != SUBOPEN_TT)
-                                        --shallowest_open_bracket_index;
-                                    if (shallowest_open_bracket_index > 0 &&
-                                        sr_stack[shallowest_open_bracket_index-1].type == OP_TT &&
-                                        sr_stack[shallowest_open_bracket_index-1].value == FCALL_OP)
-                                    {   mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, b);
-                                        break;
-                                    }
-                                    /* Non-argument-separating commas get treated like any other operator; we fall through to the default case. */
-                                }
-                            default:
-                                {
-                                    /* Add a marker for the brackets implied by operator precedence */
-                                    int operands_on_left = (operators[b.value].usage == PRE_U) ? 0 : 1;
-                                    add_bracket_layer_to_emitter_stack(operands_on_left);
-                                }
-                        }
-                }
-                get_next_etoken();
-                break;
-            case GREATER_P:
-                do
-                {   pop = sr_stack[sr_sp - 1];
-                    emit_token(pop);
-                    sr_sp--;
-                } while (find_prec(sr_stack[sr_sp-1], pop) != LOWER_P);
-                break;
-
-            case e1:                 /* Missing operand error                */
-                error_named("Missing operand after", a.text);
-                put_token_back();
-                current_token.type = NUMBER_TT;
-                current_token.value = 0;
-                current_token.marker = 0;
-                current_token.text = "0";
-                break;
-
-            case e2:                 /* Unexpected close bracket             */
-                error("Found '(' without matching ')'");
-                get_next_etoken();
-                break;
-
-            case e3:                 /* Missing operator error               */
-                error("Missing operator: inserting '+'");
-                put_token_back();
-                current_token.type = OP_TT;
-                current_token.value = PLUS_OP;
-                current_token.marker = 0;
-                current_token.text = "+";
-                break;
-
-            case e4:                 /* Expression ends with an open bracket */
-                error("Found '(' without matching ')'");
-                sr_sp--;
-                break;
-
-        }
-    }
-    while (TRUE);
-}
-
-/* --- Test for simple ++ or -- usage: used to optimise "for" loop code ---- */
-
-extern int test_for_incdec(assembly_operand AO)
-{   int s = 0;
-    if (AO.type != EXPRESSION_OT) return 0;
-    if (ET[AO.value].down == -1) return 0;
-    switch(ET[AO.value].operator_number)
-    {   case INC_OP:      s = 1; break;
-        case POST_INC_OP: s = 1; break;
-        case DEC_OP:      s = -1; break;
-        case POST_DEC_OP: s = -1; break;
-    }
-    if (s==0) return 0;
-    if (ET[ET[AO.value].down].down != -1) return 0;
-    if (!is_variable_ot(ET[ET[AO.value].down].value.type)) return 0;
-    return s*(ET[ET[AO.value].down].value.value);
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_expressp_vars(void)
-{   int i;
-    /* make_operands(); */
-    make_lexical_interface_tables();
-    for (i=0;i<32;i++) system_function_usage[i] = 0;
-}
-
-extern void expressp_begin_pass(void)
-{
-}
-
-extern void expressp_allocate_arrays(void)
-{   ET = my_calloc(sizeof(expression_tree_node), MAX_EXPRESSION_NODES,
-        "expression parse trees");
-    emitter_markers = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
-        "emitter markers");
-    emitter_bracket_counts = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
-        "emitter bracket layer counts");
-    emitter_stack = my_calloc(sizeof(assembly_operand), MAX_EXPRESSION_NODES,
-        "emitter stack");
-    sr_stack = my_calloc(sizeof(token_data), MAX_EXPRESSION_NODES,
-        "shift-reduce parser stack");
-}
-
-extern void expressp_free_arrays(void)
-{   my_free(&ET, "expression parse trees");
-    my_free(&emitter_markers, "emitter markers");
-    my_free(&emitter_bracket_counts, "emitter bracket layer counts");
-    my_free(&emitter_stack, "emitter stack");
-    my_free(&sr_stack, "shift-reduce parser stack");
-}
-
-/* ========================================================================= */