Implement a Makefile for Inform.
[inform.git] / directs.c
diff --git a/directs.c b/directs.c
deleted file mode 100644 (file)
index d3b7f32..0000000
--- a/directs.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "directs" : Directives (# commands)                                     */
-/*                                                                           */
-/* 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"
-
-int no_routines,                   /* Number of routines compiled so far     */
-    no_named_routines,             /* Number not embedded in objects         */
-    no_locals,                     /* Number of locals in current routine    */
-    no_termcs;                     /* Number of terminating characters       */
-int terminating_characters[32];
-
-brief_location routine_starts_line; /* Source code location where the current
-                                      routine starts.  (Useful for reporting
-                                      "unused variable" warnings on the start
-                                      line rather than the end line.)        */
-
-static int constant_made_yet;      /* Have any constants been defined yet?   */
-
-static int ifdef_stack[32], ifdef_sp;
-
-/* ------------------------------------------------------------------------- */
-
-static int ebf_error_recover(char *s1, char *s2)
-{
-    /* Display an "expected... but found..." error, then skim forward
-       to the next semicolon and return FALSE. This is such a common
-       case in parse_given_directive() that it's worth a utility
-       function. You will see many error paths that look like:
-          return ebf_error_recover(...);
-    */
-    ebf_error(s1, s2);
-    panic_mode_error_recovery();
-    return FALSE;
-}
-
-/* ------------------------------------------------------------------------- */
-
-extern int parse_given_directive(int internal_flag)
-{   /*  Internal_flag is FALSE if the directive is encountered normally,
-        TRUE if encountered with a # prefix inside a routine or object
-        definition.
-
-        Returns: FALSE if program continues, TRUE if end of file reached.    */
-
-    int *trace_level = NULL; int32 i, j, k, n, flag;
-    const char *constant_name;
-    debug_location_beginning beginning_debug_location;
-
-    switch(token_value)
-    {
-
-    /* --------------------------------------------------------------------- */
-    /*   Abbreviate "string1" ["string2" ...]                                */
-    /* --------------------------------------------------------------------- */
-
-    case ABBREVIATE_CODE:
-
-        do
-        {  get_next_token();
-           if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-               return FALSE;
-
-           /* Z-code has a 64-abbrev limit; Glulx doesn't. */
-           if (!glulx_mode && no_abbreviations==64)
-           {   error("All 64 abbreviations already declared");
-               panic_mode_error_recovery(); return FALSE;
-           }
-           if (no_abbreviations==MAX_ABBREVS)
-               memoryerror("MAX_ABBREVS", MAX_ABBREVS);
-
-           if (abbrevs_lookup_table_made)
-           {   error("All abbreviations must be declared together");
-               panic_mode_error_recovery(); return FALSE;
-           }
-           if (token_type != DQ_TT)
-               return ebf_error_recover("abbreviation string", token_text);
-           if (strlen(token_text)<2)
-           {   error_named("It's not worth abbreviating", token_text);
-               continue;
-           }
-           /* Abbreviation string with null must fit in a MAX_ABBREV_LENGTH
-              array. */
-           if (strlen(token_text)>=MAX_ABBREV_LENGTH)
-           {   error_named("Abbreviation too long", token_text);
-               continue;
-           }
-           make_abbreviation(token_text);
-        } while (TRUE);
-
-    /* --------------------------------------------------------------------- */
-    /*   Array arrayname array...                                            */
-    /* --------------------------------------------------------------------- */
-
-    case ARRAY_CODE: make_global(TRUE, FALSE); break;      /* See "tables.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Attribute newname [alias oldname]                                   */
-    /* --------------------------------------------------------------------- */
-
-    case ATTRIBUTE_CODE:
-        make_attribute(); break;                          /* See "objects.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Class classname ...                                                 */
-    /* --------------------------------------------------------------------- */
-
-    case CLASS_CODE: 
-        if (internal_flag)
-        {   error("Cannot nest #Class inside a routine or object");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        make_class(NULL);                                 /* See "objects.c" */
-        return FALSE;
-
-    /* --------------------------------------------------------------------- */
-    /*   Constant newname [[=] value] [, ...]                                */
-    /* --------------------------------------------------------------------- */
-
-    case CONSTANT_CODE:
-        constant_made_yet=TRUE;
-
-      ParseConstantSpec:
-        get_next_token(); i = token_value;
-        beginning_debug_location = get_token_location_beginning();
-
-        if ((token_type != SYMBOL_TT)
-            || (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))))
-        {   discard_token_location(beginning_debug_location);
-            return ebf_error_recover("new constant name", token_text);
-        }
-
-        assign_symbol(i, 0, CONSTANT_T);
-        constant_name = token_text;
-
-        get_next_token();
-
-        if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
-        {   if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
-            {   debug_file_printf("<constant>");
-                debug_file_printf("<identifier>%s</identifier>", constant_name);
-                write_debug_symbol_optional_backpatch(i);
-                write_debug_locations(get_token_location_end(beginning_debug_location));
-                debug_file_printf("</constant>");
-            }
-            goto ParseConstantSpec;
-        }
-
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-        {   if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
-            {   debug_file_printf("<constant>");
-                debug_file_printf("<identifier>%s</identifier>", constant_name);
-                write_debug_symbol_optional_backpatch(i);
-                write_debug_locations(get_token_location_end(beginning_debug_location));
-                debug_file_printf("</constant>");
-            }
-            return FALSE;
-        }
-
-        if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
-            put_token_back();
-
-        {   assembly_operand AO = parse_expression(CONSTANT_CONTEXT);
-            if (AO.marker != 0)
-            {   assign_marked_symbol(i, AO.marker, AO.value,
-                    CONSTANT_T);
-                sflags[i] |= CHANGE_SFLAG;
-                if (i == grammar_version_symbol)
-                    error(
-                "Grammar__Version must be given an explicit constant value");
-            }
-            else
-            {   assign_symbol(i, AO.value, CONSTANT_T);
-                if (i == grammar_version_symbol)
-                {   if ((grammar_version_number != AO.value)
-                        && (no_fake_actions > 0))
-                        error(
-                "Once a fake action has been defined it is too late to \
-change the grammar version. (If you are using the library, move any \
-Fake_Action directives to a point after the inclusion of \"Parser\".)");
-                    grammar_version_number = AO.value;
-                }
-            }
-        }
-
-        if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
-        {   debug_file_printf("<constant>");
-            debug_file_printf("<identifier>%s</identifier>", constant_name);
-            write_debug_symbol_optional_backpatch(i);
-            write_debug_locations
-                (get_token_location_end(beginning_debug_location));
-            debug_file_printf("</constant>");
-        }
-
-        get_next_token();
-        if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
-            goto ParseConstantSpec;
-        put_token_back();
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Default constantname integer                                        */
-    /* --------------------------------------------------------------------- */
-
-    case DEFAULT_CODE:
-        if (module_switch)
-        {   error("'Default' cannot be used in -M (Module) mode");
-            panic_mode_error_recovery(); return FALSE;
-        }
-
-        get_next_token();
-        if (token_type != SYMBOL_TT)
-            return ebf_error_recover("name", token_text);
-
-        i = -1;
-        if (sflags[token_value] & UNKNOWN_SFLAG)
-        {   i = token_value;
-            sflags[i] |= DEFCON_SFLAG;
-        }
-
-        get_next_token();
-        if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
-            put_token_back();
-
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            if (i != -1)
-            {   if (AO.marker != 0)
-                {   assign_marked_symbol(i, AO.marker, AO.value,
-                        CONSTANT_T);
-                    sflags[i] |= CHANGE_SFLAG;
-                }
-                else assign_symbol(i, AO.value, CONSTANT_T);
-            }
-        }
-
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Dictionary 'word'                                                   */
-    /*   Dictionary 'word' val1                                              */
-    /*   Dictionary 'word' val1 val3                                         */
-    /* --------------------------------------------------------------------- */
-
-    case DICTIONARY_CODE:
-        /* In Inform 5, this directive had the form
-             Dictionary SYMBOL "word";
-           This was deprecated as of I6 (if not earlier), and is no longer
-           supported at all. The current form just creates a dictionary word,
-           with the given values for dict_par1 and dict_par3. If the word
-           already exists, the values are bit-or'd in with the existing
-           values.
-           (We don't offer a way to set dict_par2, because that is entirely
-           reserved for the verb number. Or'ing values into it would create
-           garbage.)
-         */
-        get_next_token();
-        if (token_type != SQ_TT && token_type != DQ_TT)
-            return ebf_error_recover("dictionary word", token_text);
-
-        {
-            char *wd = token_text;
-            int val1 = 0;
-            int val3 = 0;
-
-            get_next_token();
-            if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
-                put_token_back();
-            }
-            else {
-                assembly_operand AO;
-                put_token_back();
-                AO = parse_expression(CONSTANT_CONTEXT);
-                if (module_switch && (AO.marker != 0))
-                    error("A definite value must be given as a Dictionary flag");
-                else
-                    val1 = AO.value;
-
-                get_next_token();
-                if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
-                    put_token_back();
-                }
-                else {
-                    assembly_operand AO;
-                    put_token_back();
-                    AO = parse_expression(CONSTANT_CONTEXT);
-                    if (module_switch && (AO.marker != 0))
-                        error("A definite value must be given as a Dictionary flag");
-                    else
-                        val3 = AO.value;
-                }
-            }
-
-            if (!glulx_mode) {
-                if ((val1 & ~0xFF) || (val3 & ~0xFF)) {
-                    warning("Dictionary flag values cannot exceed $FF in Z-code");
-                }
-            }
-            else {
-                if ((val1 & ~0xFFFF) || (val3 & ~0xFFFF)) {
-                    warning("Dictionary flag values cannot exceed $FFFF in Glulx");
-                }
-            }
-
-            dictionary_add(wd, val1, 0, val3);
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   End                                                                 */
-    /* --------------------------------------------------------------------- */
-
-    case END_CODE: return(TRUE);
-
-    case ENDIF_CODE:
-        if (ifdef_sp == 0) error("'Endif' without matching 'If...'");
-        else ifdef_sp--;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Extend ...                                                          */
-    /* --------------------------------------------------------------------- */
-
-    case EXTEND_CODE: extend_verb(); return FALSE;         /* see "tables.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Fake_Action name                                                    */
-    /* --------------------------------------------------------------------- */
-
-    case FAKE_ACTION_CODE:
-        make_fake_action(); break;                          /* see "verbs.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Global variable [= value / array...]                                */
-    /* --------------------------------------------------------------------- */
-
-    case GLOBAL_CODE: make_global(FALSE, FALSE); break;    /* See "tables.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   If...                                                               */
-    /*                                                                       */
-    /*   Note that each time Inform tests an If... condition, it stacks the  */
-    /*   result (TRUE or FALSE) on ifdef_stack: thus, the top of this stack  */
-    /*   reveals what clause of the current If... is being compiled:         */
-    /*                                                                       */
-    /*               If...;  ...  Ifnot;  ...  Endif;                        */
-    /*   top of stack:       TRUE        FALSE                               */
-    /*                                                                       */
-    /*   This is used to detect "two Ifnots in same If" errors.              */
-    /* --------------------------------------------------------------------- */
-
-    case IFDEF_CODE:
-        flag = TRUE;
-        goto DefCondition;
-    case IFNDEF_CODE:
-        flag = FALSE;
-
-      DefCondition:
-        get_next_token();
-        if (token_type != SYMBOL_TT)
-            return ebf_error_recover("symbol name", token_text);
-
-        if ((token_text[0] == 'V')
-            && (token_text[1] == 'N')
-            && (token_text[2] == '_')
-            && (strlen(token_text)==7))
-        {   i = atoi(token_text+3);
-            if (VNUMBER < i) flag = (flag)?FALSE:TRUE;
-            goto HashIfCondition;
-        }
-
-        if (sflags[token_value] & UNKNOWN_SFLAG) flag = (flag)?FALSE:TRUE;
-        else sflags[token_value] |= USED_SFLAG;
-        goto HashIfCondition;
-
-    case IFNOT_CODE:
-        if (ifdef_sp == 0)
-            error("'Ifnot' without matching 'If...'");
-        else
-        if (!(ifdef_stack[ifdef_sp-1]))
-            error("Second 'Ifnot' for the same 'If...' condition");
-        else
-        {   dont_enter_into_symbol_table = -2; n = 1;
-            directives.enabled = TRUE;
-            do
-            {   get_next_token();
-                if (token_type == EOF_TT)
-                {   error("End of file reached in code 'If...'d out");
-                    directives.enabled = FALSE;
-                    return TRUE;
-                }
-                if (token_type == DIRECTIVE_TT)
-                {   switch(token_value)
-                    {   case ENDIF_CODE:
-                            n--; break;
-                        case IFV3_CODE:
-                        case IFV5_CODE:
-                        case IFDEF_CODE:
-                        case IFNDEF_CODE:
-                        case IFTRUE_CODE:
-                        case IFFALSE_CODE:
-                            n++; break;
-                        case IFNOT_CODE:
-                            if (n == 1)
-                            {   error(
-                              "Second 'Ifnot' for the same 'If...' condition");
-                                break;
-                            }
-                    }
-                }
-            } while (n > 0);
-            ifdef_sp--; 
-            dont_enter_into_symbol_table = FALSE;
-            directives.enabled = FALSE;
-        }
-        break;
-
-    case IFV3_CODE:
-        flag = FALSE; if (version_number == 3) flag = TRUE;
-        goto HashIfCondition;
-
-    case IFV5_CODE:
-        flag = TRUE; if (version_number == 3) flag = FALSE;
-        goto HashIfCondition;
-
-    case IFTRUE_CODE:
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            if (module_switch && (AO.marker != 0))
-            {   error("This condition can't be determined");
-                flag = 0;
-            }
-            else flag = (AO.value != 0);
-        }
-        goto HashIfCondition;
-
-    case IFFALSE_CODE:
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            if (module_switch && (AO.marker != 0))
-            {   error("This condition can't be determined");
-                flag = 1;
-            }
-            else flag = (AO.value == 0);
-        }
-        goto HashIfCondition;
-
-    HashIfCondition:
-        get_next_token();
-        if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-            return ebf_error_recover("semicolon after 'If...' condition", token_text);
-
-        if (flag)
-        {   ifdef_stack[ifdef_sp++] = TRUE; return FALSE; }
-        else
-        {   dont_enter_into_symbol_table = -2; n = 1;
-            directives.enabled = TRUE;
-            do
-            {   get_next_token();
-                if (token_type == EOF_TT)
-                {   error("End of file reached in code 'If...'d out");
-                    directives.enabled = FALSE;
-                    return TRUE;
-                }
-                if (token_type == DIRECTIVE_TT)
-                {
-                    switch(token_value)
-                    {   case ENDIF_CODE:
-                            n--; break;
-                        case IFV3_CODE:
-                        case IFV5_CODE:
-                        case IFDEF_CODE:
-                        case IFNDEF_CODE:
-                        case IFTRUE_CODE:
-                        case IFFALSE_CODE:
-                            n++; break;
-                        case IFNOT_CODE:
-                            if (n == 1)
-                            {   ifdef_stack[ifdef_sp++] = FALSE;
-                                n--; break;
-                            }
-                    }
-                }
-            } while (n > 0);
-            directives.enabled = FALSE;
-            dont_enter_into_symbol_table = FALSE;
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Import global <varname> [, ...]                                     */
-    /*                                                                       */
-    /* (Further imported goods may be allowed later.)                        */
-    /* --------------------------------------------------------------------- */
-
-    case IMPORT_CODE:
-        if (!module_switch)
-        {   error("'Import' can only be used in -M (Module) mode");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        directives.enabled = TRUE;
-        do
-        {   get_next_token();
-            if ((token_type == DIRECTIVE_TT) && (token_value == GLOBAL_CODE))
-                 make_global(FALSE, TRUE);
-            else error_named("'Import' cannot import things of this type:",
-                 token_text);
-            get_next_token();
-        } while ((token_type == SEP_TT) && (token_value == COMMA_SEP));
-        put_token_back();
-        directives.enabled = FALSE;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Include "[>]filename"                                               */
-    /*                                                                       */
-    /* The ">" character means to load the file from the same directory as   */
-    /* the current file, instead of relying on the include path.             */
-    /* --------------------------------------------------------------------- */
-
-    case INCLUDE_CODE:
-        get_next_token();
-        if (token_type != DQ_TT)
-            return ebf_error_recover("filename in double-quotes", token_text);
-
-        {   char *name = token_text;
-
-            get_next_token();
-            if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-                ebf_error("semicolon ';' after Include filename", token_text);
-
-            if (strcmp(name, "language__") == 0)
-                 load_sourcefile(Language_Name, 0);
-            else if (name[0] == '>')
-                 load_sourcefile(name+1, 1);
-            else load_sourcefile(name, 0);
-            return FALSE;
-        }
-
-    /* --------------------------------------------------------------------- */
-    /*   Link "filename"                                                     */
-    /* --------------------------------------------------------------------- */
-
-    case LINK_CODE:
-        get_next_token();
-        if (token_type != DQ_TT)
-            return ebf_error_recover("filename in double-quotes", token_text);
-        link_module(token_text);                           /* See "linker.c" */
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Lowstring constantname "text of string"                             */
-    /* --------------------------------------------------------------------- */
-    /* Unlike most constant creations, these do not require backpatching:    */
-    /* the low strings always occupy a table at a fixed offset in the        */
-    /* Z-machine (after the abbreviations table has finished, at 0x100).     */
-    /* --------------------------------------------------------------------- */
-
-    case LOWSTRING_CODE:
-        if (module_switch)
-        {   error("'LowString' cannot be used in -M (Module) mode");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        get_next_token(); i = token_value;
-        if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
-            return ebf_error_recover("new low string name", token_text);
-
-        get_next_token();
-        if (token_type != DQ_TT)
-            return ebf_error_recover("literal string in double-quotes", token_text);
-
-        assign_symbol(i, compile_string(token_text, TRUE, TRUE), CONSTANT_T);
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Message | "information"                                             */
-    /*           | error "error message"                                     */
-    /*           | fatalerror "fatal error message"                          */
-    /*           | warning "warning message"                                 */
-    /* --------------------------------------------------------------------- */
-
-    case MESSAGE_CODE:
-        directive_keywords.enabled = TRUE;
-        get_next_token();
-        directive_keywords.enabled = FALSE;
-        if (token_type == DQ_TT)
-        {   int i;
-            if (hash_printed_since_newline) printf("\n");
-            for (i=0; token_text[i]!=0; i++)
-            {   if (token_text[i] == '^') printf("\n");
-                else
-                if (token_text[i] == '~') printf("\"");
-                else printf("%c", token_text[i]);
-            }
-            printf("\n");
-            break;
-        }
-        if ((token_type == DIR_KEYWORD_TT) && (token_value == ERROR_DK))
-        {   get_next_token();
-            if (token_type != DQ_TT)
-            {   return ebf_error_recover("error message in double-quotes", token_text);
-            }
-            error(token_text); break;
-        }
-        if ((token_type == DIR_KEYWORD_TT) && (token_value == FATALERROR_DK))
-        {   get_next_token();
-            if (token_type != DQ_TT)
-            {   return ebf_error_recover("fatal error message in double-quotes", token_text);
-            }
-            fatalerror(token_text); break;
-        }
-        if ((token_type == DIR_KEYWORD_TT) && (token_value == WARNING_DK))
-        {   get_next_token();
-            if (token_type != DQ_TT)
-            {   return ebf_error_recover("warning message in double-quotes", token_text);
-            }
-            warning(token_text); break;
-        }
-        return ebf_error_recover("a message in double-quotes, 'error', 'fatalerror' or 'warning'",
-            token_text);
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Nearby objname "short name" ...                                     */
-    /* --------------------------------------------------------------------- */
-
-    case NEARBY_CODE:
-        if (internal_flag)
-        {   error("Cannot nest #Nearby inside a routine or object");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        make_object(TRUE, NULL, -1, -1, -1);
-        return FALSE;                                     /* See "objects.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Object objname "short name" ...                                     */
-    /* --------------------------------------------------------------------- */
-
-    case OBJECT_CODE:
-        if (internal_flag)
-        {   error("Cannot nest #Object inside a routine or object");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        make_object(FALSE, NULL, -1, -1, -1);
-        return FALSE;                                     /* See "objects.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Origsource <file>                                                   */
-    /*   Origsource <file> <line>                                            */
-    /*   Origsource <file> <line> <char>                                     */
-    /*   Origsource                                                          */
-    /*                                                                       */
-    /*   The first three forms declare that all following lines are derived  */
-    /*   from the named Inform 7 source file (with an optional line number   */
-    /*   and character number). This will be reported in error messages and  */
-    /*   in debug output. The declaration holds through the next Origsource  */
-    /*   directive (but does not apply to included files).                   */
-    /*                                                                       */
-    /*   The fourth form, with no arguments, clears the declaration.         */
-    /*                                                                       */
-    /*   Unlike the Include directive, Origsource does not open the named    */
-    /*   file or even verify that it exists. The filename is treated as an   */
-    /*   opaque string.                                                      */
-    /* --------------------------------------------------------------------- */
-
-    case ORIGSOURCE_CODE:
-        {
-            char *origsource_file = NULL;
-            int32 origsource_line = 0;
-            int32 origsource_char = 0;
-
-            /* Parse some optional tokens followed by a mandatory semicolon. */
-
-            get_next_token();
-            if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
-                if (token_type != DQ_TT) {
-                    return ebf_error_recover("a file name in double-quotes",
-                        token_text);
-                }
-                origsource_file = token_text;
-
-                get_next_token();
-                if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
-                    if (token_type != NUMBER_TT) {
-                        return ebf_error_recover("a file line number",
-                            token_text);
-                    }
-                    origsource_line = token_value;
-                    if (origsource_line < 0)
-                        origsource_line = 0;
-
-                    get_next_token();
-                    if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
-                        if (token_type != NUMBER_TT) {
-                            return ebf_error_recover("a file line number",
-                                token_text);
-                        }
-                        origsource_char = token_value;
-                        if (origsource_char < 0)
-                            origsource_char = 0;
-                        
-                        get_next_token();
-                    }
-                }
-            }
-
-            put_token_back();
-
-            set_origsource_location(origsource_file, origsource_line, origsource_char);
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Property [long] [additive] name [alias oldname]                     */
-    /* --------------------------------------------------------------------- */
-
-    case PROPERTY_CODE: make_property(); break;           /* See "objects.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Release <number>                                                    */
-    /* --------------------------------------------------------------------- */
-
-    case RELEASE_CODE:
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            if (module_switch && (AO.marker != 0))
-                error("A definite value must be given as release number");
-            else
-                release_number = AO.value;
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Replace routine [routinename]                                       */
-    /* --------------------------------------------------------------------- */
-
-    case REPLACE_CODE:
-        /* You can also replace system functions normally implemented in     */
-        /* the "hardware" of the Z-machine, like "random()":                 */
-
-        system_functions.enabled = TRUE;
-        directives.enabled = FALSE;
-        directive_keywords.enabled = FALSE;
-
-        /* Don't count the upcoming symbol as a top-level reference
-           *to* the function. */
-        df_dont_note_global_symbols = TRUE;
-        get_next_token();
-        df_dont_note_global_symbols = FALSE;
-        if (token_type == SYSFUN_TT)
-        {   if (system_function_usage[token_value] == 1)
-                error("You can't 'Replace' a system function already used");
-            else system_function_usage[token_value] = 2;
-            get_next_token();
-            if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-            {
-                error("You can't give a 'Replace'd system function a new name");
-                panic_mode_error_recovery(); return FALSE;
-            }
-            return FALSE;
-        }
-
-        if (token_type != SYMBOL_TT)
-            return ebf_error_recover("name of routine to replace", token_text);
-        if (!(sflags[token_value] & UNKNOWN_SFLAG))
-            return ebf_error_recover("name of routine not yet defined", token_text);
-
-        sflags[token_value] |= REPLACE_SFLAG;
-
-        /* If a second symbol is provided, it will refer to the
-           original (replaced) definition of the routine. */
-        i = token_value;
-
-        system_functions.enabled = FALSE;
-        df_dont_note_global_symbols = TRUE;
-        get_next_token();
-        df_dont_note_global_symbols = FALSE;
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-        {   return FALSE;
-        }
-
-        if (token_type != SYMBOL_TT || !(sflags[token_value] & UNKNOWN_SFLAG))
-            return ebf_error_recover("semicolon ';' or new routine name", token_text);
-
-        /* Define the original-form symbol as a zero constant. Its
-           value will be overwritten later, when we define the
-           replacement. */
-        assign_symbol(token_value, 0, CONSTANT_T);
-        add_symbol_replacement_mapping(i, token_value);
-
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Serial "yymmdd"                                                     */
-    /* --------------------------------------------------------------------- */
-
-    case SERIAL_CODE:
-        get_next_token();
-        if ((token_type != DQ_TT) || (strlen(token_text)!=6))
-        {   error("The serial number must be a 6-digit date in double-quotes");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        for (i=0; i<6; i++) if (isdigit(token_text[i])==0)
-        {   error("The serial number must be a 6-digit date in double-quotes");
-            panic_mode_error_recovery(); return FALSE;
-        }
-        strcpy(serial_code_buffer, token_text);
-        serial_code_given_in_program = TRUE;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Statusline score/time                                               */
-    /* --------------------------------------------------------------------- */
-
-    case STATUSLINE_CODE:
-        if (module_switch)
-            warning("This does not set the final game's statusline");
-
-        directive_keywords.enabled = TRUE;
-        get_next_token();
-        directive_keywords.enabled = FALSE;
-        if ((token_type != DIR_KEYWORD_TT)
-            || ((token_value != SCORE_DK) && (token_value != TIME_DK)))
-            return ebf_error_recover("'score' or 'time' after 'statusline'", token_text);
-        if (token_value == SCORE_DK) statusline_flag = SCORE_STYLE;
-        else statusline_flag = TIME_STYLE;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Stub routinename number-of-locals                                   */
-    /* --------------------------------------------------------------------- */
-
-    case STUB_CODE:
-        if (internal_flag)
-        {   error("Cannot nest #Stub inside a routine or object");
-            panic_mode_error_recovery(); return FALSE;
-        }
-
-        /* The upcoming symbol is a definition; don't count it as a
-           top-level reference *to* the stub function. */
-        df_dont_note_global_symbols = TRUE;
-        get_next_token();
-        df_dont_note_global_symbols = FALSE;
-        if (token_type != SYMBOL_TT)
-            return ebf_error_recover("routine name to stub", token_text);
-
-        i = token_value; flag = FALSE;
-
-        if (sflags[i] & UNKNOWN_SFLAG)
-        {   sflags[i] |= STUB_SFLAG;
-            flag = TRUE;
-        }
-
-        get_next_token(); k = token_value;
-        if (token_type != NUMBER_TT)
-            return ebf_error_recover("number of local variables", token_text);
-        if ((k>4) || (k<0))
-        {   error("Must specify 0 to 4 local variables for 'Stub' routine");
-            k = 0;
-        }
-
-        if (flag)
-        {
-            /*  Give these parameter-receiving local variables names
-                for the benefit of the debugging information file,
-                and for assembly tracing to look sensible.                   */
-
-            local_variable_texts[0] = "dummy1";
-            local_variable_texts[1] = "dummy2";
-            local_variable_texts[2] = "dummy3";
-            local_variable_texts[3] = "dummy4";
-
-            assign_symbol(i,
-                assemble_routine_header(k, FALSE, (char *) symbs[i], FALSE, i),
-                ROUTINE_T);
-
-            /*  Ensure the return value of a stubbed routine is false,
-                since this is necessary to make the library work properly    */
-
-            if (!glulx_mode)
-                assemblez_0(rfalse_zc);
-            else
-                assembleg_1(return_gc, zero_operand);
-
-            /*  Inhibit "local variable unused" warnings  */
-
-            for (i=1; i<=k; i++) variable_usage[i] = 1;
-            sequence_point_follows = FALSE;
-            assemble_routine_end(FALSE, get_token_locations());
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Switches switchblock                                                */
-    /* (this directive is ignored if the -i switch was set at command line)  */
-    /* --------------------------------------------------------------------- */
-
-    case SWITCHES_CODE:
-        dont_enter_into_symbol_table = TRUE;
-        get_next_token();
-        dont_enter_into_symbol_table = FALSE;
-        if (token_type != DQ_TT)
-            return ebf_error_recover("string of switches", token_text);
-        if (!ignore_switches_switch)
-        {   if (constant_made_yet)
-                error("A 'Switches' directive must must come before \
-the first constant definition");
-            switches(token_text, 0);                       /* see "inform.c" */
-        }
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   System_file                                                         */
-    /*                                                                       */
-    /* Some files are declared as "system files": this information is used   */
-    /* by Inform only to skip the definition of a routine X if the designer  */
-    /* has indicated his intention to Replace X.                             */
-    /* --------------------------------------------------------------------- */
-
-    case SYSTEM_CODE:
-        declare_systemfile(); break;                        /* see "files.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Trace dictionary                                                    */
-    /*         objects                                                       */
-    /*         symbols                                                       */
-    /*         verbs                                                         */
-    /*                      [on/off]                                         */
-    /*         assembly     [on/off]                                         */
-    /*         expressions  [on/off]                                         */
-    /*         lines        [on/off]                                         */
-    /* --------------------------------------------------------------------- */
-
-    case TRACE_CODE:
-        directives.enabled = FALSE;
-        trace_keywords.enabled = TRUE;
-        get_next_token();
-        trace_keywords.enabled = FALSE;
-        directives.enabled = TRUE;
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-        {   asm_trace_level = 1; return FALSE; }
-
-        if (token_type != TRACE_KEYWORD_TT)
-            return ebf_error_recover("debugging keyword", token_text);
-
-        trace_keywords.enabled = TRUE;
-
-        i = token_value; j = 0;
-        switch(i)
-        {   case DICTIONARY_TK: break;
-            case OBJECTS_TK:    break;
-            case VERBS_TK:      break;
-            default:
-                switch(token_value)
-                {   case ASSEMBLY_TK:
-                        trace_level = &asm_trace_level;  break;
-                    case EXPRESSIONS_TK:
-                        trace_level = &expr_trace_level; break;
-                    case LINES_TK:
-                        trace_level = &line_trace_level; break;
-                    case TOKENS_TK:
-                        trace_level = &tokens_trace_level; break;
-                    case LINKER_TK:
-                        trace_level = &linker_trace_level; break;
-                    case SYMBOLS_TK:
-                        trace_level = NULL; break;
-                    default:
-                        put_token_back();
-                        trace_level = &asm_trace_level; break;
-                }
-                j = 1;
-                get_next_token();
-                if ((token_type == SEP_TT) &&
-                    (token_value == SEMICOLON_SEP))
-                {   put_token_back(); break;
-                }
-                if (token_type == NUMBER_TT)
-                {   j = token_value; break; }
-                if ((token_type == TRACE_KEYWORD_TT) && (token_value == ON_TK))
-                {   j = 1; break; }
-                if ((token_type == TRACE_KEYWORD_TT) && (token_value == OFF_TK))
-                {   j = 0; break; }
-                put_token_back(); break;
-        }
-
-        switch(i)
-        {   case DICTIONARY_TK: show_dictionary();  break;
-            case OBJECTS_TK:    list_object_tree(); break;
-            case SYMBOLS_TK:    list_symbols(j);     break;
-            case VERBS_TK:      list_verb_table();  break;
-            default:
-                *trace_level = j;
-                break;
-        }
-        trace_keywords.enabled = FALSE;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Undef symbol                                                        */
-    /* --------------------------------------------------------------------- */
-
-    case UNDEF_CODE:
-        get_next_token();
-        if (token_type != SYMBOL_TT)
-            return ebf_error_recover("symbol name", token_text);
-
-        if (sflags[token_value] & UNKNOWN_SFLAG)
-        {   break; /* undef'ing an undefined constant is okay */
-        }
-
-        if (stypes[token_value] != CONSTANT_T)
-        {   error_named("Cannot Undef a symbol which is not a defined constant:", (char *)symbs[token_value]);
-            break;
-        }
-
-        if (debugfile_switch)
-        {   write_debug_undef(token_value);
-        }
-        end_symbol_scope(token_value);
-        sflags[token_value] |= USED_SFLAG;
-        break;
-
-    /* --------------------------------------------------------------------- */
-    /*   Verb ...                                                            */
-    /* --------------------------------------------------------------------- */
-
-    case VERB_CODE: make_verb(); return FALSE;             /* see "tables.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Version <number>                                                    */
-    /* --------------------------------------------------------------------- */
-
-    case VERSION_CODE:
-
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            /* If a version has already been set on the command line,
-               that overrides this. */
-            if (version_set_switch)
-            {
-              warning("The Version directive was overridden by a command-line argument.");
-              break;
-            }
-
-            if (module_switch && (AO.marker != 0))
-                error("A definite value must be given as version number");
-            else 
-            if (glulx_mode) 
-            {
-              warning("The Version directive does not work in Glulx. Use \
--vX.Y.Z instead, as either a command-line argument or a header comment.");
-              break;
-            }
-            else
-            {   i = AO.value;
-                if ((i<3) || (i>8))
-                {   error("The version number must be in the range 3 to 8");
-                    break;
-                }
-                select_version(i);
-            }
-        }
-        break;                                             /* see "inform.c" */
-
-    /* --------------------------------------------------------------------- */
-    /*   Zcharacter table <num> ...                                          */
-    /*   Zcharacter table + <num> ...                                        */
-    /*   Zcharacter <string> <string> <string>                               */
-    /*   Zcharacter <char>                                                   */
-    /* --------------------------------------------------------------------- */
-
-    case ZCHARACTER_CODE:
-
-        if (glulx_mode) {
-            error("The Zcharacter directive has no meaning in Glulx.");
-            panic_mode_error_recovery(); return FALSE;
-        }
-
-        directive_keywords.enabled = TRUE;
-        get_next_token();
-        directive_keywords.enabled = FALSE;
-
-        switch(token_type)
-        {   case DQ_TT:
-                new_alphabet(token_text, 0);
-                get_next_token();
-                if (token_type != DQ_TT)
-                    return ebf_error_recover("double-quoted alphabet string", token_text);
-                new_alphabet(token_text, 1);
-                get_next_token();
-                if (token_type != DQ_TT)
-                    return ebf_error_recover("double-quoted alphabet string", token_text);
-                new_alphabet(token_text, 2);
-            break;
-
-            case SQ_TT:
-                map_new_zchar(text_to_unicode(token_text));
-                if (token_text[textual_form_length] != 0)
-                    return ebf_error_recover("single character value", token_text);
-            break;
-
-            case DIR_KEYWORD_TT:
-            switch(token_value)
-            {   case TABLE_DK:
-                {   int plus_flag = FALSE;
-                    get_next_token();
-                    if ((token_type == SEP_TT) && (token_value == PLUS_SEP))
-                    {   plus_flag = TRUE;
-                        get_next_token();
-                    }
-                    while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
-                    {   switch(token_type)
-                        {   case NUMBER_TT:
-                                new_zscii_character(token_value, plus_flag);
-                                plus_flag = TRUE; break;
-                            case SQ_TT:
-                                new_zscii_character(text_to_unicode(token_text),
-                                    plus_flag);
-                                if (token_text[textual_form_length] != 0)
-                                    return ebf_error_recover("single character value",
-                                        token_text);
-                                plus_flag = TRUE;
-                                break;
-                            default:
-                                return ebf_error_recover("character or Unicode number",
-                                    token_text);
-                        }
-                        get_next_token();
-                    }
-                    if (plus_flag) new_zscii_finished();
-                    put_token_back();
-                }
-                    break;
-                case TERMINATING_DK:
-                    get_next_token();
-                    while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
-                    {   switch(token_type)
-                        {   case NUMBER_TT:
-                                terminating_characters[no_termcs++]
-                                    = token_value;
-                                break;
-                            default:
-                                return ebf_error_recover("ZSCII number",
-                                    token_text);
-                        }
-                        get_next_token();
-                    }
-                    put_token_back();
-                    break;
-                default:
-                    return ebf_error_recover("'table', 'terminating', \
-a string or a constant",
-                        token_text);
-            }
-                break;
-            default:
-                return ebf_error_recover("three alphabet strings, \
-a 'table' or 'terminating' command or a single character", token_text);
-        }
-        break;
-
-    /* ===================================================================== */
-
-    }
-
-    /* We are now at the end of a syntactically valid directive. It
-       should be terminated by a semicolon. */
-
-    get_next_token();
-    if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
-    {   ebf_error("';'", token_text);
-        /* Put the non-semicolon back. We will continue parsing from
-           that point, in hope that it's the start of a new directive.
-           (This recovers cleanly from a missing semicolon at the end
-           of a directive. It's not so clean if the directive *does*
-           end with a semicolon, but there's extra garbage before it.) */
-        put_token_back();
-    }
-    return FALSE;
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_directs_vars(void)
-{
-}
-
-extern void directs_begin_pass(void)
-{   no_routines = 0;
-    no_named_routines = 0;
-    no_locals = 0;
-    no_termcs = 0;
-    constant_made_yet = FALSE;
-    ifdef_sp = 0;
-}
-
-extern void directs_allocate_arrays(void)
-{
-}
-
-extern void directs_free_arrays(void)
-{
-}
-
-/* ========================================================================= */