Implement a Makefile for Inform. master
authorJason Self <j@jxself.org>
Sat, 13 Jul 2019 17:16:55 +0000 (10:16 -0700)
committerJason Self <j@jxself.org>
Sat, 13 Jul 2019 17:16:55 +0000 (10:16 -0700)
Move source code into the src directory, dynamically compute the
version number.

52 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
arrays.c [deleted file]
asm.c [deleted file]
bpatch.c [deleted file]
chars.c [deleted file]
configure.ac [new file with mode: 0644]
directs.c [deleted file]
errors.c [deleted file]
expressc.c [deleted file]
expressp.c [deleted file]
files.c [deleted file]
header.h [deleted file]
inform.c [deleted file]
lexer.c [deleted file]
linker.c [deleted file]
memory.c [deleted file]
objects.c [deleted file]
readme.txt
src/Makefile.am [new file with mode: 0644]
src/arrays.c [new file with mode: 0644]
src/asm.c [new file with mode: 0644]
src/bpatch.c [new file with mode: 0644]
src/chars.c [new file with mode: 0644]
src/directs.c [new file with mode: 0644]
src/errors.c [new file with mode: 0644]
src/expressc.c [new file with mode: 0644]
src/expressp.c [new file with mode: 0644]
src/files.c [new file with mode: 0644]
src/header.h [new file with mode: 0644]
src/inform.c [new file with mode: 0644]
src/lexer.c [new file with mode: 0644]
src/linker.c [new file with mode: 0644]
src/memory.c [new file with mode: 0644]
src/objects.c [new file with mode: 0644]
src/states.c [new file with mode: 0644]
src/symbols.c [new file with mode: 0644]
src/syntax.c [new file with mode: 0644]
src/tables.c [new file with mode: 0644]
src/text.c [new file with mode: 0644]
src/veneer.c [new file with mode: 0644]
src/verbs.c [new file with mode: 0644]
states.c [deleted file]
symbols.c [deleted file]
syntax.c [deleted file]
tables.c [deleted file]
text.c [deleted file]
veneer.c [deleted file]
verbs.c [deleted file]
version.sh [new file with mode: 0755]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..d7162af
--- /dev/null
@@ -0,0 +1,2 @@
+.gitattributes export-ignore  
+.gitignore export-ignore
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..07c7a21
--- /dev/null
@@ -0,0 +1,16 @@
+/Makefile
+/Makefile.in
+/aclocal.m4
+/autom4te.cache/
+/compile
+/config.log
+/config.status
+/configure
+/depcomp
+/install-sh
+/missing
+/src/*.o
+/src/.deps
+/src/Makefile
+/src/Makefile.in
+/src/inform
\ No newline at end of file
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..608c201
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,369 @@
+Installation Instructions
+*************************
+
+   Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
+Foundation, Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+   Briefly, after you have run autoreconf --install, the shell 
+command './configure && make && make install' should configure, build, 
+and install this package.  The following more-detailed instructions 
+are generic; see the 'README' file for instructions specific to this 
+package.  Some packages provide this 'INSTALL' file but do not 
+implement all of the features documented below.  The lack of an 
+optional feature in a given package is not necessarily a bug.  More 
+recommendations for GNU packages can be found in *note Makefile 
+Conventions: (standards)Makefile Conventions.
+
+   The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions.  Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+   It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring.  Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'.  You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+   The simplest way to compile this package is:
+
+  1. 'cd' to the directory containing the package's source code and type
+     './configure' to configure the package for your system.
+
+     Running 'configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type 'make' to compile the package.
+
+  3. Optionally, type 'make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type 'make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the 'make install' phase executed with root
+     privileges.
+
+  5. Optionally, type 'make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior 'make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing 'make clean'.  To also remove the
+     files that 'configure' created (so you can compile the package for
+     a different kind of computer), type 'make distclean'.  There is
+     also a 'make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type 'make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide 'make
+     distcheck', which can by used by developers to test that all other
+     targets like 'make install' and 'make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about.  Run './configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here is
+an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU 'make'.  'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script.  'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'.  This is known
+as a "VPATH" build.
+
+   With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc.  You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files.  Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'.  Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated.  The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation.  However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the 'DESTDIR' variable.  For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names.  The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+   Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System).  The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of 'make' will be.  For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX 'make' updates targets which have the same time stamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved.  Use GNU 'make' instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '<wchar.h>' header file.  The option '-nodtk' can be used as a
+workaround.  If GNU CC is not installed, it is therefore recommended to
+try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put '/usr/ucb' early in your 'PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'.  So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+   On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file 'config.sub' for the possible values of each field.  If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists.  Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to 'configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation.  Until the limitation is lifted, you can use this
+workaround:
+
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+   'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+     Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+     Print a summary of the options unique to this package's
+     'configure', and exit.  The 'short' variant lists options used only
+     in the top level, while the 'recursive' variant lists options also
+     present in any nested packages.
+
+'--version'
+'-V'
+     Print the version of Autoconf used to generate the 'configure'
+     script, and exit.
+
+'--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally 'config.cache'.  FILE defaults to '/dev/null' to
+     disable caching.
+
+'--config-cache'
+'-C'
+     Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to '/dev/null' (any error
+     messages will still be shown).
+
+'--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names:: for
+     more details, including other options available for fine-tuning the
+     installation locations.
+
+'--no-create'
+'-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+'configure' also accepts some other, not widely useful, options.  Run
+'configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..b73d721
--- /dev/null
@@ -0,0 +1,16 @@
+# 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
+# theFree 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/
+
+SUBDIRS = src
\ No newline at end of file
diff --git a/arrays.c b/arrays.c
deleted file mode 100644 (file)
index 93cc31e..0000000
--- a/arrays.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "arrays" :  Parses array declarations and constructs arrays from them;  */
-/*               likewise global variables, which are in some ways a         */
-/*               simpler form of the same thing.                             */
-/*                                                                           */
-/* 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"
-
-/* ------------------------------------------------------------------------- */
-/*   Arrays defined below:                                                   */
-/*                                                                           */
-/*    int    dynamic_array_area[]         Initial values for the bytes of    */
-/*                                        the dynamic array area             */
-/*    int32  global_initial_value[n]      The initialised value of the nth   */
-/*                                        global variable (counting 0 - 239) */
-/*                                                                           */
-/*   The "dynamic array area" is the Z-machine area holding the current      */
-/*   values of the global variables (in 240x2 = 480 bytes) followed by any   */
-/*   (dynamic) arrays which may be defined.  Owing to a poor choice of name  */
-/*   some years ago, this is also called the "static data area", which is    */
-/*   why the memory setting for its maximum extent is "MAX_STATIC_DATA".     */
-/*                                                                           */
-/*   In Glulx, that 240 is changed to MAX_GLOBAL_VAR_NUMBER, and we take     */
-/*   correspondingly more space for the globals. This *really* ought to be   */
-/*   split into two segments.                                                */
-/* ------------------------------------------------------------------------- */
-int     *dynamic_array_area;           /* See above                          */
-int32   *global_initial_value;
-
-int no_globals;                        /* Number of global variables used
-                                          by the programmer (Inform itself
-                                          uses the top seven -- but these do
-                                          not count)                         */
-                                       /* In Glulx, Inform uses the bottom 
-                                          ten.                               */
-
-int dynamic_array_area_size;           /* Size in bytes                      */
-
-int no_arrays;
-int32   *array_symbols;
-int     *array_sizes, *array_types;
-
-static int array_entry_size,           /* 1 for byte array, 2 for word array */
-           array_base;                 /* Offset in dynamic array area of the
-                                          array being constructed.  During the
-                                          same time, dynamic_array_area_size
-                                          is the offset of the initial entry
-                                          in the array: so for "table" and
-                                          "string" arrays, these numbers are
-                                          different (by 2 and 1 bytes resp)  */
-
-                                       /* In Glulx, of course, that will be
-                                          4 instead of 2.                    */
-
-extern void finish_array(int32 i)
-{
-    /*  Write the array size into the 0th byte/word of the array, if it's
-        a "table" or "string" array                                          */
-  if (!glulx_mode) {
-
-    if (array_base!=dynamic_array_area_size)
-    {   if (dynamic_array_area_size-array_base==2)
-        {   dynamic_array_area[array_base]   = i/256;
-            dynamic_array_area[array_base+1] = i%256;
-        }
-        else
-        {   if (i>=256)
-                error("A 'string' array can have at most 256 entries");
-            dynamic_array_area[array_base] = i;
-        }
-    }
-
-  }
-  else {
-    if (array_base!=dynamic_array_area_size)
-    {   if (dynamic_array_area_size-array_base==4)
-        {   
-            dynamic_array_area[array_base]   = (i >> 24) & 0xFF;
-            dynamic_array_area[array_base+1] = (i >> 16) & 0xFF;
-            dynamic_array_area[array_base+2] = (i >> 8) & 0xFF;
-            dynamic_array_area[array_base+3] = (i) & 0xFF;
-        }
-        else
-        {   if (i>=256)
-                error("A 'string' array can have at most 256 entries");
-            dynamic_array_area[array_base] = i;
-        }
-    }
-    
-  }
-
-  /*  Move on the dynamic array size so that it now points to the next
-      available free space                                                   */
-
-  dynamic_array_area_size += i*array_entry_size;
-
-}
-
-extern void array_entry(int32 i, assembly_operand VAL)
-{
-  if (!glulx_mode) {
-    /*  Array entry i (initial entry has i=0) is set to Z-machine value j    */
-
-    if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
-        memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
-
-    if (array_entry_size==1)
-    {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value)%256;
-
-        if (VAL.marker != 0)
-           error("Entries in byte arrays and strings must be known constants");
-
-        /*  If the entry is too large for a byte array, issue a warning
-            and truncate the value                                           */
-        else
-        if (VAL.value >= 256)
-            warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
-    }
-    else
-    {   dynamic_array_area[dynamic_array_area_size + 2*i]   = (VAL.value)/256;
-        dynamic_array_area[dynamic_array_area_size + 2*i+1] = (VAL.value)%256;
-        if (VAL.marker != 0)
-            backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA,
-                dynamic_array_area_size + 2*i);
-    }
-  }
-  else {
-    /*  Array entry i (initial entry has i=0) is set to value j              */
-
-    if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
-        memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
-
-    if (array_entry_size==1)
-    {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value) & 0xFF;
-
-        if (VAL.marker != 0)
-           error("Entries in byte arrays and strings must be known constants");
-
-        /*  If the entry is too large for a byte array, issue a warning
-            and truncate the value                                           */
-        else
-        if (VAL.value >= 256)
-            warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
-    }
-    else if (array_entry_size==4)
-    {   dynamic_array_area[dynamic_array_area_size + 4*i]   = (VAL.value >> 24) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+1] = (VAL.value >> 16) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+2] = (VAL.value >> 8) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+3] = (VAL.value) & 0xFF;
-        if (VAL.marker != 0)
-            backpatch_zmachine(VAL.marker, ARRAY_ZA,
-                dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES + 4*i);
-    }
-    else
-    {
-        error("Somehow created an array of shorts");
-    }
-  }
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Global and Array directives.                                            */
-/*                                                                           */
-/*      Global <variablename> |                                              */
-/*                            | = <value>                                    */
-/*                            | <array specification>                        */
-/*                                                                           */
-/*      Array <arrayname> <array specification>                              */
-/*                                                                           */
-/*   where an array specification is:                                        */
-/*                                                                           */
-/*      | ->       |  <number-of-entries>                                    */
-/*      | -->      |  <entry-1> ... <entry-n>                                */
-/*      | string   |  [ <entry-1> [,] [;] <entry-2> ... <entry-n> ];         */
-/*      | table                                                              */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-extern void set_variable_value(int i, int32 v)
-{   global_initial_value[i]=v;
-}
-
-/*  There are four ways to initialise arrays:                                */
-
-#define UNSPECIFIED_AI  -1
-#define NULLS_AI        0
-#define DATA_AI         1
-#define ASCII_AI        2
-#define BRACKET_AI      3
-
-extern void make_global(int array_flag, int name_only)
-{
-    /*  array_flag is TRUE for an Array directive, FALSE for a Global;
-        name_only is only TRUE for parsing an imported variable name, so
-        array_flag is always FALSE in that case.                             */
-
-    int32 i;
-    int array_type, data_type;
-    assembly_operand AO;
-
-    int32 global_symbol;
-    const char *global_name;
-    debug_location_beginning beginning_debug_location =
-        get_token_location_beginning();
-
-    directive_keywords.enabled = FALSE;
-    get_next_token();
-    i = token_value;
-    global_symbol = i;
-    global_name = token_text;
-
-    if (!glulx_mode) {
-        if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T)
-            && (svals[i] >= LOWEST_SYSTEM_VAR_NUMBER))
-            goto RedefinitionOfSystemVar;
-    }
-    else {
-        if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T))
-            goto RedefinitionOfSystemVar;
-    }
-
-    if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
-    {   discard_token_location(beginning_debug_location);
-        if (array_flag)
-            ebf_error("new array name", token_text);
-        else ebf_error("new global variable name", token_text);
-        panic_mode_error_recovery(); return;
-    }
-
-    if ((!array_flag) && (sflags[i] & USED_SFLAG))
-        error_named("Variable must be defined before use:", token_text);
-
-    if (array_flag)
-    {   
-        if (!glulx_mode)
-            assign_symbol(i, dynamic_array_area_size, ARRAY_T);
-        else
-            assign_symbol(i, 
-                dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES, ARRAY_T);
-        if (no_arrays == MAX_ARRAYS)
-            memoryerror("MAX_ARRAYS", MAX_ARRAYS);
-        array_symbols[no_arrays] = i;
-    }
-    else
-    {   if (!glulx_mode && no_globals==233)
-        {   discard_token_location(beginning_debug_location);
-            error("All 233 global variables already declared");
-            panic_mode_error_recovery();
-            return;
-        }
-        if (glulx_mode && no_globals==MAX_GLOBAL_VARIABLES)
-        {   discard_token_location(beginning_debug_location);
-            memoryerror("MAX_GLOBAL_VARIABLES", MAX_GLOBAL_VARIABLES);
-            panic_mode_error_recovery();
-            return;
-        }
-
-        variable_tokens[MAX_LOCAL_VARIABLES+no_globals] = i;
-        assign_symbol(i, MAX_LOCAL_VARIABLES+no_globals, GLOBAL_VARIABLE_T);
-        variable_tokens[svals[i]] = i;
-
-        if (name_only) import_symbol(i);
-        else global_initial_value[no_globals++]=0;
-    }
-
-    directive_keywords.enabled = TRUE;
-
-    RedefinitionOfSystemVar:
-
-    if (name_only)
-    {   discard_token_location(beginning_debug_location);
-        return;
-    }
-
-    get_next_token();
-
-    if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-    {   if (array_flag)
-        {   discard_token_location(beginning_debug_location);
-            ebf_error("array definition", token_text);
-        }
-        put_token_back();
-        if (debugfile_switch && !array_flag)
-        {   debug_file_printf("<global-variable>");
-            debug_file_printf("<identifier>%s</identifier>", global_name);
-            debug_file_printf("<address>");
-            write_debug_global_backpatch(svals[global_symbol]);
-            debug_file_printf("</address>");
-            write_debug_locations
-                (get_token_location_end(beginning_debug_location));
-            debug_file_printf("</global-variable>");
-        }
-        return;
-    }
-
-    if (!array_flag)
-    {
-        if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
-        {   AO = parse_expression(CONSTANT_CONTEXT);
-            if (!glulx_mode) {
-                if (AO.marker != 0)
-                    backpatch_zmachine(AO.marker, DYNAMIC_ARRAY_ZA,
-                        2*(no_globals-1));
-            }
-            else {
-            if (AO.marker != 0)
-                backpatch_zmachine(AO.marker, GLOBALVAR_ZA,
-                4*(no_globals-1));
-            }
-            global_initial_value[no_globals-1] = AO.value;
-            if (debugfile_switch)
-            {   debug_file_printf("<global-variable>");
-                debug_file_printf("<identifier>%s</identifier>", global_name);
-                debug_file_printf("<address>");
-                write_debug_global_backpatch(svals[global_symbol]);
-                debug_file_printf("</address>");
-                write_debug_locations
-                    (get_token_location_end(beginning_debug_location));
-                debug_file_printf("</global-variable>");
-            }
-            return;
-        }
-
-        obsolete_warning("more modern to use 'Array', not 'Global'");
-
-        if (!glulx_mode) {
-            backpatch_zmachine(ARRAY_MV, DYNAMIC_ARRAY_ZA, 2*(no_globals-1));
-            global_initial_value[no_globals-1]
-                = dynamic_array_area_size+variables_offset;
-        }
-        else {
-            backpatch_zmachine(ARRAY_MV, GLOBALVAR_ZA, 4*(no_globals-1));
-            global_initial_value[no_globals-1]
-                = dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES;
-        }
-    }
-
-    array_type = BYTE_ARRAY; data_type = UNSPECIFIED_AI;
-
-         if ((!array_flag) &&
-             ((token_type==DIR_KEYWORD_TT)&&(token_value==DATA_DK)))
-                 data_type=NULLS_AI;
-    else if ((!array_flag) &&
-             ((token_type==DIR_KEYWORD_TT)&&(token_value==INITIAL_DK)))
-                 data_type=DATA_AI;
-    else if ((!array_flag) &&
-             ((token_type==DIR_KEYWORD_TT)&&(token_value==INITSTR_DK)))
-                 data_type=ASCII_AI;
-
-    else if ((token_type==SEP_TT)&&(token_value==ARROW_SEP))
-             array_type = BYTE_ARRAY;
-    else if ((token_type==SEP_TT)&&(token_value==DARROW_SEP))
-             array_type = WORD_ARRAY;
-    else if ((token_type==DIR_KEYWORD_TT)&&(token_value==STRING_DK))
-             array_type = STRING_ARRAY;
-    else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TABLE_DK))
-             array_type = TABLE_ARRAY;
-    else if ((token_type==DIR_KEYWORD_TT)&&(token_value==BUFFER_DK))
-             array_type = BUFFER_ARRAY;
-    else
-    {   discard_token_location(beginning_debug_location);
-        if (array_flag)
-            ebf_error
-              ("'->', '-->', 'string', 'table' or 'buffer'", token_text);
-        else
-            ebf_error
-              ("'=', '->', '-->', 'string', 'table' or 'buffer'", token_text);
-        panic_mode_error_recovery();
-        return;
-    }
-
-    array_entry_size=1;
-    if ((array_type==WORD_ARRAY) || (array_type==TABLE_ARRAY))
-        array_entry_size=WORDSIZE;
-
-    get_next_token();
-    if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-    {   discard_token_location(beginning_debug_location);
-        error("No array size or initial values given");
-        put_token_back();
-        return;
-    }
-
-    switch(data_type)
-    {   case UNSPECIFIED_AI:
-            if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
-                data_type = BRACKET_AI;
-            else
-            {   data_type = NULLS_AI;
-                if (token_type == DQ_TT) data_type = ASCII_AI;
-                get_next_token();
-                if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-                    data_type = DATA_AI;
-                put_token_back();
-                put_token_back();
-            }
-            break;
-        case NULLS_AI: obsolete_warning("use '->' instead of 'data'"); break;
-        case DATA_AI:  obsolete_warning("use '->' instead of 'initial'"); break;
-        case ASCII_AI: obsolete_warning("use '->' instead of 'initstr'"); break;
-    }
-
-    array_base = dynamic_array_area_size;
-
-    /*  Leave room to write the array size in later, if string/table array   */
-
-    if ((array_type==STRING_ARRAY) || (array_type==TABLE_ARRAY))
-        dynamic_array_area_size += array_entry_size;
-    if (array_type==BUFFER_ARRAY)
-        dynamic_array_area_size += WORDSIZE;
-    array_types[no_arrays] = array_type;
-
-    switch(data_type)
-    {
-        case NULLS_AI:
-
-            AO = parse_expression(CONSTANT_CONTEXT);
-
-            CalculatedArraySize:
-
-            if (module_switch && (AO.marker != 0))
-            {   error("Array sizes must be known now, not externally defined");
-                break;
-            }
-
-            if (!glulx_mode) {
-                if ((AO.value <= 0) || (AO.value >= 32768))
-                {   error("An array must have between 1 and 32767 entries");
-                    AO.value = 1;
-                }
-            }
-            else {
-                if (AO.value <= 0 || (AO.value & 0x80000000))
-                {   error("An array may not have 0 or fewer entries");
-                    AO.value = 1;
-                }
-            }
-
-            {   for (i=0; i<AO.value; i++) array_entry(i, zero_operand);
-            }
-            break;
-
-        case DATA_AI:
-
-            /*  In this case the array is initialised to the sequence of
-                constant values supplied on the same line                    */
-
-            i=0;
-            do
-            {   get_next_token();
-                if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-                    break;
-
-                if ((token_type == SEP_TT)
-                    && ((token_value == OPEN_SQUARE_SEP)
-                        || (token_value == CLOSE_SQUARE_SEP)))
-                {   discard_token_location(beginning_debug_location);
-                    error("Missing ';' to end the initial array values "
-                          "before \"[\" or \"]\"");
-                    return;
-                }
-                put_token_back();
-
-                AO = parse_expression(ARRAY_CONTEXT);
-
-                if (i == 0)
-                {   get_next_token();
-                    put_token_back();
-                    if ((token_type == SEP_TT)
-                        && (token_value == SEMICOLON_SEP))
-                    {   data_type = NULLS_AI;
-                        goto CalculatedArraySize;
-                    }
-                }
-
-                array_entry(i, AO);
-                i++;
-            } while (TRUE);
-            put_token_back();
-            break;
-
-        case ASCII_AI:
-
-            /*  In this case the array is initialised to the ASCII values of
-                the characters of a given "quoted string"                    */
-
-            get_next_token();
-            if (token_type != DQ_TT)
-            {   ebf_error("literal text in double-quotes", token_text);
-                token_text = "error";
-            }
-
-            {   assembly_operand chars;
-
-                int j;
-                INITAO(&chars);
-                for (i=0,j=0; token_text[j]!=0; i++,j+=textual_form_length)
-                {
-                    int32 unicode; int zscii;
-                    unicode = text_to_unicode(token_text+j);
-                    if (glulx_mode)
-                    {
-                        if (array_entry_size == 1 && (unicode < 0 || unicode >= 256))
-                        {
-                            error("Unicode characters beyond Latin-1 cannot be used in a byte array");
-                        }
-                        else
-                        {
-                            chars.value = unicode;
-                        }
-                    }
-                    else  /* Z-code */
-                    {                          
-                        zscii = unicode_to_zscii(unicode);
-                        if ((zscii != 5) && (zscii < 0x100)) chars.value = zscii;
-                        else
-                        {   unicode_char_error("Character can only be used if declared in \
-advance as part of 'Zcharacter table':", unicode);
-                            chars.value = '?';
-                        }
-                    }
-                    chars.marker = 0;
-                    set_constant_ot(&chars);
-                    array_entry(i, chars);
-                }
-            }
-            break;
-
-        case BRACKET_AI:
-
-            /*  In this case the array is initialised to the sequence of
-                constant values given over a whole range of compiler-lines,
-                between square brackets [ and ]                              */
-
-            i = 0;
-            while (TRUE)
-            {   get_next_token();
-                if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-                    continue;
-                if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP))
-                    break;
-                if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
-                {   /*  Minimal error recovery: we assume that a ] has
-                        been missed, and the programmer is now starting
-                        a new routine                                        */
-
-                    ebf_error("']'", token_text);
-                    put_token_back(); break;
-                }
-                put_token_back();
-                array_entry(i, parse_expression(ARRAY_CONTEXT));
-                i++;
-            }
-    }
-
-    finish_array(i);
-
-    if (debugfile_switch)
-    {   debug_file_printf("<array>");
-        debug_file_printf("<identifier>%s</identifier>", global_name);
-        debug_file_printf("<value>");
-        write_debug_array_backpatch(svals[global_symbol]);
-        debug_file_printf("</value>");
-        debug_file_printf
-            ("<byte-count>%d</byte-count>",
-             dynamic_array_area_size - array_base);
-        debug_file_printf
-            ("<bytes-per-element>%d</bytes-per-element>",
-             array_entry_size);
-        debug_file_printf
-            ("<zeroth-element-holds-length>%s</zeroth-element-holds-length>",
-             (array_type == STRING_ARRAY || array_type == TABLE_ARRAY) ?
-                 "true" : "false");
-        get_next_token();
-        write_debug_locations(get_token_location_end(beginning_debug_location));
-        put_token_back();
-        debug_file_printf("</array>");
-    }
-
-    if ((array_type==BYTE_ARRAY) || (array_type==WORD_ARRAY)) i--;
-    if (array_type==BUFFER_ARRAY) i+=WORDSIZE-1;
-    array_sizes[no_arrays++] = i;
-}
-
-extern int32 begin_table_array(void)
-{
-    /*  The "box" statement needs to be able to construct (static) table
-        arrays of strings like this                                          */
-
-    array_base = dynamic_array_area_size;
-    array_entry_size = WORDSIZE;
-
-    /*  Leave room to write the array size in later                          */
-
-    dynamic_array_area_size += array_entry_size;
-
-    if (!glulx_mode)
-        return array_base;
-    else
-        return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES;
-}
-
-extern int32 begin_word_array(void)
-{
-    /*  The "random(a, b, ...)" function needs to be able to construct
-        (static) word arrays like this                                       */
-
-    array_base = dynamic_array_area_size;
-    array_entry_size = WORDSIZE;
-
-    if (!glulx_mode)
-        return array_base;
-    else
-        return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES;
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_arrays_vars(void)
-{   dynamic_array_area = NULL;
-    global_initial_value = NULL;
-    array_sizes = NULL; array_symbols = NULL; array_types = NULL;
-}
-
-extern void arrays_begin_pass(void)
-{   no_arrays = 0; 
-    if (!glulx_mode)
-        no_globals=0; 
-    else
-        no_globals=11;
-    dynamic_array_area_size = WORDSIZE * MAX_GLOBAL_VARIABLES;
-}
-
-extern void arrays_allocate_arrays(void)
-{   dynamic_array_area = my_calloc(sizeof(int), MAX_STATIC_DATA, 
-        "static data");
-    array_sizes = my_calloc(sizeof(int), MAX_ARRAYS, "array sizes");
-    array_types = my_calloc(sizeof(int), MAX_ARRAYS, "array types");
-    array_symbols = my_calloc(sizeof(int32), MAX_ARRAYS, "array symbols");
-    global_initial_value = my_calloc(sizeof(int32), MAX_GLOBAL_VARIABLES, 
-        "global values");
-}
-
-extern void arrays_free_arrays(void)
-{   my_free(&dynamic_array_area, "static data");
-    my_free(&global_initial_value, "global values");
-    my_free(&array_sizes, "array sizes");
-    my_free(&array_types, "array sizes");
-    my_free(&array_symbols, "array sizes");
-}
-
-/* ========================================================================= */
diff --git a/asm.c b/asm.c
deleted file mode 100644 (file)
index a5444fd..0000000
--- a/asm.c
+++ /dev/null
@@ -1,3188 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "asm" : The Inform assembler                                            */
-/*                                                                           */
-/* 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"
-
-uchar *zcode_holding_area;         /* Area holding code yet to be transferred
-                                      to either zcode_area or temp file no 1 */
-uchar *zcode_markers;              /* Bytes holding marker values for this
-                                      code                                   */
-static int zcode_ha_size;          /* Number of bytes in holding area        */
-
-memory_block zcode_area;           /* Block to hold assembled code (if
-                                      temporary files are not being used)    */
-
-int32 zmachine_pc;                 /* PC position of assembly (byte offset
-                                      from start of Z-code area)             */
-
-int32 no_instructions;             /* Number of instructions assembled       */
-int execution_never_reaches_here,  /* TRUE if the current PC value in the
-                                      code area cannot be reached: e.g. if
-                                      the previous instruction was a "quit"
-                                      opcode and no label is set to here     */
-    next_label,                    /* Used to count the labels created all
-                                      over Inform in current routine, from 0 */
-    next_sequence_point;           /* Likewise, for sequence points          */
-int no_sequence_points;            /* Kept for statistics purposes only      */
-
-static int label_moved_error_already_given;
-                                   /* When one label has moved, all subsequent
-                                      ones probably have too, and this flag
-                                      suppresses the runaway chain of error
-                                      messages which would otherwise result  */
-
-int  sequence_point_follows;       /* Will the next instruction assembled    */
-                                   /* be at a sequence point in the routine? */
-
-int uses_unicode_features;         /* Makes use of Glulx Unicode (3.0)
-                                      features?                              */
-int uses_memheap_features;         /* Makes use of Glulx mem/heap (3.1)
-                                      features?                              */
-int uses_acceleration_features;    /* Makes use of Glulx acceleration (3.1.1)
-                                      features?                              */
-int uses_float_features;           /* Makes use of Glulx floating-point (3.1.2)
-                                      features?                              */
-
-debug_location statement_debug_location;
-                                   /* Location of current statement          */
-
-
-int32 *variable_tokens;            /* The allocated size is 
-                                      (MAX_LOCAL_VARIABLES +
-                                      MAX_GLOBAL_VARIABLES). The entries 
-                                      MAX_LOCAL_VARIABLES and up give the 
-                                      symbol table index for the names of 
-                                      the global variables                   */
-int *variable_usage;               /* TRUE if referred to, FALSE otherwise   */
-
-assembly_instruction AI;           /* A structure used to hold the full
-                                      specification of a single Z-code
-                                      instruction: effectively this is the
-                                      input to the routine
-                                      assemble_instruction()                 */
-
-static char opcode_syntax_string[128];  /*  Text buffer holding the correct
-                                      syntax for an opcode: used to produce
-                                      helpful assembler error messages       */
-
-static int routine_symbol;         /* The symbol index of the routine currently
-                                      being compiled */
-static char *routine_name;         /* The name of the routine currently being
-                                      compiled                               */
-static int routine_locals;         /* The number of local variables used by
-                                      the routine currently being compiled   */
-
-static int32 routine_start_pc;
-
-int32 *named_routine_symbols;
-
-static void transfer_routine_z(void);
-static void transfer_routine_g(void);
-
-/* ------------------------------------------------------------------------- */
-/*   Label data                                                              */
-/* ------------------------------------------------------------------------- */
-
-static int first_label, last_label;
-static int32 *label_offsets;       /* Double-linked list of label offsets    */
-static int   *label_next,          /* (i.e. zmachine_pc values) in PC order  */
-             *label_prev;
-static int32 *label_symbols;       /* Symbol numbers if defined in source    */
-
-static int   *sequence_point_labels;
-                                   /* Label numbers for each                 */
-static debug_location *sequence_point_locations;
-                                   /* Source code references for each        */
-                                   /* (used for making debugging file)       */
-
-static void set_label_offset(int label, int32 offset)
-{
-    if (label >= MAX_LABELS) memoryerror("MAX_LABELS", MAX_LABELS);
-
-    label_offsets[label] = offset;
-    if (last_label == -1)
-    {   label_prev[label] = -1;
-        first_label = label;
-    }
-    else
-    {   label_prev[label] = last_label;
-        label_next[last_label] = label;
-    }
-    last_label = label;
-    label_next[label] = -1;
-    label_symbols[label] = -1;
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Useful tool for building operands                                       */
-/* ------------------------------------------------------------------------- */
-
-extern void set_constant_ot(assembly_operand *AO)
-{
-  if (!glulx_mode) {
-    if (AO->value >= 0 && AO->value <= 255)
-      AO->type = SHORT_CONSTANT_OT;
-    else
-      AO->type = LONG_CONSTANT_OT;
-  }
-  else {
-    if (AO->value == 0)
-      AO->type = ZEROCONSTANT_OT;
-    else if (AO->value >= -0x80 && AO->value < 0x80)
-      AO->type = BYTECONSTANT_OT;
-    else if (AO->value >= -0x8000 && AO->value < 0x8000) 
-      AO->type = HALFCONSTANT_OT;
-    else
-      AO->type = CONSTANT_OT;
-  }
-}
-
-extern int is_constant_ot(int otval)
-{
-  if (!glulx_mode) {
-    return ((otval == LONG_CONSTANT_OT) 
-      || (otval == SHORT_CONSTANT_OT));
-  }
-  else {
-    return ((otval == CONSTANT_OT)
-      || (otval == HALFCONSTANT_OT)
-      || (otval == BYTECONSTANT_OT)
-      || (otval == ZEROCONSTANT_OT));
-  }
-}
-
-extern int is_variable_ot(int otval)
-{
-  if (!glulx_mode) {
-    return (otval == VARIABLE_OT);
-  }
-  else {
-    return ((otval == LOCALVAR_OT)
-      || (otval == GLOBALVAR_OT));
-  }
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Used in printing assembly traces                                        */
-/* ------------------------------------------------------------------------- */
-
-extern char *variable_name(int32 i)
-{
-    if (i==0) return("sp");
-    if (i<MAX_LOCAL_VARIABLES) return local_variable_texts[i-1];
-
-    if (!glulx_mode) {
-      if (i==255) return("TEMP1");
-      if (i==254) return("TEMP2");
-      if (i==253) return("TEMP3");
-      if (i==252) return("TEMP4");
-      if (i==251) return("self");
-      if (i==250) return("sender");
-      if (i==249) return("sw__var");
-      if (i >= 256 && i < 286)
-      {   if (i - 256 < NUMBER_SYSTEM_FUNCTIONS) return system_functions.keywords[i - 256];
-          return "<unnamed system function>";
-      }
-    }
-    else {
-      switch (i - MAX_LOCAL_VARIABLES) {
-      case 0: return "temp_global";
-      case 1: return "temp__global2";
-      case 2: return "temp__global3";
-      case 3: return "temp__global4";
-      case 4: return "self";
-      case 5: return "sender";
-      case 6: return "sw__var";
-      case 7: return "sys__glob0";
-      case 8: return "sys__glob1";
-      case 9: return "sys__glob2";
-      case 10: return "sys_statusline_flag";
-      }
-    }
-
-    return ((char *) symbs[variable_tokens[i]]);
-}
-
-static void print_operand_z(assembly_operand o)
-{   switch(o.type)
-    {   case EXPRESSION_OT: printf("expr_"); break;
-        case LONG_CONSTANT_OT: printf("long_"); break;
-        case SHORT_CONSTANT_OT: printf("short_"); break;
-        case VARIABLE_OT:
-             if (o.value==0) { printf("sp"); return; }
-             printf("%s", variable_name(o.value)); return;
-        case OMITTED_OT: printf("<no value>"); return;
-    }
-    printf("%d", o.value);
-}
-
-static void print_operand_g(assembly_operand o)
-{
-  switch (o.type) {
-  case EXPRESSION_OT: printf("expr_"); break;
-  case CONSTANT_OT: printf("long_"); break;
-  case HALFCONSTANT_OT: printf("short_"); break;
-  case BYTECONSTANT_OT: printf("byte_"); break;
-  case ZEROCONSTANT_OT: printf("zero_"); return;
-  case DEREFERENCE_OT: printf("*"); break;
-  case GLOBALVAR_OT: 
-    printf("%s (global_%d)", variable_name(o.value), o.value); 
-    return;
-  case LOCALVAR_OT: 
-    if (o.value == 0)
-      printf("stackptr"); 
-    else
-      printf("%s (local_%d)", variable_name(o.value), o.value-1); 
-    return;
-  case SYSFUN_OT:
-    if (o.value >= 0 && o.value < NUMBER_SYSTEM_FUNCTIONS)
-      printf("%s", system_functions.keywords[o.value]);
-    else
-      printf("<unnamed system function>");
-    return;
-  case OMITTED_OT: printf("<no value>"); return;
-  default: printf("???_"); break; 
-  }
-  printf("%d", o.value);
-}
-
-extern void print_operand(assembly_operand o)
-{
-  if (!glulx_mode)
-    print_operand_z(o);
-  else
-    print_operand_g(o);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Writing bytes to the code area                                          */
-/* ------------------------------------------------------------------------- */
-
-static void byteout(int32 i, int mv)
-{   if (zcode_ha_size >= MAX_ZCODE_SIZE)
-        memoryerror("MAX_ZCODE_SIZE",MAX_ZCODE_SIZE);
-    zcode_markers[zcode_ha_size] = (uchar) mv;
-    zcode_holding_area[zcode_ha_size++] = (uchar) i;
-    zmachine_pc++;
-}
-
-/* ------------------------------------------------------------------------- */
-/*   A database of the 115 canonical Infocom opcodes in Versions 3 to 6      */
-/*   And of the however-many-there-are Glulx opcode                          */
-/* ------------------------------------------------------------------------- */
-
-typedef struct opcodez
-{   uchar *name;      /* Lower case standard name */
-    int version1;     /* Valid from this version number... */
-    int version2;     /* ...until this one (or forever if this is 0) */
-    int extension;    /* In later versions, see this line in extension table:
-                         if -1, the opcode is illegal in later versions */
-    int code;         /* Opcode number within its operand-number block */
-    int flags;        /* Flags (see below) */
-    int op_rules;     /* Any unusual operand rule applying (see below) */
-    int flags2_set;   /* If not zero, set this bit in Flags 2 in the header
-                         of any game using the opcode */
-    int no;           /* Number of operands (see below) */
-} opcodez;
-
-typedef struct opcodeg
-{   uchar *name;      /* Lower case standard name */
-    int32 code;       /* Opcode number */
-    int flags;        /* Flags (see below) */
-    int op_rules;     /* Any unusual operand rule applying (see below) */
-    int no;           /* Number of operands */
-} opcodeg;
-
-    /* Flags which can be set */
-
-#define St      1     /* Store */
-#define Br      2     /* Branch */
-#define Rf      4     /* "Return flag": execution never continues after this
-                         opcode (e.g., is a return or unconditional jump) */
-#define St2 8     /* Store2 (second-to-last operand is store (Glulx)) */
-
-    /* Codes for any unusual operand assembly rules */
-
-    /* Z-code: */
-
-#define VARIAB   1    /* First operand expected to be a variable name and
-                         assembled to a short constant: the variable number */
-#define TEXT     2    /* One text operand, to be Z-encoded into the program */
-#define LABEL    3    /* One operand, a label, given as long constant offset */
-#define CALL     4    /* First operand is name of a routine, to be assembled
-                         as long constant (the routine's packed address):
-                         as if the name were prefixed by #r$ */
-
-    /* Glulx: (bit flags for Glulx VM features) */
-
-#define GOP_Unicode      1   /* uses_unicode_features */
-#define GOP_MemHeap      2   /* uses_memheap_features */
-#define GOP_Acceleration 4   /* uses_acceleration_features */
-#define GOP_Float        8   /* uses_float_features */
-
-    /* Codes for the number of operands */
-
-#define TWO      1    /* 2 (with certain types of operand, compiled as VAR) */
-#define VAR      2    /* 0 to 4 */
-#define VAR_LONG 3    /* 0 to 8 */
-#define ONE      4    /* 1 */
-#define ZERO     5    /* 0 */
-#define EXT      6    /* Extended opcode set VAR: 0 to 4 */
-#define EXT_LONG 7    /* Extended: 0 to 8 (not used by the canonical opcodes) */
-
-static opcodez opcodes_table_z[] =
-{
-    /* Opcodes introduced in Version 3 */
-
-/* 0 */ { (uchar *) "je",              3, 0, -1, 0x01,     Br,      0, 0, TWO },
-/* 1 */ { (uchar *) "jl",              3, 0, -1, 0x02,     Br,      0, 0, TWO },
-/* 2 */ { (uchar *) "jg",              3, 0, -1, 0x03,     Br,      0, 0, TWO },
-/* 3 */ { (uchar *) "dec_chk",         3, 0, -1, 0x04,     Br, VARIAB, 0, TWO },
-/* 4 */ { (uchar *) "inc_chk",         3, 0, -1, 0x05,     Br, VARIAB, 0, TWO },
-/* 5 */ { (uchar *) "jin",             3, 0, -1, 0x06,     Br,      0, 0, TWO },
-/* 6 */ { (uchar *) "test",            3, 0, -1, 0x07,     Br,      0, 0, TWO },
-/* 7 */ { (uchar *) "or",              3, 0, -1, 0x08,     St,      0, 0, TWO },
-/* 8 */ { (uchar *) "and",             3, 0, -1, 0x09,     St,      0, 0, TWO },
-/* 9 */ { (uchar *) "test_attr",       3, 0, -1, 0x0A,     Br,      0, 0, TWO },
-/* 10 */ {(uchar *) "set_attr",        3, 0, -1, 0x0B,      0,      0, 0, TWO },
-/* 11 */ {(uchar *) "clear_attr",      3, 0, -1, 0x0C,      0,      0, 0, TWO },
-/* 12 */ {(uchar *) "store",           3, 0, -1, 0x0D,      0, VARIAB, 0, TWO },
-/* 13 */ {(uchar *) "insert_obj",      3, 0, -1, 0x0E,      0,      0, 0, TWO },
-/* 14 */ {(uchar *) "loadw",           3, 0, -1, 0x0F,     St,      0, 0, TWO },
-/* 15 */ {(uchar *) "loadb",           3, 0, -1, 0x10,     St,      0, 0, TWO },
-/* 16 */ {(uchar *) "get_prop",        3, 0, -1, 0x11,     St,      0, 0, TWO },
-/* 17 */ {(uchar *) "get_prop_addr",   3, 0, -1, 0x12,     St,      0, 0, TWO },
-/* 18 */ {(uchar *) "get_next_prop",   3, 0, -1, 0x13,     St,      0, 0, TWO },
-/* 19 */ {(uchar *) "add",             3, 0, -1, 0x14,     St,      0, 0, TWO },
-/* 20 */ {(uchar *) "sub",             3, 0, -1, 0x15,     St,      0, 0, TWO },
-/* 21 */ {(uchar *) "mul",             3, 0, -1, 0x16,     St,      0, 0, TWO },
-/* 22 */ {(uchar *) "div",             3, 0, -1, 0x17,     St,      0, 0, TWO },
-/* 23 */ {(uchar *) "mod",             3, 0, -1, 0x18,     St,      0, 0, TWO },
-/* 24 */ {(uchar *) "call",            3, 0, -1, 0x20,     St,   CALL, 0, VAR },
-/* 25 */ {(uchar *) "storew",          3, 0, -1, 0x21,      0,      0, 0, VAR },
-/* 26 */ {(uchar *) "storeb",          3, 0, -1, 0x22,      0,      0, 0, VAR },
-/* 27 */ {(uchar *) "put_prop",        3, 0, -1, 0x23,      0,      0, 0, VAR },
-            /* This is the version of "read" called "sread" internally: */
-/* 28 */ {(uchar *) "read",            3, 0, -1, 0x24,      0,      0, 0, VAR },
-/* 29 */ {(uchar *) "print_char",      3, 0, -1, 0x25,      0,      0, 0, VAR },
-/* 30 */ {(uchar *) "print_num",       3, 0, -1, 0x26,      0,      0, 0, VAR },
-/* 31 */ {(uchar *) "random",          3, 0, -1, 0x27,     St,      0, 0, VAR },
-/* 32 */ {(uchar *) "push",            3, 0, -1, 0x28,      0,      0, 0, VAR },
-/* 33 */ {(uchar *) "pull",            3, 5,  6, 0x29,      0, VARIAB, 0, VAR },
-/* 34 */ {(uchar *) "split_window",    3, 0, -1, 0x2A,      0,      0, 0, VAR },
-/* 35 */ {(uchar *) "set_window",      3, 0, -1, 0x2B,      0,      0, 0, VAR },
-/* 36 */ {(uchar *) "output_stream",   3, 0, -1, 0x33,      0,      0, 0, VAR },
-/* 37 */ {(uchar *) "input_stream",    3, 0, -1, 0x34,      0,      0, 0, VAR },
-/* 38 */ {(uchar *) "sound_effect",    3, 0, -1, 0x35,      0,      0, 7, VAR },
-/* 39 */ {(uchar *) "jz",              3, 0, -1, 0x00,     Br,      0, 0, ONE },
-/* 40 */ {(uchar *) "get_sibling",     3, 0, -1, 0x01,  St+Br,      0, 0, ONE },
-/* 41 */ {(uchar *) "get_child",       3, 0, -1, 0x02,  St+Br,      0, 0, ONE },
-/* 42 */ {(uchar *) "get_parent",      3, 0, -1, 0x03,     St,      0, 0, ONE },
-/* 43 */ {(uchar *) "get_prop_len",    3, 0, -1, 0x04,     St,      0, 0, ONE },
-/* 44 */ {(uchar *) "inc",             3, 0, -1, 0x05,      0, VARIAB, 0, ONE },
-/* 45 */ {(uchar *) "dec",             3, 0, -1, 0x06,      0, VARIAB, 0, ONE },
-/* 46 */ {(uchar *) "print_addr",      3, 0, -1, 0x07,      0,      0, 0, ONE },
-/* 47 */ {(uchar *) "remove_obj",      3, 0, -1, 0x09,      0,      0, 0, ONE },
-/* 48 */ {(uchar *) "print_obj",       3, 0, -1, 0x0A,      0,      0, 0, ONE },
-/* 49 */ {(uchar *) "ret",             3, 0, -1, 0x0B,     Rf,      0, 0, ONE },
-/* 50 */ {(uchar *) "jump",            3, 0, -1, 0x0C,     Rf,  LABEL, 0, ONE },
-/* 51 */ {(uchar *) "print_paddr",     3, 0, -1, 0x0D,      0,      0, 0, ONE },
-/* 52 */ {(uchar *) "load",            3, 0, -1, 0x0E,     St, VARIAB, 0, ONE },
-/* 53 */ {(uchar *) "not",             3, 3,  0, 0x0F,     St,      0, 0, ONE },
-/* 54 */ {(uchar *) "rtrue",           3, 0, -1, 0x00,     Rf,      0, 0,ZERO },
-/* 55 */ {(uchar *) "rfalse",          3, 0, -1, 0x01,     Rf,      0, 0,ZERO },
-/* 56 */ {(uchar *) "print",           3, 0, -1, 0x02,      0,   TEXT, 0,ZERO },
-/* 57 */ {(uchar *) "print_ret",       3, 0, -1, 0x03,     Rf,   TEXT, 0,ZERO },
-/* 58 */ {(uchar *) "nop",             3, 0, -1, 0x04,      0,      0, 0,ZERO },
-/* 59 */ {(uchar *) "save",            3, 3,  1, 0x05,     Br,      0, 0,ZERO },
-/* 60 */ {(uchar *) "restore",         3, 3,  2, 0x06,     Br,      0, 0,ZERO },
-/* 61 */ {(uchar *) "restart",         3, 0, -1, 0x07,      0,      0, 0,ZERO },
-/* 62 */ {(uchar *) "ret_popped",      3, 0, -1, 0x08,     Rf,      0, 0,ZERO },
-/* 63 */ {(uchar *) "pop",             3, 4, -1, 0x09,      0,      0, 0,ZERO },
-/* 64 */ {(uchar *) "quit",            3, 0, -1, 0x0A,     Rf,      0, 0,ZERO },
-/* 65 */ {(uchar *) "new_line",        3, 0, -1, 0x0B,      0,      0, 0,ZERO },
-/* 66 */ {(uchar *) "show_status",     3, 3, -1, 0x0C,      0,      0, 0,ZERO },
-/* 67 */ {(uchar *) "verify",          3, 0, -1, 0x0D,     Br,      0, 0,ZERO },
-
-    /* Opcodes introduced in Version 4 */
-
-/* 68 */ {(uchar *) "call_2s",         4, 0, -1, 0x19,     St,   CALL, 0, TWO },
-/* 69 */ {(uchar *) "call_vs",         4, 0, -1, 0x20,     St,   CALL, 0, VAR },
-            /* This is the version of "read" called "aread" internally: */
-/* 70 */ {(uchar *) "read",            4, 0, -1, 0x24,     St,      0, 0, VAR },
-/* 71 */ {(uchar *) "call_vs2",        4, 0, -1, 0x2C,     St,   CALL, 0,
-                                                                     VAR_LONG },
-/* 72 */ {(uchar *) "erase_window",    4, 0, -1, 0x2D,      0,      0, 0, VAR },
-/* 73 */ {(uchar *) "erase_line",      4, 0, -1, 0x2E,      0,      0, 0, VAR },
-/* 74 */ {(uchar *) "set_cursor",      4, 0, -1, 0x2F,      0,      0, 0, VAR },
-/* 75 */ {(uchar *) "get_cursor",      4, 0, -1, 0x30,      0,      0, 0, VAR },
-/* 76 */ {(uchar *) "set_text_style",  4, 0, -1, 0x31,      0,      0, 0, VAR },
-/* 77 */ {(uchar *) "buffer_mode",     4, 0, -1, 0x32,      0,      0, 0, VAR },
-/* 78 */ {(uchar *) "read_char",       4, 0, -1, 0x36,     St,      0, 0, VAR },
-/* 79 */ {(uchar *) "scan_table",      4, 0, -1, 0x37,  St+Br,      0, 0, VAR },
-/* 80 */ {(uchar *) "call_1s",         4, 0, -1, 0x08,     St,   CALL, 0, ONE },
-
-    /* Opcodes introduced in Version 5 */
-
-/* 81 */ {(uchar *) "call_2n",         5, 0, -1, 0x1a,      0,   CALL, 0, TWO },
-/* 82 */ {(uchar *) "set_colour",      5, 0, -1, 0x1b,      0,      0, 6, TWO },
-/* 83 */ {(uchar *) "throw",           5, 0, -1, 0x1c,      0,      0, 0, TWO },
-/* 84 */ {(uchar *) "call_vn",         5, 0, -1, 0x39,      0,   CALL, 0, VAR },
-/* 85 */ {(uchar *) "call_vn2",        5, 0, -1, 0x3a,      0,   CALL, 0,
-                                                                     VAR_LONG },
-/* 86 */ {(uchar *) "tokenise",        5, 0, -1, 0x3b,      0,      0, 0, VAR },
-/* 87 */ {(uchar *) "encode_text",     5, 0, -1, 0x3c,      0,      0, 0, VAR },
-/* 88 */ {(uchar *) "copy_table",      5, 0, -1, 0x3d,      0,      0, 0, VAR },
-/* 89 */ {(uchar *) "print_table",     5, 0, -1, 0x3e,      0,      0, 0, VAR },
-/* 90 */ {(uchar *) "check_arg_count", 5, 0, -1, 0x3f,     Br,      0, 0, VAR },
-/* 91 */ {(uchar *) "call_1n",         5, 0, -1, 0x0F,      0,   CALL, 0, ONE },
-/* 92 */ {(uchar *) "catch",           5, 0, -1, 0x09,     St,      0, 0, ZERO },
-/* 93 */ {(uchar *) "piracy",          5, 0, -1, 0x0F,     Br,      0, 0, ZERO },
-/* 94 */ {(uchar *) "log_shift",       5, 0, -1, 0x02,     St,      0, 0, EXT },
-/* 95 */ {(uchar *) "art_shift",       5, 0, -1, 0x03,     St,      0, 0, EXT },
-/* 96 */ {(uchar *) "set_font",        5, 0, -1, 0x04,     St,      0, 0, EXT },
-/* 97 */ {(uchar *) "save_undo",       5, 0, -1, 0x09,     St,      0, 4, EXT },
-/* 98 */ {(uchar *) "restore_undo",    5, 0, -1, 0x0A,     St,      0, 4, EXT },
-
-    /* Opcodes introduced in Version 6 */
-
-/* 99 */  { (uchar *) "draw_picture",  6, 6, -1, 0x05,      0,      0, 3, EXT },
-/* 100 */ { (uchar *) "picture_data",  6, 6, -1, 0x06,     Br,      0, 3, EXT },
-/* 101 */ { (uchar *) "erase_picture", 6, 6, -1, 0x07,      0,      0, 3, EXT },
-/* 102 */ { (uchar *) "set_margins",   6, 6, -1, 0x08,      0,      0, 0, EXT },
-/* 103 */ { (uchar *) "move_window",   6, 6, -1, 0x10,      0,      0, 0, EXT },
-/* 104 */ { (uchar *) "window_size",   6, 6, -1, 0x11,      0,      0, 0, EXT },
-/* 105 */ { (uchar *) "window_style",  6, 6, -1, 0x12,      0,      0, 0, EXT },
-/* 106 */ { (uchar *) "get_wind_prop", 6, 6, -1, 0x13,     St,      0, 0, EXT },
-/* 107 */ { (uchar *) "scroll_window", 6, 6, -1, 0x14,      0,      0, 0, EXT },
-/* 108 */ { (uchar *) "pop_stack",     6, 6, -1, 0x15,      0,      0, 0, EXT },
-/* 109 */ { (uchar *) "read_mouse",    6, 6, -1, 0x16,      0,      0, 5, EXT },
-/* 110 */ { (uchar *) "mouse_window",  6, 6, -1, 0x17,      0,      0, 5, EXT },
-/* 111 */ { (uchar *) "push_stack",    6, 6, -1, 0x18,     Br,      0, 0, EXT },
-/* 112 */ { (uchar *) "put_wind_prop", 6, 6, -1, 0x19,      0,      0, 0, EXT },
-/* 113 */ { (uchar *) "print_form",    6, 6, -1, 0x1a,      0,      0, 0, EXT },
-/* 114 */ { (uchar *) "make_menu",     6, 6, -1, 0x1b,     Br,      0, 8, EXT },
-/* 115 */ { (uchar *) "picture_table", 6, 6, -1, 0x1c,      0,      0, 3, EXT },
-
-    /* Opcodes introduced in Z-Machine Specification Standard 1.0 */
-
-/* 116 */ { (uchar *) "print_unicode", 5, 0, -1, 0x0b,      0,      0, 0, EXT },
-/* 117 */ { (uchar *) "check_unicode", 5, 0, -1, 0x0c,     St,      0, 0, EXT }
-};
-
-    /* Subsequent forms for opcodes whose meaning changes with version */
-
-static opcodez extension_table_z[] =
-{
-/* 0 */ { (uchar *) "not",             4, 4,  3, 0x0F,     St,      0, 0, ONE },
-/* 1 */ { (uchar *) "save",            4, 4,  4, 0x05,     St,      0, 0,ZERO },
-/* 2 */ { (uchar *) "restore",         4, 4,  5, 0x06,     St,      0, 0,ZERO },
-/* 3 */ { (uchar *) "not",             5, 0, -1, 0x38,     St,      0, 0, VAR },
-/* 4 */ { (uchar *) "save",            5, 0, -1, 0x00,     St,      0, 0, EXT },
-/* 5 */ { (uchar *) "restore",         5, 0, -1, 0x01,     St,      0, 0, EXT },
-/* 6 */ { (uchar *) "pull",            6, 6, -1, 0x29,     St,      0, 0, VAR }
-};
-
-static opcodez invalid_opcode_z =
-        { (uchar *) "invalid",         0, 0, -1, 0xff,      0,      0, 0, ZERO};
-
-static opcodez custom_opcode_z;
-
-/* Note that this table assumes that all opcodes have at most two 
-   branch-label or store operands, and that if they exist, they are the
-   last operands. Glulx does not actually guarantee this. But it is
-   true for all opcodes in the current Glulx spec, so we will assume
-   it for now.
-
-   Also note that Inform can only compile branches to constant offsets,
-   even though the Glulx machine can handle stack or memory-loaded
-   operands in a branch instruction.
-*/
-
-static opcodeg opcodes_table_g[] = {
-  { (uchar *) "nop",        0x00,  0, 0, 0 },
-  { (uchar *) "add",        0x10, St, 0, 3 },
-  { (uchar *) "sub",        0x11, St, 0, 3 },
-  { (uchar *) "mul",        0x12, St, 0, 3 },
-  { (uchar *) "div",        0x13, St, 0, 3 },
-  { (uchar *) "mod",        0x14, St, 0, 3 },
-  { (uchar *) "neg",        0x15, St, 0, 2 },
-  { (uchar *) "bitand",     0x18, St, 0, 3 },
-  { (uchar *) "bitor",      0x19, St, 0, 3 },
-  { (uchar *) "bitxor",     0x1A, St, 0, 3 },
-  { (uchar *) "bitnot",     0x1B, St, 0, 2 },
-  { (uchar *) "shiftl",     0x1C, St, 0, 3 },
-  { (uchar *) "sshiftr",    0x1D, St, 0, 3 },
-  { (uchar *) "ushiftr",    0x1E, St, 0, 3 },
-  { (uchar *) "jump",       0x20, Br|Rf, 0, 1 },
-  { (uchar *) "jz",     0x22, Br, 0, 2 },
-  { (uchar *) "jnz",        0x23, Br, 0, 2 },
-  { (uchar *) "jeq",        0x24, Br, 0, 3 },
-  { (uchar *) "jne",        0x25, Br, 0, 3 },
-  { (uchar *) "jlt",        0x26, Br, 0, 3 },
-  { (uchar *) "jge",        0x27, Br, 0, 3 },
-  { (uchar *) "jgt",        0x28, Br, 0, 3 },
-  { (uchar *) "jle",        0x29, Br, 0, 3 },
-  { (uchar *) "jltu",       0x2A, Br, 0, 3 },
-  { (uchar *) "jgeu",       0x2B, Br, 0, 3 },
-  { (uchar *) "jgtu",       0x2C, Br, 0, 3 },
-  { (uchar *) "jleu",       0x2D, Br, 0, 3 },
-  { (uchar *) "call",       0x30, St, 0, 3 },
-  { (uchar *) "return",     0x31, Rf, 0, 1 },
-  { (uchar *) "catch",      0x32, Br|St, 0, 2 },
-  { (uchar *) "throw",      0x33, Rf, 0, 2 },
-  { (uchar *) "tailcall",   0x34, Rf, 0, 2 },
-  { (uchar *) "copy",       0x40, St, 0, 2 },
-  { (uchar *) "copys",      0x41, St, 0, 2 },
-  { (uchar *) "copyb",      0x42, St, 0, 2 },
-  { (uchar *) "sexs",       0x44, St, 0, 2 },
-  { (uchar *) "sexb",       0x45, St, 0, 2 },
-  { (uchar *) "aload",      0x48, St, 0, 3 },
-  { (uchar *) "aloads",     0x49, St, 0, 3 },
-  { (uchar *) "aloadb",     0x4A, St, 0, 3 },
-  { (uchar *) "aloadbit",   0x4B, St, 0, 3 },
-  { (uchar *) "astore",     0x4C,  0, 0, 3 },
-  { (uchar *) "astores",    0x4D,  0, 0, 3 },
-  { (uchar *) "astoreb",    0x4E,  0, 0, 3 },
-  { (uchar *) "astorebit",  0x4F,  0, 0, 3 },
-  { (uchar *) "stkcount",   0x50, St, 0, 1 },
-  { (uchar *) "stkpeek",    0x51, St, 0, 2 },
-  { (uchar *) "stkswap",    0x52,  0, 0, 0 },
-  { (uchar *) "stkroll",    0x53,  0, 0, 2 },
-  { (uchar *) "stkcopy",    0x54,  0, 0, 1 },
-  { (uchar *) "streamchar", 0x70,  0, 0, 1 },
-  { (uchar *) "streamnum",  0x71,  0, 0, 1 },
-  { (uchar *) "streamstr",  0x72,  0, 0, 1 },
-  { (uchar *) "gestalt",    0x0100, St, 0, 3 },
-  { (uchar *) "debugtrap",  0x0101, 0, 0, 1 },
-  { (uchar *) "getmemsize",     0x0102, St, 0, 1 },
-  { (uchar *) "setmemsize",     0x0103, St, 0, 2 },
-  { (uchar *) "jumpabs",    0x0104, Rf, 0, 1 },
-  { (uchar *) "random",     0x0110, St, 0, 2 },
-  { (uchar *) "setrandom",  0x0111,  0, 0, 1 },
-  { (uchar *) "quit",       0x0120, Rf, 0, 0 },
-  { (uchar *) "verify",     0x0121, St, 0, 1 },
-  { (uchar *) "restart",    0x0122,  0, 0, 0 },
-  { (uchar *) "save",       0x0123, St, 0, 2 },
-  { (uchar *) "restore",    0x0124, St, 0, 2 },
-  { (uchar *) "saveundo",   0x0125, St, 0, 1 },
-  { (uchar *) "restoreundo",    0x0126, St, 0, 1 },
-  { (uchar *) "protect",    0x0127,  0, 0, 2 },
-  { (uchar *) "glk",        0x0130, St, 0, 3 },
-  { (uchar *) "getstringtbl",   0x0140, St, 0, 1 },
-  { (uchar *) "setstringtbl",   0x0141, 0, 0, 1 },
-  { (uchar *) "getiosys",   0x0148, St|St2, 0, 2 },
-  { (uchar *) "setiosys",   0x0149, 0, 0, 2 },
-  { (uchar *) "linearsearch",   0x0150, St, 0, 8 },
-  { (uchar *) "binarysearch",   0x0151, St, 0, 8 },
-  { (uchar *) "linkedsearch",   0x0152, St, 0, 7 },
-  { (uchar *) "callf",      0x0160, St, 0, 2 },
-  { (uchar *) "callfi",     0x0161, St, 0, 3 },
-  { (uchar *) "callfii",    0x0162, St, 0, 4 },
-  { (uchar *) "callfiii",   0x0163, St, 0, 5 },
-  { (uchar *) "streamunichar", 0x73,  0, GOP_Unicode, 1 },
-  { (uchar *) "mzero",      0x170,  0, GOP_MemHeap, 2 },
-  { (uchar *) "mcopy",      0x171,  0, GOP_MemHeap, 3 },
-  { (uchar *) "malloc",     0x178,  St, GOP_MemHeap, 2 },
-  { (uchar *) "mfree",      0x179,  0, GOP_MemHeap, 1 },
-  { (uchar *) "accelfunc",  0x180,  0, GOP_Acceleration, 2 },
-  { (uchar *) "accelparam", 0x181,  0, GOP_Acceleration, 2 },
-  { (uchar *) "numtof",     0x190,  St, GOP_Float, 2 },
-  { (uchar *) "ftonumz",    0x191,  St, GOP_Float, 2 },
-  { (uchar *) "ftonumn",    0x192,  St, GOP_Float, 2 },
-  { (uchar *) "ceil",       0x198,  St, GOP_Float, 2 },
-  { (uchar *) "floor",      0x199,  St, GOP_Float, 2 },
-  { (uchar *) "fadd",       0x1A0,  St, GOP_Float, 3 },
-  { (uchar *) "fsub",       0x1A1,  St, GOP_Float, 3 },
-  { (uchar *) "fmul",       0x1A2,  St, GOP_Float, 3 },
-  { (uchar *) "fdiv",       0x1A3,  St, GOP_Float, 3 },
-  { (uchar *) "fmod",       0x1A4,  St|St2, GOP_Float, 4 },
-  { (uchar *) "sqrt",       0x1A8,  St, GOP_Float, 2 },
-  { (uchar *) "exp",        0x1A9,  St, GOP_Float, 2 },
-  { (uchar *) "log",        0x1AA,  St, GOP_Float, 2 },
-  { (uchar *) "pow",        0x1AB,  St, GOP_Float, 3 },
-  { (uchar *) "sin",        0x1B0,  St, GOP_Float, 2 },
-  { (uchar *) "cos",        0x1B1,  St, GOP_Float, 2 },
-  { (uchar *) "tan",        0x1B2,  St, GOP_Float, 2 },
-  { (uchar *) "asin",       0x1B3,  St, GOP_Float, 2 },
-  { (uchar *) "acos",       0x1B4,  St, GOP_Float, 2 },
-  { (uchar *) "atan",       0x1B5,  St, GOP_Float, 2 },
-  { (uchar *) "atan2",      0x1B6,  St, GOP_Float, 3 },
-  { (uchar *) "jfeq",       0x1C0,  Br, GOP_Float, 4 },
-  { (uchar *) "jfne",       0x1C1,  Br, GOP_Float, 4 },
-  { (uchar *) "jflt",       0x1C2,  Br, GOP_Float, 3 },
-  { (uchar *) "jfle",       0x1C3,  Br, GOP_Float, 3 },
-  { (uchar *) "jfgt",       0x1C4,  Br, GOP_Float, 3 },
-  { (uchar *) "jfge",       0x1C5,  Br, GOP_Float, 3 },
-  { (uchar *) "jisnan",     0x1C8,  Br, GOP_Float, 2 },
-  { (uchar *) "jisinf",     0x1C9,  Br, GOP_Float, 2 },
-};
-
-/* The opmacros table is used for fake opcodes. The opcode numbers are
-   ignored; this table is only used for argument parsing. */
-static opcodeg opmacros_table_g[] = {
-  { (uchar *) "pull", 0, St, 0, 1 },
-  { (uchar *) "push", 0,  0, 0, 1 },
-};
-
-static opcodeg custom_opcode_g;
-
-static opcodez internal_number_to_opcode_z(int32 i)
-{   opcodez x;
-    ASSERT_ZCODE();
-    if (i == -1) return custom_opcode_z;
-    x = opcodes_table_z[i];
-    if (instruction_set_number < x.version1) return invalid_opcode_z;
-    if (x.version2 == 0) return x;
-    if (instruction_set_number <= x.version2) return x;
-    i = x.extension;
-    if (i < 0) return invalid_opcode_z;
-    x = extension_table_z[i];
-    if (instruction_set_number < x.version1) return invalid_opcode_z;
-    if (x.version2 == 0) return x;
-    if (instruction_set_number <= x.version2) return x;
-    return extension_table_z[x.extension];
-}
-
-static void make_opcode_syntax_z(opcodez opco)
-{   char *p = "", *q = opcode_syntax_string;
-    sprintf(q, "%s", opco.name);
-    switch(opco.no)
-    {   case ONE: p=" <operand>"; break;
-        case TWO: p=" <operand1> <operand2>"; break;
-        case EXT:
-        case VAR: p=" <0 to 4 operands>"; break;
-        case VAR_LONG: p=" <0 to 8 operands>"; break;
-    }
-    switch(opco.op_rules)
-    {   case TEXT: sprintf(q+strlen(q), " <text>"); return;
-        case LABEL: sprintf(q+strlen(q), " <label>"); return;
-        case VARIAB:
-            sprintf(q+strlen(q), " <variable>");
-        case CALL:
-            if (opco.op_rules==CALL) sprintf(q+strlen(q), " <routine>");
-            switch(opco.no)
-            {   case ONE: p=""; break;
-                case TWO: p=" <operand>"; break;
-                case EXT:
-                case VAR: p=" <1 to 4 operands>"; break;
-                case VAR_LONG: p=" <1 to 8 operands>"; break;
-            }
-            break;
-    }
-    sprintf(q+strlen(q), "%s", p);
-    if ((opco.flags & St) != 0) sprintf(q+strlen(q), " -> <result-variable>");
-    if ((opco.flags & Br) != 0) sprintf(q+strlen(q), " ?[~]<label>");
-}
-
-static opcodeg internal_number_to_opcode_g(int32 i)
-{   
-    opcodeg x;
-    if (i == -1) return custom_opcode_g;
-    x = opcodes_table_g[i];
-    return x;
-}
-
-static opcodeg internal_number_to_opmacro_g(int32 i)
-{
-    return opmacros_table_g[i];
-}
-
-static void make_opcode_syntax_g(opcodeg opco)
-{
-    int ix;
-    char *cx;
-    char *q = opcode_syntax_string;
-
-    sprintf(q, "%s", opco.name);
-    sprintf(q+strlen(q), " <%d operand%s", opco.no,
-        ((opco.no==1) ? "" : "s"));
-    if (opco.no) {
-        cx = q+strlen(q);
-        strcpy(cx, ": ");
-        cx += strlen(cx);
-        for (ix=0; ix<opco.no; ix++) {
-            if (ix) {
-                *cx = ' ';
-                cx++;
-            }
-            if (ix == opco.no-1) {
-                if (opco.flags & Br) {
-                    strcpy(cx, "Lb");
-                }
-                else if (opco.flags & St) {
-                    strcpy(cx, "S");
-                }
-                else {
-                    strcpy(cx, "L");
-                }
-            }
-            else if (ix == opco.no-2 && (opco.flags & Br) && (opco.flags & St)) {
-                strcpy(cx, "S");
-            }
-            else if (ix == opco.no-2 && (opco.flags & St2)) {
-                strcpy(cx, "S");
-            }
-            else {
-                strcpy(cx, "L");
-            }
-            cx += strlen(cx);
-            sprintf(cx, "%d", ix+1);
-            cx += strlen(cx);
-        }
-    }
-    sprintf(q+strlen(q), ">");
-}
-
-
-/* ========================================================================= */
-/*   The assembler itself does four things:                                  */
-/*                                                                           */
-/*       assembles instructions                                              */
-/*       sets label N to the current code position                           */
-/*       assembles routine headers                                           */
-/*       assembles routine ends                                              */
-/* ------------------------------------------------------------------------- */
-
-/* This is for Z-code only. */
-static void write_operand(assembly_operand op)
-{   int32 j;
-    if (module_switch && (op.marker != 0))
-    {   if ((op.marker != VARIABLE_MV) && (op.type == SHORT_CONSTANT_OT))
-            op.type = LONG_CONSTANT_OT;
-    }
-    j=op.value;
-    switch(op.type)
-    {   case LONG_CONSTANT_OT:
-            byteout(j/256, op.marker); byteout(j%256, 0); return;
-        case SHORT_CONSTANT_OT:
-            if (op.marker == 0)
-            byteout(j, 0);
-            else byteout(j, 0x80 + op.marker); return;
-        case VARIABLE_OT:
-            byteout(j, (module_switch)?(0x80 + op.marker):0); return;
-        case CONSTANT_OT:
-        case HALFCONSTANT_OT:
-        case BYTECONSTANT_OT:
-        case ZEROCONSTANT_OT:
-        case SYSFUN_OT:
-        case DEREFERENCE_OT:
-        case LOCALVAR_OT:
-        case GLOBALVAR_OT:
-            compiler_error("Glulx OT in Z-code assembly operand.");
-            return;
-    }
-}
-
-extern void assemblez_instruction(assembly_instruction *AI)
-{
-    uchar *start_pc, *operands_pc;
-    int32 offset, j, topbits=0, types_byte1, types_byte2;
-    int operand_rules, min=0, max=0, no_operands_given, at_seq_point = FALSE;
-    assembly_operand o1, o2;
-    opcodez opco;
-
-    ASSERT_ZCODE();
-
-    offset = zmachine_pc;
-
-    no_instructions++;
-
-    if (veneer_mode) sequence_point_follows = FALSE;
-    if (sequence_point_follows)
-    {   sequence_point_follows = FALSE; at_seq_point = TRUE;
-        if (debugfile_switch)
-        {   sequence_point_labels[next_sequence_point] = next_label;
-            sequence_point_locations[next_sequence_point] =
-                statement_debug_location;
-            set_label_offset(next_label++, zmachine_pc);
-        }
-        next_sequence_point++;
-    }
-
-    opco = internal_number_to_opcode_z(AI->internal_number);
-    if (opco.version1==0)
-    {   error_named("Opcode unavailable in this Z-machine version",
-            opcode_names.keywords[AI->internal_number]);
-        return;
-    }
-
-    if (execution_never_reaches_here)
-        warning("This statement can never be reached");
-
-    operand_rules = opco.op_rules;
-    execution_never_reaches_here = ((opco.flags & Rf) != 0);
-
-    if (opco.flags2_set != 0) flags2_requirements[opco.flags2_set] = 1;
-
-    no_operands_given = AI->operand_count;
-
-    if ((opco.no == TWO) && ((no_operands_given==3)||(no_operands_given==4)))
-        opco.no = VAR;
-
-    /* 1. Write the opcode byte(s) */
-
-    start_pc = zcode_holding_area + zcode_ha_size;
-
-    switch(opco.no)
-    {   case VAR_LONG: topbits=0xc0; min=0; max=8; break;
-        case VAR:      topbits=0xc0; min=0; max=4; break;
-        case ZERO:     topbits=0xb0; min=0; max=0; break;
-        case ONE:      topbits=0x80; min=1; max=1; break;
-        case TWO:      topbits=0x00; min=2; max=2; break;
-        case EXT:      topbits=0x00; min=0; max=4;
-                       byteout(0xbe, 0); opco.no=VAR; break;
-        case EXT_LONG: topbits=0x00; min=0; max=8;
-                       byteout(0xbe, 0); opco.no=VAR_LONG; break;
-    }
-    byteout(opco.code + topbits, 0);
-
-    operands_pc = zcode_holding_area + zcode_ha_size;
-
-    /* 2. Dispose of the special rules LABEL and TEXT */
-
-    if (operand_rules==LABEL)
-    {   j = (AI->operand[0]).value;
-        byteout(j/256, LABEL_MV); byteout(j%256, 0);
-        goto Instruction_Done;
-    }
-
-    if (operand_rules==TEXT)
-    {   int32 i;
-        uchar *tmp = translate_text(zcode_holding_area + zcode_ha_size, zcode_holding_area+MAX_ZCODE_SIZE, AI->text);
-        if (!tmp)
-            memoryerror("MAX_ZCODE_SIZE", MAX_ZCODE_SIZE);
-        j = subtract_pointers(tmp, (zcode_holding_area + zcode_ha_size));
-        for (i=0; i<j; i++) zcode_markers[zcode_ha_size++] = 0;
-        zmachine_pc += j;
-        goto Instruction_Done;
-    }
-
-    /* 3. Sort out the operands */
-
-    if ((no_operands_given < min) || (no_operands_given > max))
-        goto OpcodeSyntaxError;
-
-    switch(opco.no)
-    {   case VAR:
-        case VAR_LONG:
-            byteout(0, 0);
-            if (opco.no == VAR_LONG) byteout(0, 0);
-            types_byte1=0xff; types_byte2=0xff;
-            for (j=0; j<no_operands_given; j++)
-            {   int multi=0, mask=0;
-                switch(j)
-                {   case 0: case 4: multi=0x40; mask=0xc0; break;
-                    case 1: case 5: multi=0x10; mask=0x30; break;
-                    case 2: case 6: multi=0x04; mask=0x0c; break;
-                    case 3: case 7: multi=0x01; mask=0x03; break;
-                }
-                o1 = AI->operand[j];
-                write_operand(o1);
-                if (j<4)
-                    types_byte1 = (types_byte1 & (~mask)) + o1.type*multi;
-                else
-                    types_byte2 = (types_byte2 & (~mask)) + o1.type*multi;
-            }
-            *operands_pc=types_byte1;
-            if (opco.no == VAR_LONG) *(operands_pc+1)=types_byte2;
-            break;
-
-        case ONE:
-            o1 = AI->operand[0];
-            *start_pc=(*start_pc) + o1.type*0x10;
-            write_operand(o1);
-            break;
-
-        case TWO:
-            o1 = AI->operand[0];
-            o2 = AI->operand[1];
-
-            /* Transfer to VAR form if either operand is a long constant */
-
-            if ((o1.type==LONG_CONSTANT_OT)||(o2.type==LONG_CONSTANT_OT))
-            {   *start_pc=(*start_pc) + 0xc0;
-                byteout(o1.type*0x40 + o2.type*0x10 + 0x0f, 0);
-            }
-            else
-            {   if (o1.type==VARIABLE_OT) *start_pc=(*start_pc) + 0x40;
-                if (o2.type==VARIABLE_OT) *start_pc=(*start_pc) + 0x20;
-            }
-            write_operand(o1);
-            write_operand(o2);
-            break;
-    }
-
-    /* 4. Assemble a Store destination, if needed */
-
-    if ((AI->store_variable_number) != -1)
-    {   if (AI->store_variable_number >= MAX_LOCAL_VARIABLES+MAX_GLOBAL_VARIABLES) {
-            goto OpcodeSyntaxError;
-        }
-        o1.type = VARIABLE_OT;
-        o1.value = AI->store_variable_number;
-        variable_usage[o1.value] = TRUE;
-        o1.marker = 0;
-
-        /*  Note that variable numbers 249 to 255 (i.e. globals 233 to 239)
-            are used as scratch workspace, so need no mapping between
-            modules and story files: nor do local variables 0 to 15  */
-
-        if ((o1.value >= MAX_LOCAL_VARIABLES) && (o1.value < 249))
-            o1.marker = VARIABLE_MV;
-        write_operand(o1);
-    }
-
-    /* 5. Assemble a branch, if needed */
-
-    if (AI->branch_label_number != -1)
-    {   int32 addr, long_form;
-        int branch_on_true = (AI->branch_flag)?1:0;
-
-        switch (AI->branch_label_number)
-        {   case -2: addr = 2; branch_on_true = 0; long_form = 0; break;
-                                                 /* branch nowhere, carry on */
-            case -3: addr = 0; long_form = 0; break;  /* rfalse on condition */
-            case -4: addr = 1; long_form = 0; break;  /* rtrue on condition */
-            default:
-                long_form = 1; addr = AI->branch_label_number;
-                break;
-        }
-        if (addr > 0x7fff) fatalerror("Too many branch points in routine.");
-        if (long_form==1)
-        {   byteout(branch_on_true*0x80 + addr/256, BRANCH_MV);
-            byteout(addr%256, 0);
-        }
-        else
-            byteout(branch_on_true*0x80+ 0x40 + (addr&0x3f), 0);
-    }
-
-    Instruction_Done:
-
-    if (asm_trace_level > 0)
-    {   int i;
-        printf("%5d  +%05lx %3s %-12s ", ErrorReport.line_number,
-            ((long int) offset),
-            (at_seq_point)?"<*>":"   ", opco.name);
-
-        if ((AI->internal_number == print_zc)
-            || (AI->internal_number == print_ret_zc))
-        {   printf("\"");
-            for (i=0;(AI->text)[i]!=0 && i<35; i++) printf("%c",(AI->text)[i]);
-            if (i == 35) printf("...");
-            printf("\"");
-        }
-
-        for (i=0; i<AI->operand_count; i++)
-        {   if ((i==0) && (opco.op_rules == VARIAB))
-            {   if ((AI->operand[0]).type == VARIABLE_OT)
-                {   printf("["); print_operand_z(AI->operand[i]); }
-                else
-                    printf("%s", variable_name((AI->operand[0]).value));
-            }
-            else
-            if ((i==0) && (opco.op_rules == LABEL))
-            {   printf("L%d", AI->operand[0].value);
-            }
-            else print_operand_z(AI->operand[i]);
-            printf(" ");
-        }
-        if (AI->store_variable_number != -1)
-        {   assembly_operand AO;
-            printf("-> ");
-            AO.type = VARIABLE_OT; AO.value = AI->store_variable_number;
-            print_operand_z(AO); printf(" ");
-        }
-
-        switch(AI->branch_label_number)
-        {   case -4: printf("rtrue if %s", (AI->branch_flag)?"TRUE":"FALSE");
-                break;
-            case -3: printf("rfalse if %s", (AI->branch_flag)?"TRUE":"FALSE");
-                break;
-            case -2: printf("(no branch)"); break;
-            case -1: break;
-            default:
-                printf("to L%d if %s", AI->branch_label_number,
-                   (AI->branch_flag)?"TRUE":"FALSE"); break;
-        }
-
-        if (asm_trace_level>=2)
-        {   for (j=0;start_pc<zcode_holding_area + zcode_ha_size;
-                 j++, start_pc++)
-            {   if (j%16==0) printf("\n                               ");
-                printf("%02x ", *start_pc);
-            }
-        }
-        printf("\n");
-    }
-
-    if (module_switch) flush_link_data();
-
-    return;
-
-    OpcodeSyntaxError:
-
-    make_opcode_syntax_z(opco);
-    error_named("Assembly mistake: syntax is", opcode_syntax_string);
-}
-
-static void assembleg_macro(assembly_instruction *AI)
-{
-    /* validate macro syntax first */
-    int ix, no_operands_given;
-    opcodeg opco;
-    
-    opco = internal_number_to_opmacro_g(AI->internal_number);
-    no_operands_given = AI->operand_count;
-    
-    if (no_operands_given != opco.no)
-        goto OpcodeSyntaxError;
-    
-    for (ix = 0; ix < no_operands_given; ix++) {
-        int type = AI->operand[ix].type;
-        if ((opco.flags & St) 
-          && ((!(opco.flags & Br) && (ix == no_operands_given-1))
-          || ((opco.flags & Br) && (ix == no_operands_given-2)))) {
-            if (is_constant_ot(type)) {
-                error("*** assembly macro tried to store to a constant ***");
-                goto OpcodeSyntaxError; 
-            }
-        }
-        if ((opco.flags & St2) 
-            && (ix == no_operands_given-2)) {
-            if (is_constant_ot(type)) {
-              error("*** assembly macro tried to store to a constant ***");
-              goto OpcodeSyntaxError; 
-            }
-        }
-    }
-    
-    /* expand the macro */
-    switch (AI->internal_number) {
-        case pull_gm:
-            assembleg_store(AI->operand[0], stack_pointer);
-            break;
-        
-        case push_gm:
-            assembleg_store(stack_pointer, AI->operand[0]);
-            break;
-        
-        default:
-            compiler_error("Invalid Glulx assembly macro");
-            break;
-    }
-    
-    return;
-    
-    OpcodeSyntaxError:
-    
-    make_opcode_syntax_g(opco);
-    error_named("Assembly mistake: syntax is", opcode_syntax_string);
-}
-
-extern void assembleg_instruction(assembly_instruction *AI)
-{
-    uchar *start_pc, *opmodes_pc;
-    int32 offset, j;
-    int no_operands_given, at_seq_point = FALSE;
-    int ix, k;
-    opcodeg opco;
-
-    ASSERT_GLULX();
-
-    offset = zmachine_pc;
-
-    no_instructions++;
-
-    if (veneer_mode) sequence_point_follows = FALSE;
-    if (sequence_point_follows)
-    {   sequence_point_follows = FALSE; at_seq_point = TRUE;
-        if (debugfile_switch)
-        {   sequence_point_labels[next_sequence_point] = next_label;
-            sequence_point_locations[next_sequence_point] =
-                statement_debug_location;
-            set_label_offset(next_label++, zmachine_pc);
-        }
-        next_sequence_point++;
-    }
-
-    opco = internal_number_to_opcode_g(AI->internal_number);
-
-    if (execution_never_reaches_here)
-        warning("This statement can never be reached");
-
-    execution_never_reaches_here = ((opco.flags & Rf) != 0);
-
-    if (opco.op_rules & GOP_Unicode) {
-        uses_unicode_features = TRUE;
-    }
-    if (opco.op_rules & GOP_MemHeap) {
-        uses_memheap_features = TRUE;
-    }
-    if (opco.op_rules & GOP_Acceleration) {
-        uses_acceleration_features = TRUE;
-    }
-    if (opco.op_rules & GOP_Float) {
-        uses_float_features = TRUE;
-    }
-
-    no_operands_given = AI->operand_count;
-
-    /* 1. Write the opcode byte(s) */
-
-    start_pc = zcode_holding_area + zcode_ha_size; 
-
-    if (opco.code < 0x80) {
-      byteout(opco.code, 0);
-    }
-    else if (opco.code < 0x4000) {
-      byteout(((opco.code >> 8) & 0xFF) | 0x80, 0);
-      byteout((opco.code & 0xFF), 0);
-    }
-    else {
-      byteout(((opco.code >> 24) & 0xFF) | 0xC0, 0);
-      byteout(((opco.code >> 16) & 0xFF), 0);
-      byteout(((opco.code >> 8) & 0xFF), 0);
-      byteout(((opco.code) & 0xFF), 0);
-    }
-
-    /* ... and the operand addressing modes. There's one byte for
-       every two operands (rounded up). We write zeroes for now; 
-       when the operands are written, we'll go back and fix them. */
-
-    opmodes_pc = zcode_holding_area + zcode_ha_size;
-
-    for (ix=0; ix<opco.no; ix+=2) {
-      byteout(0, 0);
-    }
-
-    /* 2. Dispose of the special rules */
-    /* There aren't any in Glulx. */
-
-    /* 3. Sort out the operands */
-
-    if (no_operands_given != opco.no) {
-      goto OpcodeSyntaxError;
-    }
-
-    for (ix=0; ix<no_operands_given; ix++) {
-        int marker = AI->operand[ix].marker;
-        int type = AI->operand[ix].type;
-        k = AI->operand[ix].value;
-
-        if ((opco.flags & Br) && (ix == no_operands_given-1)) {
-            if (!(marker >= BRANCH_MV && marker < BRANCHMAX_MV)) {
-                compiler_error("Assembling branch without BRANCH_MV marker");
-                goto OpcodeSyntaxError; 
-            }
-            if (k == -2) {
-                k = 2; /* branch no-op */
-                type = BYTECONSTANT_OT;
-                marker = 0;
-            }
-            else if (k == -3) {
-                k = 0; /* branch return 0 */
-                type = ZEROCONSTANT_OT;
-                marker = 0;
-            }
-            else if (k == -4) {
-                k = 1; /* branch return 1 */
-                type = BYTECONSTANT_OT;
-                marker = 0;
-            }
-            else {
-                /* branch to label k */
-                j = subtract_pointers((zcode_holding_area + zcode_ha_size), 
-                    opmodes_pc);
-                j = 2*j - ix;
-                marker = BRANCH_MV + j;
-                if (!(marker >= BRANCH_MV && marker < BRANCHMAX_MV)) {
-                    error("*** branch marker too far from opmode byte ***");
-                    goto OpcodeSyntaxError; 
-                }
-            }
-        }
-    if ((opco.flags & St) 
-      && ((!(opco.flags & Br) && (ix == no_operands_given-1))
-      || ((opco.flags & Br) && (ix == no_operands_given-2)))) {
-        if (type == BYTECONSTANT_OT || type == HALFCONSTANT_OT
-            || type == CONSTANT_OT) {
-            error("*** instruction tried to store to a constant ***");
-            goto OpcodeSyntaxError; 
-        }
-    }
-    if ((opco.flags & St2) 
-        && (ix == no_operands_given-2)) {
-        if (type == BYTECONSTANT_OT || type == HALFCONSTANT_OT
-          || type == CONSTANT_OT) {
-          error("*** instruction tried to store to a constant ***");
-          goto OpcodeSyntaxError; 
-        }
-    }
-
-      if (marker && (type == HALFCONSTANT_OT 
-        || type == BYTECONSTANT_OT
-        || type == ZEROCONSTANT_OT)) {
-        compiler_error("Assembling marker in less than 32-bit constant.");
-        /* Actually we should store marker|0x80 for a byte constant,
-           but let's hold off on that. */
-        }
-
-      switch (type) {
-      case LONG_CONSTANT_OT:
-      case SHORT_CONSTANT_OT:
-      case VARIABLE_OT:
-        j = 0;
-        compiler_error("Z-code OT in Glulx assembly operand.");
-        break;
-      case CONSTANT_OT:
-        j = 3;
-        byteout((k >> 24) & 0xFF, marker);
-        byteout((k >> 16) & 0xFF, 0);
-        byteout((k >> 8) & 0xFF, 0);
-        byteout((k & 0xFF), 0);
-        break;
-      case HALFCONSTANT_OT:
-        j = 2;
-        byteout((k >> 8) & 0xFF, marker);
-        byteout((k & 0xFF), 0);
-        break;
-      case BYTECONSTANT_OT:
-        j = 1;
-        byteout((k & 0xFF), marker);
-        break;
-      case ZEROCONSTANT_OT:
-        j = 0;
-        break;
-      case DEREFERENCE_OT:
-        j = 7;
-        byteout((k >> 24) & 0xFF, marker);
-        byteout((k >> 16) & 0xFF, 0);
-        byteout((k >> 8) & 0xFF, 0);
-        byteout((k & 0xFF), 0);
-        break;
-      case GLOBALVAR_OT:
-        /* Global variable -- a constant address. */
-        k -= MAX_LOCAL_VARIABLES;
-        if (/* DISABLES CODE */ (0)) {
-            /* We could write the value as a marker and patch it later... */
-            j = 7;
-            byteout(((k) >> 24) & 0xFF, VARIABLE_MV);
-            byteout(((k) >> 16) & 0xFF, 0);
-            byteout(((k) >> 8) & 0xFF, 0);
-            byteout(((k) & 0xFF), 0);
-        }
-        else {
-            /* ...but it's more efficient to write it as a RAM operand,
-                  which can be 1, 2, or 4 bytes. Remember that global variables
-                  are the very first thing in RAM. */
-            k = k * 4; /* each variable is four bytes */
-            if (k <= 255) {
-                j = 13;
-                byteout(((k) & 0xFF), 0);
-            }
-            else if (k <= 65535) {
-                j = 14;
-                byteout(((k) >> 8) & 0xFF, 0);
-                byteout(((k) & 0xFF), 0);
-            }
-            else {
-                j = 15;
-                byteout(((k) >> 24) & 0xFF, 0);
-                byteout(((k) >> 16) & 0xFF, 0);
-                byteout(((k) >> 8) & 0xFF, 0);
-                byteout(((k) & 0xFF), 0);       
-            }
-        }
-        break;
-      case LOCALVAR_OT:
-        if (k == 0) {
-            /* Stack-pointer magic variable */
-            j = 8; 
-        }
-        else {
-            /* Local variable -- a byte or short offset from the
-               frame pointer. It's an unsigned offset, so we can
-               fit up to long 63 (offset 4*63) in a byte. */
-            if ((k-1) < 64) {
-                j = 9;
-                byteout((k-1)*4, 0);
-            }
-            else {
-                j = 10;
-                byteout((((k-1)*4) >> 8) & 0xFF, 0);
-                byteout(((k-1)*4) & 0xFF, 0);
-            }
-        }
-        break;
-      default:
-        j = 0;
-        break;
-      }
-
-      if (ix & 1)
-          j = (j << 4);
-      opmodes_pc[ix/2] |= j;
-    }
-
-    /* Print assembly trace. */
-    if (asm_trace_level > 0) {
-      int i;
-      printf("%5d  +%05lx %3s %-12s ", ErrorReport.line_number,
-        ((long int) offset),
-        (at_seq_point)?"<*>":"   ", opco.name);
-      for (i=0; i<AI->operand_count; i++) {
-          if ((opco.flags & Br) && (i == opco.no-1)) {
-            if (AI->operand[i].value == -4)
-                printf("to rtrue");
-            else if (AI->operand[i].value == -3)
-                printf("to rfalse");
-            else
-                printf("to L%d", AI->operand[i].value);
-            }
-          else {
-            print_operand_g(AI->operand[i]);
-          }
-          printf(" ");
-      }
-
-      if (asm_trace_level>=2) {
-        for (j=0;
-            start_pc<zcode_holding_area + zcode_ha_size;
-            j++, start_pc++) {
-            if (j%16==0) printf("\n                               ");
-            if (/* DISABLES CODE */ (0)) {
-                printf("%02x ", *start_pc);
-            }
-            else {
-                printf("%02x", *start_pc);
-                if (zcode_markers[start_pc-zcode_holding_area])
-                    printf("{%02x}", zcode_markers[start_pc-zcode_holding_area]);
-                printf(" ");
-            }
-        }
-      }
-      printf("\n");
-    }
-
-    if (module_switch) flush_link_data();
-
-    return;
-
-    OpcodeSyntaxError:
-
-    make_opcode_syntax_g(opco);
-    error_named("Assembly mistake: syntax is", opcode_syntax_string);
-}
-
-extern void assemble_label_no(int n)
-{
-    if (asm_trace_level > 0)
-        printf("%5d  +%05lx    .L%d\n", ErrorReport.line_number,
-            ((long int) zmachine_pc), n);
-    set_label_offset(n, zmachine_pc);
-    execution_never_reaches_here = FALSE;
-}
-
-extern void define_symbol_label(int symbol)
-{   label_symbols[svals[symbol]] = symbol;
-}
-
-extern int32 assemble_routine_header(int no_locals,
-    int routine_asterisked, char *name, int embedded_flag, int the_symbol)
-{   int i, rv;
-    int stackargs = FALSE;
-    int name_length;
-
-    execution_never_reaches_here = FALSE;
-
-    routine_locals = no_locals;
-    for (i=0; i<MAX_LOCAL_VARIABLES; i++) variable_usage[i] = FALSE;
-
-    if (no_locals >= 1 
-      && !strcmp(local_variables.keywords[0], "_vararg_count")) {
-      stackargs = TRUE;
-    }
-
-    if (veneer_mode) routine_starts_line = blank_brief_location;
-    else routine_starts_line = get_brief_location(&ErrorReport);
-
-    if (asm_trace_level > 0)
-    {   printf("\n%5d  +%05lx  [ %s ", ErrorReport.line_number,
-            ((long int) zmachine_pc), name);
-        for (i=1; i<=no_locals; i++) printf("%s ", variable_name(i));
-        printf("\n\n");
-    }
-
-    routine_start_pc = zmachine_pc;
-
-    if (track_unused_routines) {
-        /* The name of an embedded function is in a temporary buffer,
-           so we shouldn't keep a reference to it. (It is sad that we
-           have to know this here.) */
-        char *funcname = name;
-        if (embedded_flag)
-            funcname = "<embedded>";
-
-        df_note_function_start(funcname, zmachine_pc, embedded_flag,
-                               routine_starts_line);
-    }
-
-    routine_symbol = the_symbol;
-    name_length = strlen(name) + 1;
-    routine_name =
-      my_malloc(name_length * sizeof(char), "temporary copy of routine name");
-    strncpy(routine_name, name, name_length);
-
-    /*  Update the routine counter                                           */
-
-    no_routines++;
-
-    /*  Actually assemble the routine header into the code area; note        */
-    /*  Inform doesn't support the setting of local variables to default     */
-    /*  values other than 0 in V3 and V4.  (In V5+ the Z-Machine doesn't     */
-    /*  provide the possibility in any case.)                                */
-
-    if (!glulx_mode) {
-
-      if (stackargs) 
-        warning("Z-code does not support stack-argument function definitions.");
-
-      byteout(no_locals, 0);
-
-      /*  Not the packed address, but the scaled offset from code area start:  */
-
-      rv = zmachine_pc/scale_factor;
-
-      if (instruction_set_number<5)
-          for (i=0; i<no_locals; i++) { byteout(0,0); byteout(0,0); }
-
-      next_label = 0; next_sequence_point = 0; last_label = -1;
-
-      /*  Compile code to print out text like "a=3, b=4, c=5" when the       */
-      /*  function is called, if it's required.                              */
-
-      if ((routine_asterisked) || (define_INFIX_switch))
-      {   char fnt[256]; assembly_operand PV, RFA, CON, STP, SLF; int ln, ln2;
-
-          ln = next_label++;
-          ln2 = next_label++;
-
-          if (define_INFIX_switch)
-          {
-                if (embedded_flag)
-            {   SLF.value = 251; SLF.type = VARIABLE_OT; SLF.marker = 0;
-                  CON.value = 0; CON.type = SHORT_CONSTANT_OT; CON.marker = 0;
-                assemblez_2_branch(test_attr_zc, SLF, CON, ln2, FALSE);
-            }
-            else
-            {   i = no_named_routines++;
-                  named_routine_symbols[i] = the_symbol;
-                CON.value = i/8; CON.type = LONG_CONSTANT_OT; CON.marker = 0;
-                RFA.value = routine_flags_array_SC;
-                RFA.type = LONG_CONSTANT_OT; RFA.marker = INCON_MV;
-                STP.value = 0; STP.type = VARIABLE_OT; STP.marker = 0;
-                assemblez_2_to(loadb_zc, RFA, CON, STP);
-                CON.value = (1 << (i%8)); CON.type = SHORT_CONSTANT_OT;
-                assemblez_2_to(and_zc, STP, CON, STP);
-                assemblez_1_branch(jz_zc, STP, ln2, TRUE);
-            }
-        }
-        sprintf(fnt, "[ %s(", name);
-        AI.text = fnt; assemblez_0(print_zc);
-        for (i=1; (i<=7)&&(i<=no_locals); i++)
-        {   if (version_number >= 5)
-            {   PV.type = SHORT_CONSTANT_OT;
-                PV.value = i; PV.marker = 0;
-                assemblez_1_branch(check_arg_count_zc, PV, ln, FALSE);
-            }
-            sprintf(fnt, "%s%s = ", (i==1)?"":", ", variable_name(i));
-            AI.text = fnt; assemblez_0(print_zc);
-            PV.type = VARIABLE_OT; PV.value = i; PV.marker = 0;
-            assemblez_1(print_num_zc, PV);
-        }
-        assemble_label_no(ln);
-        sprintf(fnt, ") ]^"); AI.text = fnt;
-        assemblez_0(print_zc);
-        assemble_label_no(ln2);
-      }
-
-    }
-    else {
-      rv = zmachine_pc;
-
-      if (stackargs)
-        byteout(0xC0, 0); /* Glulx type byte for function */
-      else
-        byteout(0xC1, 0); /* Glulx type byte for function */
-
-      /* Now the locals format list. This is simple; we only use
-        four-byte locals. That's a single pair, unless we have more
-        than 255 locals, or none at all. */
-      i = no_locals;
-      while (i) {
-        int j = i;
-        if (j > 255)
-          j = 255;
-        byteout(4, 0); 
-        byteout(j, 0);
-        i -= j;
-      }
-      /* Terminate the list with a (0, 0) pair. */
-      byteout(0, 0);
-      byteout(0, 0);
-
-      if (stackargs) {
-        /* The top stack value is the number of function arguments. Let's
-           move that into the first local, which is _vararg_count. */
-        /* @copy sp _vararg_count; */
-        byteout(0x40, 0); byteout(0x98, 0); byteout(0x00, 0);
-      }
-
-      next_label = 0; next_sequence_point = 0; last_label = -1; 
-
-      if ((routine_asterisked) || (define_INFIX_switch)) {
-        int ix;
-        char fnt[256];
-        assembly_operand AO, AO2;
-        if (define_INFIX_switch) {
-          /* This isn't supported */
-          if (embedded_flag) {
-          }
-          else {
-            i = no_named_routines++;
-            named_routine_symbols[i] = the_symbol;
-          }
-        }
-        sprintf(fnt, "[ %s(", name);
-        AO.marker = STRING_MV;
-        AO.type   = CONSTANT_OT;
-        AO.value  = compile_string(fnt, FALSE, FALSE);
-        assembleg_1(streamstr_gc, AO);
-
-        if (!stackargs) {
-          for (ix=1; ix<=no_locals; ix++) {
-            sprintf(fnt, "%s%s = ", (ix==1)?"":", ", variable_name(ix));
-            AO.marker = STRING_MV;
-            AO.type   = CONSTANT_OT;
-            AO.value  = compile_string(fnt, FALSE, FALSE);
-            assembleg_1(streamstr_gc, AO);
-            AO.marker = 0;
-            AO.type = LOCALVAR_OT;
-            AO.value = ix;
-            assembleg_1(streamnum_gc, AO);
-          }
-        }
-        else {
-          int lntop, lnbottom;
-          sprintf(fnt, "%s = ", variable_name(1));
-          AO.marker = STRING_MV;
-          AO.type   = CONSTANT_OT;
-          AO.value  = compile_string(fnt, FALSE, FALSE);
-          assembleg_1(streamstr_gc, AO);
-          AO.marker = 0;
-          AO.type = LOCALVAR_OT;
-          AO.value = 1;
-          assembleg_1(streamnum_gc, AO);
-          AO2.type = BYTECONSTANT_OT;
-          AO2.marker = 0;
-          AO2.value = ':';
-          assembleg_1(streamchar_gc, AO2);
-          AO2.type = BYTECONSTANT_OT;
-          AO2.marker = 0;
-          AO2.value = ' ';
-          /* for (temp_var4=0 : temp_var4<_vararg_count : temp_var4++) {
-               @streamchar ' ';
-               @stkpeek temp_var4 sp;
-               @stream_num sp;
-             }
-          */
-          assembleg_store(temp_var4, zero_operand);
-          lntop = next_label++;
-          lnbottom = next_label++;
-          assemble_label_no(lntop);
-          assembleg_2_branch(jge_gc, temp_var4, AO, lnbottom); /* AO is _vararg_count */
-          assembleg_1(streamchar_gc, AO2); /* AO2 is space */
-          assembleg_2(stkpeek_gc, temp_var4, stack_pointer);
-          assembleg_1(streamnum_gc, stack_pointer);
-          assembleg_3(add_gc, temp_var4, one_operand, temp_var4);
-          assembleg_0_branch(jump_gc, lntop);
-          assemble_label_no(lnbottom);
-        }
-
-        AO.marker = STRING_MV;
-        AO.type   = CONSTANT_OT;
-        AO.value  = compile_string(") ]^", FALSE, FALSE);
-        assembleg_1(streamstr_gc, AO);
-      }
-    }
-
-    return rv;
-}
-
-void assemble_routine_end(int embedded_flag, debug_locations locations)
-{   int32 i;
-
-    /* No marker is made in the Z-machine's code area to indicate the        */
-    /* end of a routine.  Instead, we simply assemble a return opcode if     */
-    /* need be (it won't be if the last instruction was, say, a "quit").     */
-    /* The return value is true (1) for normal routines, false (0) for       */
-    /* embedded routines (e.g. the library uses this for "before"            */
-    /* properties).                                                          */
-
-    if (!execution_never_reaches_here)
-    {   
-      if (!glulx_mode) {
-        if (embedded_flag) assemblez_0(rfalse_zc);
-                      else assemblez_0(rtrue_zc);
-      }
-      else {
-        assembly_operand AO;
-        if (embedded_flag) 
-            AO = zero_operand;
-        else 
-            AO = one_operand;
-        assembleg_1(return_gc, AO);
-      }
-    }
-
-    /* Dump the contents of the current routine into longer-term Z-code
-       storage                                                               */
-
-    if (!glulx_mode)
-      transfer_routine_z();
-    else
-      transfer_routine_g();
-
-    if (track_unused_routines)
-        df_note_function_end(zmachine_pc);
-
-    /* Tell the debugging file about the routine just ended.                 */
-
-    if (debugfile_switch)
-    {
-        debug_file_printf("<routine>");
-        if (embedded_flag)
-        {   debug_file_printf
-                ("<identifier artificial=\"true\">%s</identifier>",
-                 routine_name);
-        }
-        else if (sflags[routine_symbol] & REPLACE_SFLAG)
-        {   /* The symbol type will be set to ROUTINE_T once the replaced
-               version has been given; if it is already set, we must be dealing
-               with a replacement, and we can use the routine name as-is.
-               Otherwise we look for a rename.  And if that doesn't work, we
-               fall back to an artificial identifier. */
-            if (stypes[routine_symbol] == ROUTINE_T)
-            {   /* Optional because there may be further replacements. */
-                write_debug_optional_identifier(routine_symbol);
-            }
-            else if (find_symbol_replacement(&routine_symbol))
-            {   debug_file_printf
-                    ("<identifier>%s</identifier>", symbs[routine_symbol]);
-            }
-            else
-            {   debug_file_printf
-                    ("<identifier artificial=\"true\">%s (replaced)"
-                         "</identifier>",
-                     routine_name);
-            }
-        } else
-        {   debug_file_printf("<identifier>%s</identifier>", routine_name);
-        }
-        debug_file_printf("<value>");
-        if (glulx_mode)
-        {   write_debug_code_backpatch(routine_start_pc);
-        } else
-        {   write_debug_packed_code_backpatch(routine_start_pc);
-        }
-        debug_file_printf("</value>");
-        debug_file_printf("<address>");
-        write_debug_code_backpatch(routine_start_pc);
-        debug_file_printf("</address>");
-        debug_file_printf
-            ("<byte-count>%d</byte-count>", zmachine_pc - routine_start_pc);
-        write_debug_locations(locations);
-        for (i = 1; i <= routine_locals; ++i)
-        {   debug_file_printf("<local-variable>");
-            debug_file_printf("<identifier>%s</identifier>", variable_name(i));
-            if (glulx_mode)
-            {   debug_file_printf
-                    ("<frame-offset>%d</frame-offset>", 4 * (i - 1));
-            }
-            else
-            {   debug_file_printf("<index>%d</index>", i);
-            }
-            debug_file_printf("</local-variable>");
-        }
-        for (i = 0; i < next_sequence_point; ++i)
-        {   debug_file_printf("<sequence-point>");
-            debug_file_printf("<address>");
-            write_debug_code_backpatch
-                (label_offsets[sequence_point_labels[i]]);
-            debug_file_printf("</address>");
-            write_debug_location(sequence_point_locations[i]);
-            debug_file_printf("</sequence-point>");
-        }
-        debug_file_printf("</routine>");
-    }
-
-    my_free(&routine_name, "temporary copy of routine name");
-
-    /* Issue warnings about any local variables not used in the routine. */
-
-    for (i=1; i<=routine_locals; i++)
-        if (!(variable_usage[i]))
-            dbnu_warning("Local variable", variable_name(i),
-                routine_starts_line);
-
-    for (i=0; i<next_label; i++)
-    {   int j = label_symbols[i];
-        if (j != -1)
-        {   if (sflags[j] & CHANGE_SFLAG)
-                error_named_at("Routine contains no such label as",
-                    (char *) symbs[j], slines[j]);
-            else
-                if ((sflags[j] & USED_SFLAG) == 0)
-                    dbnu_warning("Label", (char *) symbs[j], slines[j]);
-            stypes[j] = CONSTANT_T;
-            sflags[j] = UNKNOWN_SFLAG;
-        }
-    }
-    no_sequence_points += next_sequence_point;
-    next_label = 0; next_sequence_point = 0;
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Called when the holding area contains an entire routine of code:        */
-/*   backpatches the labels, issues module markers, then dumps the routine   */
-/*   into longer-term storage.                                               */
-/*   Note that in the code received, all branches have long form, and their  */
-/*   contents are not an offset but the label numbers they branch to.        */
-/*   Similarly, LABEL operands (those of "jump" instructions) are label      */
-/*   numbers.  So this routine must change the label numbers to offsets,     */
-/*   slimming the code down as it does so to take advantage of short-form    */
-/*   branch operands where possible.                                         */
-/* ------------------------------------------------------------------------- */
-
-static int32 adjusted_pc;
-
-static void transfer_to_temp_file(uchar *c)
-{   fputc(*c,Temp2_fp);
-    adjusted_pc++;
-}
-
-static void transfer_to_zcode_area(uchar *c)
-{   write_byte_to_memory_block(&zcode_area, adjusted_pc++, *c);
-}
-
-static void transfer_routine_z(void)
-{   int32 i, j, pc, new_pc, label, long_form, offset_of_next, addr,
-          branch_on_true, rstart_pc;
-    void (* transfer_byte)(uchar *);
-
-    adjusted_pc = zmachine_pc - zcode_ha_size; rstart_pc = adjusted_pc;
-
-    if (asm_trace_level >= 3)
-    {   printf("Backpatching routine at %05lx: initial size %d, %d labels\n",
-             (long int) adjusted_pc, zcode_ha_size, next_label);
-    }
-
-    transfer_byte =
-        (temporary_files_switch)?transfer_to_temp_file:transfer_to_zcode_area;
-
-    /*  (1) Scan through for branches and make short/long decisions in each
-            case.  Mark omitted bytes (2nd bytes in branches converted to
-            short form) with DELETED_MV.                                     */
-
-    for (i=0, pc=adjusted_pc; i<zcode_ha_size; i++, pc++)
-    {   if (zcode_markers[i] == BRANCH_MV)
-        {   if (asm_trace_level >= 4)
-                printf("Branch detected at offset %04x\n", pc);
-            j = (256*zcode_holding_area[i] + zcode_holding_area[i+1]) & 0x7fff;
-            if (asm_trace_level >= 4)
-                printf("To label %d, which is %d from here\n",
-                    j, label_offsets[j]-pc);
-            if ((label_offsets[j] >= pc+2) && (label_offsets[j] < pc+64))
-            {   if (asm_trace_level >= 4) printf("Short form\n");
-                zcode_markers[i+1] = DELETED_MV;
-            }
-        }
-    }
-
-    /*  (2) Calculate the new positions of the labels.  Note that since the
-            long/short decision was taken on the basis of the old labels,
-            and since the new labels are slightly closer together because
-            of branch bytes deleted, there may be a few further branch
-            optimisations which are possible but which have been missed
-            (if two labels move inside the "short" range as a result of
-            a previous optimisation).  However, this is acceptably uncommon. */
-
-    if (next_label > 0)
-    {   if (asm_trace_level >= 4)
-        {   printf("Opening label: %d\n", first_label);
-            for (i=0;i<next_label;i++)
-                printf("Label %d offset %04x next -> %d previous -> %d\n",
-                    i, label_offsets[i], label_next[i], label_prev[i]);
-        }
-
-        for (i=0, pc=adjusted_pc, new_pc=adjusted_pc, label = first_label;
-            i<zcode_ha_size; i++, pc++)
-        {   while ((label != -1) && (label_offsets[label] == pc))
-            {   if (asm_trace_level >= 4)
-                    printf("Position of L%d corrected from %04x to %04x\n",
-                        label, label_offsets[label], new_pc);
-                label_offsets[label] = new_pc;
-                label = label_next[label];
-            }
-           if (zcode_markers[i] != DELETED_MV) new_pc++;
-        }
-    }
-
-    /*  (3) As we are transferring, replace the label numbers in branch
-            operands with offsets to those labels.  Also issue markers, now
-            that we know where they occur in the final Z-code area.          */
-
-    for (i=0, new_pc=adjusted_pc; i<zcode_ha_size; i++)
-    {   switch(zcode_markers[i])
-        { case BRANCH_MV:
-            long_form = 1; if (zcode_markers[i+1] == DELETED_MV) long_form = 0;
-
-            j = (256*zcode_holding_area[i] + zcode_holding_area[i+1]) & 0x7fff;
-            branch_on_true = ((zcode_holding_area[i]) & 0x80);
-            offset_of_next = new_pc + long_form + 1;
-
-            addr = label_offsets[j] - offset_of_next + 2;
-            if (addr<-0x2000 || addr>0x1fff) 
-                fatalerror("Branch out of range: divide the routine up?");
-            if (addr<0) addr+=(int32) 0x10000L;
-
-            addr=addr&0x3fff;
-            if (long_form==1)
-            {   zcode_holding_area[i] = branch_on_true + addr/256;
-                zcode_holding_area[i+1] = addr%256;
-            }
-            else
-            {   if (addr >= 64)
-                {   compiler_error("Label out of range for branch");
-                    printf("Addr is %04x\n", addr);
-                }
-                zcode_holding_area[i] = branch_on_true + 0x40 + (addr&0x3f);
-            }
-            transfer_byte(zcode_holding_area + i); new_pc++;
-            break;
-
-          case LABEL_MV:
-            j = 256*zcode_holding_area[i] + zcode_holding_area[i+1];
-            addr = label_offsets[j] - new_pc;
-            if (addr<-0x8000 || addr>0x7fff) 
-                fatalerror("Jump out of range: divide the routine up?");
-            if (addr<0) addr += (int32) 0x10000L;
-            zcode_holding_area[i] = addr/256;
-            zcode_holding_area[i+1] = addr%256;
-            transfer_byte(zcode_holding_area + i); new_pc++;
-            break;
-
-          case DELETED_MV:
-            break;
-
-          default:
-            switch(zcode_markers[i] & 0x7f)
-            {   case NULL_MV: break;
-                case VARIABLE_MV:
-                case OBJECT_MV:
-                case ACTION_MV:
-                case IDENT_MV:
-                    if (!module_switch) break;
-                default:
-                    if ((zcode_markers[i] & 0x7f) > LARGEST_BPATCH_MV)
-                    {   compiler_error("Illegal code backpatch value");
-                        printf("Illegal value of %02x at PC = %04x\n",
-                            zcode_markers[i] & 0x7f, new_pc);
-                        break;
-                    }
-
-                    write_byte_to_memory_block(&zcode_backpatch_table,
-                        zcode_backpatch_size++,
-                        zcode_markers[i] + 32*(new_pc/65536));
-                    write_byte_to_memory_block(&zcode_backpatch_table,
-                        zcode_backpatch_size++, (new_pc/256)%256);
-                    write_byte_to_memory_block(&zcode_backpatch_table,
-                        zcode_backpatch_size++, new_pc%256);
-                    break;
-            }
-            transfer_byte(zcode_holding_area + i); new_pc++;
-            break;
-        }
-    }
-
-    if (asm_trace_level >= 3)
-    {   printf("After branch optimisation, routine length is %d bytes\n",
-             new_pc - rstart_pc);
-    }
-
-    /*  Insert null bytes if necessary to ensure the next routine address is */
-    /*  expressible as a packed address                                      */
-
-    {   uchar zero[1];
-        zero[0] = 0;
-        if (oddeven_packing_switch)
-            while ((adjusted_pc%(scale_factor*2))!=0) transfer_byte(zero);
-        else
-            while ((adjusted_pc%scale_factor)!=0) transfer_byte(zero);
-    }
-
-    zmachine_pc = adjusted_pc;
-    zcode_ha_size = 0;
-}
-
-static void transfer_routine_g(void)
-{   int32 i, j, pc, new_pc, label, form_len, offset_of_next, addr,
-          rstart_pc;
-    void (* transfer_byte)(uchar *);
-
-    adjusted_pc = zmachine_pc - zcode_ha_size; rstart_pc = adjusted_pc;
-
-    if (asm_trace_level >= 3)
-    {   printf("Backpatching routine at %05lx: initial size %d, %d labels\n",
-             (long int) adjusted_pc, zcode_ha_size, next_label);
-    }
-
-    transfer_byte =
-        (temporary_files_switch)?transfer_to_temp_file:transfer_to_zcode_area;
-
-    /*  (1) Scan through for branches and make short/long decisions in each
-            case.  Mark omitted bytes (bytes 2-4 in branches converted to
-            short form) with DELETED_MV.                                     */
-
-    for (i=0, pc=adjusted_pc; i<zcode_ha_size; i++, pc++) {
-      if (zcode_markers[i] >= BRANCH_MV && zcode_markers[i] < BRANCHMAX_MV) {
-        int opmodeoffset = (zcode_markers[i] - BRANCH_MV);
-        int32 opmodebyte;
-        if (asm_trace_level >= 4)
-            printf("Branch detected at offset %04x\n", pc);
-        j = ((zcode_holding_area[i] << 24) 
-            | (zcode_holding_area[i+1] << 16)
-            | (zcode_holding_area[i+2] << 8)
-            | (zcode_holding_area[i+3]));
-        offset_of_next = pc + 4;
-        addr = (label_offsets[j] - offset_of_next) + 2;
-        if (asm_trace_level >= 4)
-            printf("To label %d, which is (%d-2) = %d from here\n",
-                j, addr, label_offsets[j] - offset_of_next);
-        if (addr >= -0x80 && addr < 0x80) {
-            if (asm_trace_level >= 4) printf("...Byte form\n");
-            zcode_markers[i+1] = DELETED_MV;
-            zcode_markers[i+2] = DELETED_MV;
-            zcode_markers[i+3] = DELETED_MV;
-            opmodebyte = i - ((opmodeoffset+1)/2);
-            if ((opmodeoffset & 1) == 0)
-                zcode_holding_area[opmodebyte] = 
-                    (zcode_holding_area[opmodebyte] & 0xF0) | 0x01;
-            else
-                zcode_holding_area[opmodebyte] = 
-                    (zcode_holding_area[opmodebyte] & 0x0F) | 0x10;
-        }
-        else if (addr >= -0x8000 && addr < 0x8000) {
-            if (asm_trace_level >= 4) printf("...Short form\n");
-            zcode_markers[i+2] = DELETED_MV;
-            zcode_markers[i+3] = DELETED_MV;
-            opmodebyte = i - ((opmodeoffset+1)/2);
-            if ((opmodeoffset & 1) == 0)
-                zcode_holding_area[opmodebyte] = 
-                    (zcode_holding_area[opmodebyte] & 0xF0) | 0x02;
-            else
-                zcode_holding_area[opmodebyte] = 
-                    (zcode_holding_area[opmodebyte] & 0x0F) | 0x20;
-        }
-      }
-    }
-
-    /*  (2) Calculate the new positions of the labels.  Note that since the
-            long/short decision was taken on the basis of the old labels,
-            and since the new labels are slightly closer together because
-            of branch bytes deleted, there may be a few further branch
-            optimisations which are possible but which have been missed
-            (if two labels move inside the "short" range as a result of
-            a previous optimisation).  However, this is acceptably uncommon. */
-    if (next_label > 0) {
-      if (asm_trace_level >= 4) {
-        printf("Opening label: %d\n", first_label);
-        for (i=0;i<next_label;i++)
-            printf("Label %d offset %04x next -> %d previous -> %d\n",
-                i, label_offsets[i], label_next[i], label_prev[i]);
-      }
-
-      for (i=0, pc=adjusted_pc, new_pc=adjusted_pc, label = first_label;
-        i<zcode_ha_size; 
-        i++, pc++) {
-        while ((label != -1) && (label_offsets[label] == pc)) {
-            if (asm_trace_level >= 4)
-                printf("Position of L%d corrected from %04x to %04x\n",
-                label, label_offsets[label], new_pc);
-            label_offsets[label] = new_pc;
-            label = label_next[label];
-        }
-        if (zcode_markers[i] != DELETED_MV) new_pc++;
-      }
-    }
-
-    /*  (3) As we are transferring, replace the label numbers in branch
-            operands with offsets to those labels.  Also issue markers, now
-            that we know where they occur in the final Z-code area.          */
-
-    for (i=0, new_pc=adjusted_pc; i<zcode_ha_size; i++) {
-
-      if (zcode_markers[i] >= BRANCH_MV && zcode_markers[i] < BRANCHMAX_MV) {
-        form_len = 4;
-        if (zcode_markers[i+1] == DELETED_MV) {
-            form_len = 1;
-        }
-        else {
-            if (zcode_markers[i+2] == DELETED_MV)
-                form_len = 2;
-        }
-        j = ((zcode_holding_area[i] << 24) 
-            | (zcode_holding_area[i+1] << 16)
-            | (zcode_holding_area[i+2] << 8)
-            | (zcode_holding_area[i+3]));
-
-        /* At the moment, we can safely assume that the branch operand
-           is the end of the opcode, so the next opcode starts right
-           after it. */
-        offset_of_next = new_pc + form_len;
-
-        addr = (label_offsets[j] - offset_of_next) + 2;
-        if (asm_trace_level >= 4) {
-            printf("Branch at offset %04x: %04x (%s)\n",
-                new_pc, addr, ((form_len == 1) ? "byte" :
-                ((form_len == 2) ? "short" : "long")));
-        }
-        if (form_len == 1) {
-            if (addr < -0x80 && addr >= 0x80) {
-                error("*** Label out of range for byte branch ***");
-            }
-        zcode_holding_area[i] = (addr) & 0xFF;
-        }
-        else if (form_len == 2) {
-            if (addr < -0x8000 && addr >= 0x8000) {
-                error("*** Label out of range for short branch ***");
-            }
-            zcode_holding_area[i] = (addr >> 8) & 0xFF;
-            zcode_holding_area[i+1] = (addr) & 0xFF;
-        }
-        else {
-            zcode_holding_area[i] = (addr >> 24) & 0xFF;
-            zcode_holding_area[i+1] = (addr >> 16) & 0xFF;
-            zcode_holding_area[i+2] = (addr >> 8) & 0xFF;
-            zcode_holding_area[i+3] = (addr) & 0xFF;
-        }
-        transfer_byte(zcode_holding_area + i); new_pc++;
-      }
-      else if (zcode_markers[i] == LABEL_MV) {
-          error("*** No LABEL opcodes in Glulx ***");
-      }
-      else if (zcode_markers[i] == DELETED_MV) {
-        /* skip it */
-      }
-      else {
-        switch(zcode_markers[i] & 0x7f) {
-        case NULL_MV: 
-            break;
-        case ACTION_MV:
-        case IDENT_MV:
-            if (!module_switch) break;
-        case OBJECT_MV:
-        case VARIABLE_MV:
-        default:
-            if ((zcode_markers[i] & 0x7f) > LARGEST_BPATCH_MV) {
-                error("*** Illegal code backpatch value ***");
-                printf("Illegal value of %02x at PC = %04x\n",
-                zcode_markers[i] & 0x7f, new_pc);
-                break;
-            }
-          /* The backpatch table format for Glulx:
-             First, the marker byte (0..LARGEST_BPATCH_MV).
-             Then a byte indicating the data size to be patched (1, 2, 4).
-             Then the four-byte address (new_pc).
-          */
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++,
-            zcode_markers[i]);
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++,
-            4);
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++, ((new_pc >> 24) & 0xFF));
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++, ((new_pc >> 16) & 0xFF));
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++, ((new_pc >> 8) & 0xFF));
-          write_byte_to_memory_block(&zcode_backpatch_table,
-            zcode_backpatch_size++, (new_pc & 0xFF));
-          break;
-        }
-        transfer_byte(zcode_holding_area + i); new_pc++;
-      }
-    }
-
-    if (asm_trace_level >= 3)
-    {   printf("After branch optimisation, routine length is %d bytes\n",
-             new_pc - rstart_pc);
-    }
-
-    zmachine_pc = adjusted_pc;
-    zcode_ha_size = 0;
-}
-
-
-/* ========================================================================= */
-/*   Front ends for the instruction assembler: convenient shorthand forms    */
-/*   used in various code generation routines all over Inform.               */
-/* ------------------------------------------------------------------------- */
-
-void assemble_jump(int n)
-{
-    if (!glulx_mode)
-        assemblez_jump(n);
-    else
-        assembleg_jump(n);
-}
-
-void assemblez_0(int internal_number)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 0;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_0_to(int internal_number, assembly_operand o)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 0;
-    AI.store_variable_number = o.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_0_branch(int internal_number, int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 0;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = label;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_1(int internal_number, assembly_operand o1)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0] = o1;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_1_to(int internal_number,
-    assembly_operand o1, assembly_operand st)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0] = o1;
-    AI.store_variable_number = st.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_1_branch(int internal_number,
-    assembly_operand o1, int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0] = o1;
-    AI.branch_label_number = label;
-    AI.store_variable_number = -1;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_2(int internal_number,
-    assembly_operand o1, assembly_operand o2)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 2;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_3(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 3;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_3_to(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand st)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 3;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.store_variable_number = st.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_3_branch(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 3;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = label;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_4(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 4;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_5(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4, assembly_operand o5)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 5;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.operand[4] = o5;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_6(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4, assembly_operand o5, assembly_operand o6)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 6;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.operand[4] = o5;
-    AI.operand[5] = o6;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_4_branch(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4, int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 4;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = label;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_4_to(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4, assembly_operand st)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 4;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.store_variable_number = st.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_5_to(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand o3,
-    assembly_operand o4, assembly_operand o5, assembly_operand st)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 5;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.operand[4] = o5;
-    AI.store_variable_number = st.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_2_to(int internal_number,
-    assembly_operand o1, assembly_operand o2, assembly_operand st)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 2;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.store_variable_number = st.value;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_2_branch(int internal_number,
-    assembly_operand o1, assembly_operand o2, int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 2;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.branch_label_number = label;
-    AI.store_variable_number = -1;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_objcode(int internal_number,
-    assembly_operand o1, assembly_operand st, int label, int flag)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0] = o1;
-    AI.branch_label_number = label;
-    AI.store_variable_number = st.value;
-    AI.branch_flag = flag;
-    assemblez_instruction(&AI);
-}
-
-extern void assemblez_inc(assembly_operand o1)
-{   int m = 0;
-    if ((o1.value >= MAX_LOCAL_VARIABLES) 
-        && (o1.value<LOWEST_SYSTEM_VAR_NUMBER))
-            m = VARIABLE_MV;
-    AI.internal_number = inc_zc;
-    AI.operand_count = 1;
-    AI.operand[0].value = o1.value;
-    AI.operand[0].type = SHORT_CONSTANT_OT;
-    AI.operand[0].marker = m;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-extern void assemblez_dec(assembly_operand o1)
-{   int m = 0;
-    if ((o1.value >= MAX_LOCAL_VARIABLES) 
-        && (o1.value<LOWEST_SYSTEM_VAR_NUMBER))
-            m = VARIABLE_MV;
-    AI.internal_number = dec_zc;
-    AI.operand_count = 1;
-    AI.operand[0].value = o1.value;
-    AI.operand[0].type = SHORT_CONSTANT_OT;
-    AI.operand[0].marker = m;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-extern void assemblez_store(assembly_operand o1, assembly_operand o2)
-{   int m = 0;
-    if ((o1.value >= MAX_LOCAL_VARIABLES)
-        && (o1.value<LOWEST_SYSTEM_VAR_NUMBER))
-            m = VARIABLE_MV;
-
-    if ((o2.type == VARIABLE_OT) && (o2.value == 0))
-    {
-        /*  Assemble "pull VAR" rather than "store VAR sp",
-            saving 1 byte  */
-
-        AI.internal_number = pull_zc;
-        if (instruction_set_number == 6)
-        {   AI.operand_count = 0;
-            AI.store_variable_number = o1.value;
-        }
-        else
-        {   AI.operand_count = 1;
-            AI.operand[0].value = o1.value;
-            AI.operand[0].type = SHORT_CONSTANT_OT;
-            AI.operand[0].marker = m;
-            AI.store_variable_number = -1;
-        }
-        AI.branch_label_number = -1;
-        assemblez_instruction(&AI);
-        return;
-    }
-
-    if ((o1.type == VARIABLE_OT) && (o1.value == 0))
-    {   /*  Assemble "push VAR" rather than "store sp VAR",
-            saving 1 byte  */
-
-        AI.internal_number = push_zc;
-        AI.operand_count = 1;
-        AI.operand[0] = o2;
-        AI.store_variable_number = -1;
-        AI.branch_label_number = -1;
-        assemblez_instruction(&AI);
-        return;
-    }
-    AI.internal_number = store_zc;
-    AI.operand_count = 2;
-    AI.operand[0].value = o1.value;
-    AI.operand[0].type = SHORT_CONSTANT_OT;
-    AI.operand[0].marker = m;
-    AI.operand[1] = o2;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    assemblez_instruction(&AI);
-}
-
-void assemblez_jump(int n)
-{   assembly_operand AO;
-    if (n==-4) assemblez_0(rtrue_zc);
-    else if (n==-3) assemblez_0(rfalse_zc);
-    else
-    {   AO.type = LONG_CONSTANT_OT; AO.value = n; AO.marker = 0;
-        assemblez_1(jump_zc, AO);
-    }
-}
-
-void assembleg_0(int internal_number)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 0;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_1(int internal_number, assembly_operand o1)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0] = o1;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_2(int internal_number, assembly_operand o1,
-  assembly_operand o2)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 2;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_3(int internal_number, assembly_operand o1,
-  assembly_operand o2, assembly_operand o3)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 3;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_4(int internal_number, assembly_operand o1,
-  assembly_operand o2, assembly_operand o3,
-  assembly_operand o4)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 4;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_5(int internal_number, assembly_operand o1,
-  assembly_operand o2, assembly_operand o3,
-  assembly_operand o4, assembly_operand o5)
-{   AI.internal_number = internal_number;
-    AI.operand_count = 5;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2] = o3;
-    AI.operand[3] = o4;
-    AI.operand[4] = o5;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_0_branch(int internal_number,
-    int label)
-{
-    AI.internal_number = internal_number;
-    AI.operand_count = 1;
-    AI.operand[0].type = CONSTANT_OT;
-    AI.operand[0].value = label;
-    AI.operand[0].marker = BRANCH_MV;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_1_branch(int internal_number,
-    assembly_operand o1, int label)
-{
-    /* Some clever optimizations first. A constant is always or never equal
-       to zero. */
-    if (o1.marker == 0 && is_constant_ot(o1.type)) {
-        if ((internal_number == jz_gc && o1.value == 0)
-          || (internal_number == jnz_gc && o1.value != 0)) {
-            assembleg_0_branch(jump_gc, label);
-            /* We clear the "can't reach statement" flag here, 
-               so that "if (1)" doesn't produce that warning. */
-            execution_never_reaches_here = 0;
-            return;
-        }
-        if ((internal_number == jz_gc && o1.value != 0)
-          || (internal_number == jnz_gc && o1.value == 0)) {
-            /* assemble nothing at all! */
-            return;
-        }
-    }
-    AI.internal_number = internal_number;
-    AI.operand_count = 2;
-    AI.operand[0] = o1;
-    AI.operand[1].type = CONSTANT_OT;
-    AI.operand[1].value = label;
-    AI.operand[1].marker = BRANCH_MV;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_2_branch(int internal_number,
-    assembly_operand o1, assembly_operand o2, int label)
-{
-    AI.internal_number = internal_number;
-    AI.operand_count = 3;
-    AI.operand[0] = o1;
-    AI.operand[1] = o2;
-    AI.operand[2].type = CONSTANT_OT;
-    AI.operand[2].value = label;
-    AI.operand[2].marker = BRANCH_MV;
-    assembleg_instruction(&AI);
-}
-
-void assembleg_call_1(assembly_operand oaddr, assembly_operand o1, 
-  assembly_operand odest)
-{
-  assembleg_3(callfi_gc, oaddr, o1, odest);
-}
-
-void assembleg_call_2(assembly_operand oaddr, assembly_operand o1, 
-  assembly_operand o2, assembly_operand odest)
-{
-  assembleg_4(callfii_gc, oaddr, o1, o2, odest);
-}
-
-void assembleg_call_3(assembly_operand oaddr, assembly_operand o1, 
-  assembly_operand o2, assembly_operand o3, assembly_operand odest)
-{
-  assembleg_5(callfiii_gc, oaddr, o1, o2, o3, odest);
-}
-
-void assembleg_inc(assembly_operand o1)
-{
-  AI.internal_number = add_gc;
-  AI.operand_count = 3;
-  AI.operand[0] = o1;
-  AI.operand[1] = one_operand;
-  AI.operand[2] = o1;
-  assembleg_instruction(&AI);
-}
-
-void assembleg_dec(assembly_operand o1)
-{
-  AI.internal_number = sub_gc;
-  AI.operand_count = 3;
-  AI.operand[0] = o1;
-  AI.operand[1] = one_operand;
-  AI.operand[2] = o1;
-  assembleg_instruction(&AI);
-}
-
-void assembleg_store(assembly_operand o1, assembly_operand o2)
-{
-    /* Note the order is reversed: "o1 = o2;" */
-    assembleg_2(copy_gc, o2, o1);
-}
-
-void assembleg_jump(int n)
-{
-  if (n==-4) {
-      assembleg_1(return_gc, one_operand);
-  }
-  else if (n==-3) {
-      assembleg_1(return_gc, zero_operand); 
-  }
-  else {
-      assembleg_0_branch(jump_gc, n);
-  }
-}
-
-/* ========================================================================= */
-/*   Parsing and then calling the assembler for @ (assembly language)        */
-/*   statements                                                              */
-/* ------------------------------------------------------------------------- */
-
-static assembly_operand parse_operand_z(void)
-{   assembly_operand AO;
-
-    AO = parse_expression(ASSEMBLY_CONTEXT);
-    if (AO.type == EXPRESSION_OT)
-    {   ebf_error("variable or constant", "expression");
-        AO.type = SHORT_CONSTANT_OT;
-    }
-    return(AO);
-}
-
-static void parse_assembly_z(void)
-{   int n, min, max, indirect_addressed, error_flag = FALSE;
-    opcodez O;
-
-    AI.operand_count = 0;
-    AI.store_variable_number = -1;
-    AI.branch_label_number = -1;
-    AI.text = NULL;
-
-    opcode_names.enabled = TRUE;
-    get_next_token();
-    opcode_names.enabled = FALSE;
-
-    if (token_type == DQ_TT)
-    {   int i;
-        AI.internal_number = -1;
-
-        custom_opcode_z.name = (uchar *) token_text;
-        custom_opcode_z.version1 = instruction_set_number;
-        custom_opcode_z.version2 = instruction_set_number;
-        custom_opcode_z.extension = -1;
-        custom_opcode_z.flags = 0;
-        custom_opcode_z.op_rules = 0;
-        custom_opcode_z.flags2_set = 0;
-        custom_opcode_z.no = ZERO;
-
-        for (i=0; token_text[i]!=0; i++)
-        {   if (token_text[i] == ':')
-            {   token_text[i++] = 0;
-                break;
-            }
-        }
-        if (token_text[i] == 0)
-            error("Opcode specification should have form \"VAR:102\"");
-
-        n = -1;
-        if (strcmp(token_text, "0OP")==0)      n=ZERO;
-        if (strcmp(token_text, "1OP")==0)      n=ONE;
-        if (strcmp(token_text, "2OP")==0)      n=TWO;
-        if (strcmp(token_text, "VAR")==0)      n=VAR;
-        if (strcmp(token_text, "EXT")==0)      n=EXT;
-        if (strcmp(token_text, "VAR_LONG")==0) n=VAR_LONG;
-        if (strcmp(token_text, "EXT_LONG")==0) n=EXT_LONG;
-
-        if (i>0) token_text[i-1] = ':';
-
-        if (n==-1)
-        {   ebf_error("Expected 0OP, 1OP, 2OP, VAR, EXT, VAR_LONG or EXT_LONG",
-                token_text);
-            n = EXT;
-        }
-        custom_opcode_z.no = n;
-
-        custom_opcode_z.code = atoi(token_text+i);
-        while (isdigit(token_text[i])) i++;
-
-        {   max = 0; min = 0;
-            switch(n)
-            {   case ZERO: case ONE: max = 16; break;
-                case VAR: case VAR_LONG: min = 32; max = 64; break;
-                case EXT: case EXT_LONG: max = 256; break;
-                case TWO: max = 32; break;
-            }
-            if ((custom_opcode_z.code < min) || (custom_opcode_z.code >= max))
-            {   char range[32];
-                sprintf(range, "%d to %d", min, max-1);
-            error_named("For this operand type, opcode number must be in range",
-                    range);
-                custom_opcode_z.code = min;
-            }
-        }
-
-        while (token_text[i++] != 0)
-        {   switch(token_text[i-1])
-            {   case 'B': custom_opcode_z.flags |= Br; break;
-                case 'S': custom_opcode_z.flags |= St; break;
-                case 'T': custom_opcode_z.op_rules = TEXT; break;
-                case 'I': custom_opcode_z.op_rules = VARIAB; break;
-                case 'F': custom_opcode_z.flags2_set = atoi(token_text+i);
-                          while (isdigit(token_text[i])) i++; break;
-                default:
-                    error("Unknown flag: options are B (branch), S (store), \
-T (text), I (indirect addressing), F** (set this Flags 2 bit)");
-                    break;
-            }
-        }
-        O = custom_opcode_z;
-    }
-    else
-    {   if (token_type != OPCODE_NAME_TT)
-        {   ebf_error("an opcode name", token_text);
-            panic_mode_error_recovery();
-            return;
-        }
-        AI.internal_number = token_value;
-        O = internal_number_to_opcode_z(AI.internal_number);
-    }
-
-    indirect_addressed = (O.op_rules == VARIAB);
-
-    if (O.op_rules == TEXT)
-    {   get_next_token();
-        if (token_type != DQ_TT)
-            ebf_error("literal text in double-quotes", token_text);
-        AI.text = token_text;
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return;
-        get_next_token();
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-        {   assemblez_instruction(&AI);
-            return;
-        }
-        ebf_error("semicolon ';' after print string", token_text);
-        put_token_back();
-        return;
-    }
-
-    return_sp_as_variable = TRUE;
-    do
-    {   get_next_token();
-
-        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
-
-        if ((token_type == SEP_TT) && (token_value == ARROW_SEP))
-        {   if (AI.store_variable_number != -1)
-                error("Only one '->' store destination can be given");
-            get_next_token();
-            if ((token_type != SYMBOL_TT)
-                && (token_type != LOCAL_VARIABLE_TT))
-                ebf_error("variable name or 'sp'", token_text);
-            n = 255;
-            if (token_type == LOCAL_VARIABLE_TT) n = token_value;
-            else
-            {   if (strcmp(token_text, "sp") == 0) n = 0;
-                else
-                {   if (stypes[token_value] != GLOBAL_VARIABLE_T)
-                        error_named(
-                            "Store '->' destination not 'sp' or a variable:",
-                            token_text);
-                    else n = svals[token_value];
-                }
-            }
-            AI.store_variable_number = n;
-            continue;
-        }
-
-        if ((token_type == SEP_TT) &&
-            ((token_value == BRANCH_SEP) || (token_value == NBRANCH_SEP)))
-        {   if (AI.branch_label_number != -1)
-                error("Only one '?' branch destination can be given");
-
-            AI.branch_flag = (token_value == BRANCH_SEP);
-
-            opcode_names.enabled = TRUE;
-            get_next_token();
-            opcode_names.enabled = FALSE;
-
-            n = -2;
-            if ((token_type == OPCODE_NAME_TT)
-                && (token_value == rfalse_zc)) n = -3;
-            else
-            if ((token_type == OPCODE_NAME_TT)
-                && (token_value == rtrue_zc)) n = -4;
-            else
-            {   if (token_type == SYMBOL_TT)
-                {   put_token_back();
-                    n = parse_label();
-                }
-                else
-                    ebf_error("label name after '?' or '?~'", token_text);
-            }
-            AI.branch_label_number = n;
-            continue;
-        }
-
-        if (AI.operand_count == 8)
-        {   error("No assembly instruction may have more than 8 operands");
-            panic_mode_error_recovery(); break;
-        }
-
-        if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
-        {   if (!indirect_addressed)
-                error("This opcode does not use indirect addressing");
-            if (AI.operand_count > 0)
-            error("Indirect addressing can only be used on the first operand");
-            AI.operand[AI.operand_count++] = parse_operand_z();
-            get_next_token();
-            if (!((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP)))
-            {   ebf_error("']'", token_text);
-                put_token_back();
-            }
-        }
-        else
-        {   put_token_back();
-            AI.operand[AI.operand_count++] = parse_operand_z();
-            if ((indirect_addressed) && (AI.operand_count == 1)
-                && (AI.operand[AI.operand_count-1].type == VARIABLE_OT))
-            {   AI.operand[AI.operand_count-1].type = SHORT_CONSTANT_OT;
-                AI.operand[AI.operand_count-1].marker = VARIABLE_MV;
-            }
-        }
-
-    } while (TRUE);
-
-    return_sp_as_variable = FALSE;
-
-
-    if (O.version1 == 0)
-    {   error_named("Opcode unavailable in this Z-machine version:",
-            opcode_names.keywords[AI.internal_number]);
-        return;
-    }
-
-    if (((O.flags) & Br) != 0)
-    {   if (AI.branch_label_number == -1)
-        {   error_flag = TRUE;
-            AI.branch_label_number = -2;
-        }
-    }
-    else
-    {   if (AI.branch_label_number != -1)
-        {   error_flag = TRUE;
-            AI.branch_label_number = -1;
-        }
-    }
-    if (((O.flags) & St) != 0)
-    {   if (AI.store_variable_number == -1)
-        {   if (AI.operand_count == 0)
-            {   error_flag = TRUE;
-                AI.store_variable_number = 255;
-            }
-            else
-            {   AI.store_variable_number
-                    = AI.operand[--AI.operand_count].value;
-                if (AI.operand[AI.operand_count].type != VARIABLE_OT)
-            error("Store destination (the last operand) is not a variable");
-            }
-        }
-    }
-    else
-    {   if (AI.store_variable_number != -1)
-        {   error_flag = TRUE;
-            AI.store_variable_number = -1;
-        }
-    }
-
-    min = 0; max = 0;
-    switch(O.no)
-    {   case TWO:      min = 2; max = 2;
-                       /* Exception for the V6 set_colour, which can take
-                          a third argument, thus forcing it into VAR form: */
-                       if ((version_number == 6) && (O.code == 0x1b)) max = 3;
-                       /* Also an exception for je, which can take from 1
-                          argument (useless) to 4 arguments */
-                       if (O.code == 0x01) { min = 1; max = 4; }
-                       break;
-        case VAR:      min = 0; max = 4; break;
-        case VAR_LONG: min = 0; max = 8; break;
-        case ONE:      min = 1; max = 1; break;
-        case ZERO:     min = 0; max = 0; break;
-        case EXT:      min = 0; max = 4; break;
-        case EXT_LONG: min = 0; max = 8; break;
-    }
-
-    if ((AI.operand_count >= min) && (AI.operand_count <= max))
-        assemblez_instruction(&AI);
-    else error_flag = TRUE;
-
-    if (error_flag)
-    {   make_opcode_syntax_z(O);
-        error_named("Assembly mistake: syntax is",
-            opcode_syntax_string);
-    }
-}
-
-static assembly_operand parse_operand_g(void)
-{   assembly_operand AO;
-
-    AO = parse_expression(ASSEMBLY_CONTEXT);
-    if (AO.type == EXPRESSION_OT)
-    {   ebf_error("variable or constant", "expression");
-        AO.type = CONSTANT_OT;
-    }
-    return(AO);
-}
-
-static void parse_assembly_g(void)
-{
-  opcodeg O;
-  assembly_operand AO;
-  int error_flag = FALSE, is_macro = FALSE;
-
-  AI.operand_count = 0;
-
-  opcode_names.enabled = TRUE;
-  opcode_macros.enabled = TRUE;
-  get_next_token();
-  opcode_names.enabled = FALSE;
-  opcode_macros.enabled = FALSE;
-
-  if (token_type == DQ_TT) {
-    char *cx;
-    int badflags;
-
-    AI.internal_number = -1;
-
-    /* The format is @"FlagsCount:Code". Flags (which are optional)
-       can include "S" for store, "SS" for two stores, "B" for branch
-       format, "R" if execution never continues after the opcode. The
-       Count is the number of arguments (currently limited to 0-9),
-       and the Code is a decimal integer representing the opcode
-       number.
-
-       So: @"S3:123" for a three-argument opcode (load, load, store)
-       whose opcode number is (decimal) 123. Or: @"2:234" for a
-       two-argument opcode (load, load) whose number is 234. */
-
-    custom_opcode_g.name = (uchar *) token_text;
-    custom_opcode_g.flags = 0;
-    custom_opcode_g.op_rules = 0;
-    custom_opcode_g.no = 0;
-
-    badflags = FALSE;
-
-    for (cx = token_text; *cx && *cx != ':'; cx++) {
-      if (badflags)
-      continue;
-
-      switch (*cx) {
-      case 'S':
-      if (custom_opcode_g.flags & St)
-        custom_opcode_g.flags |= St2;
-      else
-        custom_opcode_g.flags |= St;
-      break;
-      case 'B':
-      custom_opcode_g.flags |= Br;
-      break;
-      case 'R':
-      custom_opcode_g.flags |= Rf;
-      break;
-      default:
-      if (isdigit(*cx)) {
-        custom_opcode_g.no = (*cx) - '0';
-        break;
-      }
-      badflags = TRUE;
-      error("Unknown custom opcode flag: options are B (branch), \
-S (store), SS (two stores), R (execution never continues)");
-      break;
-      }
-    }
-
-    if (*cx != ':') {
-      error("Custom opcode must have colon");
-    }
-    else {
-      cx++;
-      if (!(*cx))
-      error("Custom opcode must have colon followed by opcode number");
-      else
-      custom_opcode_g.code = atoi(cx);
-    }
-
-    O = custom_opcode_g;
-  }
-  else {
-    if (token_type != OPCODE_NAME_TT && token_type != OPCODE_MACRO_TT) {
-      ebf_error("an opcode name", token_text);
-      panic_mode_error_recovery();
-      return;
-    }
-    AI.internal_number = token_value;
-    if (token_type == OPCODE_MACRO_TT) {
-      O = internal_number_to_opmacro_g(AI.internal_number);
-      is_macro = TRUE;
-    }
-    else
-      O = internal_number_to_opcode_g(AI.internal_number);
-  }
-  
-  return_sp_as_variable = TRUE;
-
-  while (1) {
-    get_next_token();
-    
-    if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) 
-      break;
-
-    if (AI.operand_count == 8) {
-      error("No assembly instruction may have more than 8 operands");
-      panic_mode_error_recovery(); 
-      break;
-    }
-
-    if ((O.flags & Br) && (AI.operand_count == O.no-1)) {
-      if (!((token_type == SEP_TT) && (token_value == BRANCH_SEP))) {
-        error_flag = TRUE;
-        error("Branch opcode must have '?' label");
-        put_token_back();
-      }
-      AO.type = CONSTANT_OT;
-      AO.value = parse_label();
-      AO.marker = BRANCH_MV;
-    }
-    else {
-      put_token_back();
-      AO = parse_operand_g();
-    }
-
-    AI.operand[AI.operand_count] = AO;
-    AI.operand_count++;
-  }
-
-  return_sp_as_variable = FALSE;
-
-  if (O.no != AI.operand_count) {
-    error_flag = TRUE;
-  }
-
-  if (!error_flag) {
-    if (is_macro)
-      assembleg_macro(&AI);
-    else
-      assembleg_instruction(&AI);
-  }
-
-  if (error_flag) {
-    make_opcode_syntax_g(O);
-    error_named("Assembly mistake: syntax is",
-      opcode_syntax_string);
-  }
-}
-
-extern void parse_assembly(void)
-{
-  if (!glulx_mode)
-    parse_assembly_z();
-  else
-    parse_assembly_g();
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void asm_begin_pass(void)
-{   no_instructions = 0;
-    zmachine_pc = 0;
-    no_sequence_points = 0;
-    next_label = 0;
-    next_sequence_point = 0;
-    zcode_ha_size = 0;
-}
-
-extern void init_asm_vars(void)
-{   int i;
-
-    for (i=0;i<16;i++) flags2_requirements[i]=0;
-
-    uses_unicode_features = FALSE;
-    uses_memheap_features = FALSE;
-    uses_acceleration_features = FALSE;
-    uses_float_features = FALSE;
-
-    sequence_point_follows = TRUE;
-    label_moved_error_already_given = FALSE;
-
-    initialise_memory_block(&zcode_area);
-}
-
-extern void asm_allocate_arrays(void)
-{   if ((debugfile_switch) && (MAX_LABELS < 2000)) MAX_LABELS = 2000;
-
-    variable_tokens = my_calloc(sizeof(int32),  
-        MAX_LOCAL_VARIABLES+MAX_GLOBAL_VARIABLES, "variable tokens");
-    variable_usage = my_calloc(sizeof(int),  
-        MAX_LOCAL_VARIABLES+MAX_GLOBAL_VARIABLES, "variable usage");
-
-    label_offsets = my_calloc(sizeof(int32), MAX_LABELS, "label offsets");
-    label_symbols = my_calloc(sizeof(int32), MAX_LABELS, "label symbols");
-    label_next = my_calloc(sizeof(int), MAX_LABELS, "label dll 1");
-    label_prev = my_calloc(sizeof(int), MAX_LABELS, "label dll 1");
-    sequence_point_labels
-        = my_calloc(sizeof(int), MAX_LABELS, "sequence point labels");
-    sequence_point_locations
-        = my_calloc(sizeof(debug_location),
-                    MAX_LABELS,
-                    "sequence point locations");
-
-    zcode_holding_area = my_malloc(MAX_ZCODE_SIZE,"compiled routine code area");
-    zcode_markers = my_malloc(MAX_ZCODE_SIZE, "compiled routine code area");
-
-    named_routine_symbols
-        = my_calloc(sizeof(int32), MAX_SYMBOLS, "named routine symbols");
-}
-
-extern void asm_free_arrays(void)
-{
-    my_free(&variable_tokens, "variable tokens");
-    my_free(&variable_usage, "variable usage");
-
-    my_free(&label_offsets, "label offsets");
-    my_free(&label_symbols, "label symbols");
-    my_free(&label_next, "label dll 1");
-    my_free(&label_prev, "label dll 2");
-    my_free(&sequence_point_labels, "sequence point labels");
-    my_free(&sequence_point_locations, "sequence point locations");
-
-    my_free(&zcode_holding_area, "compiled routine code area");
-    my_free(&zcode_markers, "compiled routine code markers");
-
-    my_free(&named_routine_symbols, "named routine symbols");
-    deallocate_memory_block(&zcode_area);
-}
-
-/* ========================================================================= */
diff --git a/bpatch.c b/bpatch.c
deleted file mode 100644 (file)
index ccc87ba..0000000
--- a/bpatch.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "bpatch" : Keeps track of, and finally acts on, backpatch markers,      */
-/*              correcting symbol values not known at compilation time       */
-/*                                                                           */
-/* 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"
-
-memory_block zcode_backpatch_table, zmachine_backpatch_table;
-int32 zcode_backpatch_size, zmachine_backpatch_size;
-
-/* ------------------------------------------------------------------------- */
-/*   The mending operation                                                   */
-/* ------------------------------------------------------------------------- */
-
-int backpatch_marker, backpatch_size, backpatch_error_flag;
-
-static int32 backpatch_value_z(int32 value)
-{   /*  Corrects the quantity "value" according to backpatch_marker  */
-
-    ASSERT_ZCODE();
-
-    if (asm_trace_level >= 4)
-        printf("BP %s applied to %04x giving ",
-            describe_mv(backpatch_marker), value);
-
-    switch(backpatch_marker)
-    {   case STRING_MV:
-            value += strings_offset/scale_factor; break;
-        case ARRAY_MV:
-            value += variables_offset; break;
-        case IROUTINE_MV:
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset/scale_factor;
-            break;
-        case VROUTINE_MV:
-            if ((value<0) || (value>=VENEER_ROUTINES))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error
-                    ("Backpatch veneer routine number out of range"))
-                {   printf("Illegal BP veneer routine number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            value = veneer_routine_address[value]; 
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset/scale_factor;
-            break;
-        case NO_OBJS_MV:
-            value = no_objects; break;
-        case INCON_MV:
-            if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error
-                    ("Backpatch system constant number out of range"))
-                {   printf("Illegal BP system constant number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            value = value_of_system_constant(value); break;
-        case DWORD_MV:
-            value = dictionary_offset + 7 +
-                    final_dict_order[value]*((version_number==3)?7:9);
-            break;
-        case ACTION_MV:
-            break;
-        case INHERIT_MV:
-            value = 256*zmachine_paged_memory[value + prop_values_offset]
-                    + zmachine_paged_memory[value + prop_values_offset + 1];
-            break;
-        case INHERIT_INDIV_MV:
-            value = 256*zmachine_paged_memory[value
-                        + individuals_offset]
-                    + zmachine_paged_memory[value
-                        + individuals_offset + 1];
-            break;
-        case INDIVPT_MV:
-            value += individuals_offset;
-            break;
-        case MAIN_MV:
-            value = symbol_index("Main", -1);
-            if (stypes[value] != ROUTINE_T)
-                error("No 'Main' routine has been defined");
-            sflags[value] |= USED_SFLAG;
-            value = svals[value];
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset/scale_factor;
-            break;
-        case SYMBOL_MV:
-            if ((value<0) || (value>=no_symbols))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error("Backpatch symbol number out of range"))
-                {   printf("Illegal BP symbol number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            if (sflags[value] & UNKNOWN_SFLAG)
-            {   if (!(sflags[value] & UERROR_SFLAG))
-                {   sflags[value] |= UERROR_SFLAG;
-                    error_named_at("No such constant as",
-                        (char *) symbs[value], slines[value]);
-                }
-            }
-            else
-            if (sflags[value] & CHANGE_SFLAG)
-            {   sflags[value] &= (~(CHANGE_SFLAG));
-                backpatch_marker = (svals[value]/0x10000);
-                if ((backpatch_marker < 0)
-                    || (backpatch_marker > LARGEST_BPATCH_MV))
-                {
-                    if (no_link_errors == 0)
-                    {   compiler_error_named(
-                        "Illegal backpatch marker attached to symbol",
-                        (char *) symbs[value]);
-                        backpatch_error_flag = TRUE;
-                    }
-                }
-                else
-                    svals[value] = backpatch_value_z((svals[value]) % 0x10000);
-            }
-
-            sflags[value] |= USED_SFLAG;
-            {   int t = stypes[value];
-                value = svals[value];
-                switch(t)
-                {   case ROUTINE_T: 
-                        if (OMIT_UNUSED_ROUTINES)
-                            value = df_stripped_address_for_address(value);
-                        value += code_offset/scale_factor; 
-                        break;
-                    case ARRAY_T: value += variables_offset; break;
-                }
-            }
-            break;
-        default:
-            if (no_link_errors > 0) break;
-            if (compiler_error("Illegal backpatch marker"))
-            {   printf("Illegal backpatch marker %d value %04x\n",
-                    backpatch_marker, value);
-                backpatch_error_flag = TRUE;
-            }
-            break;
-    }
-
-    if (asm_trace_level >= 4) printf(" %04x\n", value);
-
-    return(value);
-}
-
-static int32 backpatch_value_g(int32 value)
-{   /*  Corrects the quantity "value" according to backpatch_marker  */
-    int32 valaddr;
-
-    ASSERT_GLULX();
-
-    if (asm_trace_level >= 4)
-        printf("BP %s applied to %04x giving ",
-            describe_mv(backpatch_marker), value);
-
-    switch(backpatch_marker)
-    {
-        case STRING_MV:
-            if (value <= 0 || value > no_strings)
-              compiler_error("Illegal string marker.");
-            value = strings_offset + compressed_offsets[value-1]; break;
-        case IROUTINE_MV:
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset;
-            break;
-        case ARRAY_MV:
-            value += arrays_offset; break;
-        case VARIABLE_MV:
-            value = variables_offset + (4*value); break;
-        case OBJECT_MV:
-            value = object_tree_offset + (OBJECT_BYTE_LENGTH*(value-1)); 
-            break;
-        case VROUTINE_MV:
-            if ((value<0) || (value>=VENEER_ROUTINES))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error
-                    ("Backpatch veneer routine number out of range"))
-                {   printf("Illegal BP veneer routine number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            value = veneer_routine_address[value];
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset;
-            break;
-        case NO_OBJS_MV:
-            value = no_objects; break;
-        case INCON_MV:
-            if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error
-                    ("Backpatch system constant number out of range"))
-                {   printf("Illegal BP system constant number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            value = value_of_system_constant(value); break;
-        case DWORD_MV:
-            value = dictionary_offset + 4 
-              + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
-            break;
-        case ACTION_MV:
-            break;
-        case INHERIT_MV:
-            valaddr = (prop_values_offset - Write_RAM_At) + value;
-            value = ReadInt32(zmachine_paged_memory + valaddr);
-            break;
-        case INHERIT_INDIV_MV:
-            error("*** No individual property storage in Glulx ***");
-            break;
-        case INDIVPT_MV:
-            value += individuals_offset;
-            break;
-        case MAIN_MV:
-            value = symbol_index("Main", -1);
-            if (stypes[value] != ROUTINE_T)
-                error("No 'Main' routine has been defined");
-            sflags[value] |= USED_SFLAG;
-            value = svals[value];
-            if (OMIT_UNUSED_ROUTINES)
-                value = df_stripped_address_for_address(value);
-            value += code_offset;
-            break;
-        case SYMBOL_MV:
-            if ((value<0) || (value>=no_symbols))
-            {   if (no_link_errors > 0) break;
-                if (compiler_error("Backpatch symbol number out of range"))
-                {   printf("Illegal BP symbol number: %d\n", value);
-                    backpatch_error_flag = TRUE;
-                }
-                value = 0;
-                break;
-            }
-            if (sflags[value] & UNKNOWN_SFLAG)
-            {   if (!(sflags[value] & UERROR_SFLAG))
-                {   sflags[value] |= UERROR_SFLAG;
-                    error_named_at("No such constant as",
-                        (char *) symbs[value], slines[value]);
-                }
-            }
-            else
-            if (sflags[value] & CHANGE_SFLAG)
-            {   sflags[value] &= (~(CHANGE_SFLAG));
-                backpatch_marker = smarks[value];
-                if ((backpatch_marker < 0)
-                    || (backpatch_marker > LARGEST_BPATCH_MV))
-                {
-                    if (no_link_errors == 0)
-                    {   compiler_error_named(
-                        "Illegal backpatch marker attached to symbol",
-                        (char *) symbs[value]);
-                        backpatch_error_flag = TRUE;
-                    }
-                }
-                else
-                    svals[value] = backpatch_value_g(svals[value]);
-            }
-
-            sflags[value] |= USED_SFLAG;
-            {   int t = stypes[value];
-                value = svals[value];
-                switch(t)
-                {
-                    case ROUTINE_T:
-                        if (OMIT_UNUSED_ROUTINES)
-                            value = df_stripped_address_for_address(value);
-                        value += code_offset;
-                        break;
-                    case ARRAY_T: value += arrays_offset; break;
-                    case OBJECT_T:
-                    case CLASS_T:
-                      value = object_tree_offset + 
-                        (OBJECT_BYTE_LENGTH*(value-1)); 
-                      break;
-                    case ATTRIBUTE_T:
-                      /* value is unchanged */
-                      break;
-                    case CONSTANT_T:
-                    case INDIVIDUAL_PROPERTY_T:
-                      /* value is unchanged */
-                      break;
-                    default:
-                      error("*** Illegal backpatch marker in forward-declared \
-symbol");
-                      break;
-                }
-            }
-            break;
-        default:
-            if (no_link_errors > 0) break;
-            if (compiler_error("Illegal backpatch marker"))
-            {   printf("Illegal backpatch marker %d value %04x\n",
-                    backpatch_marker, value);
-                backpatch_error_flag = TRUE;
-            }
-            break;
-    }
-
-    if (asm_trace_level >= 4) printf(" %04x\n", value);
-
-    return(value);
-}
-
-extern int32 backpatch_value(int32 value)
-{
-  if (!glulx_mode)
-    return backpatch_value_z(value);
-  else
-    return backpatch_value_g(value);
-}
-
-static void backpatch_zmachine_z(int mv, int zmachine_area, int32 offset)
-{   if (module_switch)
-    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
-    }
-    else
-    {   if (mv == OBJECT_MV) return;
-        if (mv == IDENT_MV) return;
-        if (mv == ACTION_MV) return;
-    }
-
-    /* printf("MV %d ZA %d Off %04x\n", mv, zmachine_area, offset); */
-
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, mv);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, zmachine_area);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, offset/256);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, offset%256);
-}
-
-static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
-{   if (module_switch)
-    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
-    }
-    else
-    {   if (mv == IDENT_MV) return;
-        if (mv == ACTION_MV) return;
-    }
-
-/* The backpatch table format for Glulx:
-   First, the marker byte.
-   Then, the zmachine area being patched.
-   Then the four-byte address.
-*/
-
-/*    printf("+MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);  */
-
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, mv);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, zmachine_area);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 24) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 16) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 8) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset) & 0xFF);
-}
-
-extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
-{
-  if (!glulx_mode)
-    backpatch_zmachine_z(mv, zmachine_area, offset);
-  else
-    backpatch_zmachine_g(mv, zmachine_area, offset);
-}
-
-extern void backpatch_zmachine_image_z(void)
-{   int bm = 0, zmachine_area; int32 offset, value, addr = 0;
-    ASSERT_ZCODE();
-    backpatch_error_flag = FALSE;
-    while (bm < zmachine_backpatch_size)
-    {   backpatch_marker
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
-        zmachine_area
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
-        offset
-          = 256*read_byte_from_memory_block(&zmachine_backpatch_table,bm+2)
-            + read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
-        bm += 4;
-
-        switch(zmachine_area)
-        {   case PROP_DEFAULTS_ZA:   addr = prop_defaults_offset; break;
-            case PROP_ZA:            addr = prop_values_offset; break;
-            case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
-            case DYNAMIC_ARRAY_ZA:   addr = variables_offset; break;
-            default:
-                if (no_link_errors == 0)
-                    if (compiler_error("Illegal area to backpatch"))
-                        backpatch_error_flag = TRUE;
-        }
-        addr += offset;
-
-        value = 256*zmachine_paged_memory[addr]
-                + zmachine_paged_memory[addr+1];
-        value = backpatch_value_z(value);
-        zmachine_paged_memory[addr] = value/256;
-        zmachine_paged_memory[addr+1] = value%256;
-
-        if (backpatch_error_flag)
-        {   backpatch_error_flag = FALSE;
-            if (no_link_errors == 0)
-                printf("*** MV %d ZA %d Off %04x ***\n",
-                    backpatch_marker, zmachine_area, offset);
-        }
-    }
-}
-
-extern void backpatch_zmachine_image_g(void)
-{   int bm = 0, zmachine_area; int32 offset, value, addr = 0;
-    ASSERT_GLULX();
-    backpatch_error_flag = FALSE;
-    while (bm < zmachine_backpatch_size)
-    {   backpatch_marker
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
-        zmachine_area
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
-        offset = read_byte_from_memory_block(&zmachine_backpatch_table, bm+2);
-        offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
-        offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+4);
-        offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+5);
-            bm += 6;
-
-        /* printf("-MV %d ZA %d Off %06x\n", backpatch_marker, zmachine_area, offset);  */
-
-            switch(zmachine_area) {   
-        case PROP_DEFAULTS_ZA:   addr = prop_defaults_offset+4; break;
-        case PROP_ZA:            addr = prop_values_offset; break;
-        case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
-        case ARRAY_ZA:           addr = arrays_offset; break;
-        case GLOBALVAR_ZA:       addr = variables_offset; break;
-        default:
-          if (no_link_errors == 0)
-            if (compiler_error("Illegal area to backpatch"))
-              backpatch_error_flag = TRUE;
-        }
-        addr = addr + offset - Write_RAM_At;
-
-        value = (zmachine_paged_memory[addr] << 24)
-                | (zmachine_paged_memory[addr+1] << 16)
-                | (zmachine_paged_memory[addr+2] << 8)
-                | (zmachine_paged_memory[addr+3]);
-        value = backpatch_value_g(value);
-        zmachine_paged_memory[addr] = (value >> 24) & 0xFF;
-        zmachine_paged_memory[addr+1] = (value >> 16) & 0xFF;
-        zmachine_paged_memory[addr+2] = (value >> 8) & 0xFF;
-        zmachine_paged_memory[addr+3] = (value) & 0xFF;
-
-        if (backpatch_error_flag)
-        {   backpatch_error_flag = FALSE;
-            if (no_link_errors == 0)
-                printf("*** MV %d ZA %d Off %04x ***\n",
-                    backpatch_marker, zmachine_area, offset);
-        }
-    }
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_bpatch_vars(void)
-{   initialise_memory_block(&zcode_backpatch_table);
-    initialise_memory_block(&zmachine_backpatch_table);
-}
-
-extern void bpatch_begin_pass(void)
-{   zcode_backpatch_size = 0;
-    zmachine_backpatch_size = 0;
-}
-
-extern void bpatch_allocate_arrays(void)
-{
-}
-
-extern void bpatch_free_arrays(void)
-{   deallocate_memory_block(&zcode_backpatch_table);
-    deallocate_memory_block(&zmachine_backpatch_table);
-}
-
-/* ========================================================================= */
diff --git a/chars.c b/chars.c
deleted file mode 100644 (file)
index e91e9c1..0000000
--- a/chars.c
+++ /dev/null
@@ -1,1324 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "chars" : Character set mappings and the Z-machine alphabet table       */
-/*                                                                           */
-/* 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/                  */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-/*  Inform uses six different character representations:                     */
-/*                                                                           */
-/*      ASCII      plain ASCII characters in range $20 to $7e                */
-/*                     (unsigned 7-bit number)                               */
-/*      Source     raw bytes from source code                                */
-/*                     (unsigned 8-bit number)                               */
-/*      ISO        plain ASCII or ISO 8859-1 to -9, according to value       */
-/*                     character_set_setting == 0 or 1 to 9                  */
-/*                 in Unicode mode (character_set_unicode), individual       */
-/*                     UTF-8 bytes                                           */
-/*                     (unsigned 8-bit number)                               */
-/*      ZSCII      the Z-machine's character set                             */
-/*                     (unsigned 10-bit number)                              */
-/*      textual    such as the text @'e to mean e-acute                      */
-/*                     or @$03a3 to mean capital Greek sigma                 */
-/*                 in Unicode mode, the operations manipulating multibyte    */
-/*                     UCS representations are included in text routines     */
-/*                     (sequence of ASCII characters)                        */
-/*      Unicode    a unifying character set holding all possible characters  */
-/*                     Inform can ever deal with                             */
-/*                     (unsigned 16-bit number)                              */
-/*                                                                           */
-/*  Conversion can always be made down this list, but generally not up.      */
-/*  Note that all ASCII values are the same in any version of ISO            */
-/*  and in Unicode.                                                          */
-/*                                                                           */
-/*  There is a seventh form: sequences of 5-bit "Z-chars" which encode       */
-/*  ZSCII into the story file in compressed form.  Conversion of ZSCII to    */
-/*  and from Z-char sequences, although it uses the alphabet table, is done  */
-/*  in "text.c".                                                             */
-/* ------------------------------------------------------------------------- */
-/*  The main data structures need to be modified in mid-compilation, but     */
-/*  several of them depend on each other, and must remain consistent;        */
-/*  and rebuilding one sometimes uses conversion routines depending on       */
-/*  information held in the others:                                          */
-/*                                                                           */
-/*      Structure                   If changed, need to rebuild:             */
-/*      character_set_setting       source_to_iso_grid[]                     */
-/*                                  zscii_to_unicode_grid[]                  */
-/*                                  zscii_to_iso_grid[]                      */
-/*                                  iso_to_unicode_grid[]                    */
-/*      alphabet[][]                iso_to_alphabet_grid[]                   */
-/*                                  zscii_to_alphabet_grid[]                 */
-/*      zscii_to_unicode_grid[]     iso_to_alphabet_grid[]                   */
-/*      source_to_iso_grid[]        <nothing>                                */
-/*      iso_to_alphabet_grid[]      <nothing>                                */
-/*      zscii_to_alphabet_grid[]    <nothing>                                */
-/*      zscii_to_iso_grid[]         <nothing>                                */
-/*                                                                           */
-/*      (zscii_to_iso_grid[] is made whenever iso_to_alphabet_grid[] is      */
-/*      made but does not depend on alphabet[].)                             */
-/*                                                                           */
-/*      Conversion routine          Makes use of:                            */
-/*      iso_to_unicode              character_set_setting                    */
-/*      unicode_to_zscii            character_set_setting                    */
-/*                                  zscii_to_unicode_grid[]                  */
-/*      zscii_to_unicode            character_set_setting                    */
-/*                                  zscii_to_unicode_grid[]                  */
-/*      text_to_unicode             <nothing>                                */
-/*      zscii_to_text               character_set_setting                    */
-/*                                  zscii_to_unicode_grid[]                  */
-/*                                  zscii_to_iso_grid[]                      */
-/*                                                                           */
-/*  For example, if we want to change alphabet[][] then we can safely        */
-/*  use any of the conversion routines while working on the change, but      */
-/*  must rebuild the iso_to_alphabet_grid[] before allowing Inform to        */
-/*  continue compiling.                                                      */
-/* ------------------------------------------------------------------------- */
-
-#include "header.h"
-
-uchar source_to_iso_grid[0x100];       /* Filters source code into legal ISO */
-
-int32 iso_to_unicode_grid[0x100];      /* Filters ISO into Unicode           */
-
-int character_digit_value[128];        /* Parsing of binary, decimal and hex */
-
-static char *accents =                 /* Standard 0.2 stock of accented...  */
-
-   ":a:o:u:A:O:Uss>><<:e:i:y:E:I'a'e'i'o'u'y'A'E'I'O'U'Y`a`e`i`o`u\
-`A`E`I`O`U^a^e^i^o^u^A^E^I^O^UoaoA/o/O~a~n~o~A~N~OaeAEcccCthetThEtLLoeOE!!??";
-
-                                       /* ...characters, numbered upwards    */
-                                       /* from 155                           */
-
-/* ------------------------------------------------------------------------- */
-
-uchar alphabet[3][27];                  /* The alphabet table. */
-
-int alphabet_modified;                 /* Has the default been changed?      */
-
-char alphabet_used[78];                /* Flags (holding 'N' or 'Y') for
-                                          which of the Z-alphabet letters
-                                          have actually been encrypted       */
-
-/* ------------------------------------------------------------------------- */
-
-int iso_to_alphabet_grid[0x100];
-
-/* This array combines two conversion processes which have to run quickly:
-   an ISO character n is being converted for text purposes into a stream
-   of Z-chars (anything from 1 up to 8 of these).  Unicode but non-ISO
-   characters are also converted from text, but far less often, and
-   different (and slower) methods are used to carry this out.
-
-   iso_to_alphabet_grid[n]
-       =  i   if the character exists in ZSCII and is located at
-              position i in the Z-machine alphabet (where 0 to 25
-              give positions in A0, 26 to 51 in A1 and 52 to 77 in A2);
-
-          -z  if the character exists in ZSCII as value z, but is not
-              located anywhere in the Z-machine alphabet;
-
-          -5  if the character does not exist in ZSCII.  (It will still
-              be printable using an 8-Z-char sequence to encode it in
-              Unicode form, but there's no ZSCII form.)
-
-   Note that ISO tilde ~ is interpreted as ZSCII double-quote ",
-   and ISO circumflex ^ is interpreted as ZSCII new-line, in accordance
-   with the Inform syntax for strings.  This is automatic from the
-   structure of alphabet[][]:
-
-   alphabet[i][j] = the ZSCII code of letter j (0 to 25)
-                        in alphabet i (0 to 2)
-
-                    _except that_
-
-                    alphabet[2][0] is ignored by the Z-machine and Inform
-                                   (char 0 in A2 is an escape)
-                    alphabet[2][1] is ignored by the Z-machine
-                                   (char 1 in A2 means new-line)
-                                   but used by Inform to hold ISO circumflex
-                                   so that ^ is translated as new-line
-                    alphabet[2][19] is used by Inform to hold ISO tilde
-                                   so that ~ is translated as ": after
-                                   compilation, when the alphabet table is
-                                   written into the Z-machine, this entry
-                                   is changed back to ".
-
-   Note that the alphabet can only hold ZSCII values between 0 and 255.
-
-   The array is dimensioned as [3][27], not [3][26], to make it easier to
-   initialise using strcpy (see below), but the zero entries [x][26] are
-   not used                                                                 */
-
-int zscii_to_alphabet_grid[0x100];
-
-/* The same, except that the index is a ZSCII character, not an ISO one.    */
-
-int zscii_to_iso_grid[0x100];      /* Converts ZSCII between 0 and 255 to
-                                      codes in current ISO set: or to 0 if
-                                      code isn't in the current ISO set.    */
-
-static void make_iso_to_alphabet_grid(void)
-{   int i, j, k; int z;
-
-    for (j=0; j<0x100; j++)
-    {   zscii_to_iso_grid[j] = 0;
-        zscii_to_alphabet_grid[j] = -j;
-    }
-
-    for (j=0; j<0x100; j++)
-    {   iso_to_alphabet_grid[j]=-5;
-        if ((j >= 0x20) && (j <= 0x7e))
-        {   iso_to_alphabet_grid[j] = -j;
-            zscii_to_iso_grid[j] = j;
-        }
-        if ((j >= 0xa1) && (j <= 0xff))
-        {   z = unicode_to_zscii(iso_to_unicode(j));
-            if (character_set_setting != 0)
-                zscii_to_iso_grid[z] = j;
-            iso_to_alphabet_grid[j] = -z;
-        }
-        iso_to_unicode_grid[j] = iso_to_unicode(j);
-    }
-    for (j=0; j<3; j++)
-        for (k=(j<2?0:1); k<26; k++)
-            {   i=(int) ((alphabet[j])[k]);
-                zscii_to_alphabet_grid[i] = k + j*26;
-                iso_to_alphabet_grid[zscii_to_iso_grid[i]] = k + j*26;
-            }
-}
-
-extern void map_new_zchar(int32 unicode)
-{   /*  Attempts to enter the given Unicode character into the "alphabet[]"
-        array, in place of one which has not so far been used in the
-        compilation of the current file.  This may of course fail.           */
-
-    int i, j; int zscii;
-
-    zscii = unicode_to_zscii(unicode);
-
-    /*  Out of ZSCII range?  */
-    if ((zscii == 5) || (zscii >= 0x100))
-    {   unicode_char_error(
-            "Character must first be entered into Zcharacter table:", unicode);
-        return;
-    }
-
-    /*  Already there?  */
-    for (i=0;i<3;i++) for (j=0;j<26;j++)
-        if (alphabet[i][j] == zscii) return;
-
-    /*  A0 and A1 are never changed.  Try to find a place in alphabet A2:
-
-        xx0123456789.,!?_#'~/\-:()
-          ^^^^^^^^^^  ^^^^^ ^^^^^^
-
-        The letters marked ^ are considered to be replaceable, as long as
-        they haven't yet been used in any text already encoded, and haven't
-        already been replaced.  The routine works along from the left, since
-        numerals are more of a luxury than punctuation.                      */
-
-    for (i=2; i<26; i++)
-    {   if ((i == 12) || (i == 13) || (i == 19)) continue;
-        if (alphabet_used[52+i] == 'N')
-        {   alphabet_used[52+i] = 'Y';
-            alphabet[2][i] = zscii;
-            alphabet_modified = TRUE;
-            make_iso_to_alphabet_grid();
-            return;
-        }
-    }
-}
-
-extern void new_alphabet(char *text, int which_alph)
-{
-    /*  Called three times in succession, with which_alph = 0, 1, 2  */
-
-    int i, j, zscii; int32 unicode;
-
-    alphabet_modified = TRUE;
-
-    if (which_alph == 2)
-    {   i=3; alphabet[2][2] = '~';
-    }
-    else i=0;
-
-    for (j=0; i<26; i++)
-    {   if (text[j] == 0) goto WrongSizeError;
-
-        unicode = text_to_unicode(text+j);
-        j += textual_form_length;
-
-        zscii = unicode_to_zscii(unicode);
-        if ((zscii == 5) || (zscii >= 0x100))
-            unicode_char_error("Character can't be used in alphabets unless \
-entered into Zcharacter table", unicode);
-        else alphabet[which_alph][i] = zscii;
-    }
-
-    if (text[j] != 0)
-    {   WrongSizeError:
-        if (which_alph == 2)
-            error("Alphabet string must give exactly 23 characters");
-        else
-            error("Alphabet string must give exactly 26 characters");
-    }
-
-    if (which_alph == 2)
-    {   int test_dups[0x100];
-        for (i=0; i<0x100; i++) test_dups[i] = 0;
-        for (i=0; i<3; i++) for (j=0; j<26; j++)
-        {   if (test_dups[alphabet[i][j]]++ == 1)
-                unicode_char_error("Character duplicated in alphabet:",
-                    zscii_to_unicode(alphabet[i][j]));
-        }
-
-        make_iso_to_alphabet_grid();
-    }
-}
-
-static void read_source_to_iso_file(uchar *uccg)
-{   FILE *charset_file;
-    char cs_buff[256];
-    char *p;
-    int i=0;
-
-    charset_file=fopen(Charset_Map, "r");
-    if (charset_file==NULL)
-        fatalerror_named("Couldn't open character set mapping", Charset_Map);
-
-    while (feof(charset_file)==0)
-    {   if (fgets(cs_buff,256,charset_file)==0) break;
-
-        switch (cs_buff[0])
-        {   case '!': /* Ignore comments in file */
-                break;
-            case 'C': /* Set character set */
-                character_set_setting = cs_buff[1]-'0';
-                if ((character_set_setting < 0) || (character_set_setting > 9))
-                {   fatalerror_named("Character set in mapping must be 0 to 9",
-                        Charset_Map);
-                }
-                break;
-            default:
-                p = cs_buff;
-                while ((i<256) && (p!=NULL))
-                {
-                    uccg[i++] = (uchar)atoi(p);
-                    p = strchr(p,',');
-                    if (p != NULL)
-                        p++;
-                }
-                break;
-        }
-    }
-    fclose(charset_file);
-}
-
-/* ========================================================================= */
-/*   Conversion functions (without side effects)                             */
-/* ------------------------------------------------------------------------- */
-/*  (1) Source -> ISO                                                        */
-/*                                                                           */
-/*      00         remains 0 (meaning "end of file")                         */
-/*      TAB        becomes SPACE                                             */
-/*      0c         ("form feed") becomes '\n'                                */
-/*      0d         becomes '\n'                                              */
-/*      other control characters become '?'                                  */
-/*      7f         becomes '?'                                               */
-/*      80 to 9f   become '?'                                                */
-/*      a0         (ISO "non-breaking space") becomes SPACE                  */
-/*      ad         (ISO "soft hyphen") becomes '-'                           */
-/*      any character undefined in ISO is mapped to '?'                      */
-/*      In Unicode mode, characters 80 and upwards are preserved.            */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-static void make_source_to_iso_grid(void)
-{   int n; uchar *uccg = (uchar *) source_to_iso_grid;
-
-    for (n=0; n<0x100; n++) uccg[n] = (char) n;
-
-    if (Charset_Map[0] != '\0')
-        read_source_to_iso_file(uccg);
-    else
-    {   source_to_iso_grid[0] = (char) 0;
-        for (n=1; n<32; n++) source_to_iso_grid[n] = '?';
-        source_to_iso_grid[10] = '\n';
-        source_to_iso_grid[12] = '\n';
-        source_to_iso_grid[13] = '\n';
-        source_to_iso_grid[127] = '?';
-        source_to_iso_grid[TAB_CHARACTER] = ' ';
-
-        if (character_set_unicode) /* No need to meddle with 8-bit for UTF-8 */
-            return;
-
-        for (n=0x80; n<0xa0; n++) source_to_iso_grid[n] = '?';
-        source_to_iso_grid[0xa0] = ' ';
-        source_to_iso_grid[0xad] = '-';
-
-        switch(character_set_setting)
-        {   case 0:
-                for (n=0xa0; n<0x100; n++)
-                     source_to_iso_grid[n] = '?';
-                break;
-            case 6:  /* Arabic */
-                for (n=0xa0; n<0xc1; n++)
-                    switch(n)
-                    {   case 0xa0: case 0xa4: case 0xac: case 0xad:
-                        case 0xbb: case 0xbf: break;
-                        default: source_to_iso_grid[n] = '?';
-                    }
-                for (n=0xdb; n<0xe0; n++)
-                     source_to_iso_grid[n] = '?';
-                for (n=0xf3; n<0x100; n++)
-                     source_to_iso_grid[n] = '?';
-                break;
-            case 7:  /* Greek */
-                source_to_iso_grid[0xa4] = '?';
-                source_to_iso_grid[0xa5] = '?';
-                source_to_iso_grid[0xaa] = '?';
-                source_to_iso_grid[0xae] = '?';
-                source_to_iso_grid[0xd2] = '?';
-                source_to_iso_grid[0xff] = '?';
-                break;
-            case 8:  /* Hebrew */
-                source_to_iso_grid[0xa1] = '?';
-                for (n=0xbf; n<0xdf; n++)
-                     source_to_iso_grid[n] = '?';
-                for (n=0xfb; n<0x100; n++)
-                     source_to_iso_grid[n] = '?';
-                break;
-        }
-    }
-}
-
-/* ------------------------------------------------------------------------- */
-/*  (2) ISO -> Unicode                                                       */
-/*                                                                           */
-/*     Need not be rapid, as the results are mostly cached.                  */
-/*     Always succeeds.                                                      */
-/* ------------------------------------------------------------------------- */
-
-extern int iso_to_unicode(int iso)
-{   int u = iso;
-    switch(character_set_setting)
-    {
-
-  case 0: /* Plain ASCII only */
-  break;
-
-  case 1: /* ISO 8859-1: Latin1: west European */
-  break;
-
-  case 2: /* ISO 8859-2: Latin2: central European */
-
-switch(iso)
-{ case 0xA1: u=0x0104; break; /* LATIN CAP A WITH OGONEK */
-  case 0xA2: u=0x02D8; break; /* BREVE */
-  case 0xA3: u=0x0141; break; /* LATIN CAP L WITH STROKE */
-  case 0xA5: u=0x013D; break; /* LATIN CAP L WITH CARON */
-  case 0xA6: u=0x015A; break; /* LATIN CAP S WITH ACUTE */
-  case 0xA9: u=0x0160; break; /* LATIN CAP S WITH CARON */
-  case 0xAA: u=0x015E; break; /* LATIN CAP S WITH CEDILLA */
-  case 0xAB: u=0x0164; break; /* LATIN CAP T WITH CARON */
-  case 0xAC: u=0x0179; break; /* LATIN CAP Z WITH ACUTE */
-  case 0xAE: u=0x017D; break; /* LATIN CAP Z WITH CARON */
-  case 0xAF: u=0x017B; break; /* LATIN CAP Z WITH DOT ABOVE */
-  case 0xB1: u=0x0105; break; /* LATIN SMALL A WITH OGONEK */
-  case 0xB2: u=0x02DB; break; /* OGONEK */
-  case 0xB3: u=0x0142; break; /* LATIN SMALL L WITH STROKE */
-  case 0xB5: u=0x013E; break; /* LATIN SMALL L WITH CARON */
-  case 0xB6: u=0x015B; break; /* LATIN SMALL S WITH ACUTE */
-  case 0xB7: u=0x02C7; break; /* CARON */
-  case 0xB9: u=0x0161; break; /* LATIN SMALL S WITH CARON */
-  case 0xBA: u=0x015F; break; /* LATIN SMALL S WITH CEDILLA */
-  case 0xBB: u=0x0165; break; /* LATIN SMALL T WITH CARON */
-  case 0xBC: u=0x017A; break; /* LATIN SMALL Z WITH ACUTE */
-  case 0xBD: u=0x02DD; break; /* DOUBLE ACUTE ACCENT */
-  case 0xBE: u=0x017E; break; /* LATIN SMALL Z WITH CARON */
-  case 0xBF: u=0x017C; break; /* LATIN SMALL Z WITH DOT ABOVE */
-  case 0xC0: u=0x0154; break; /* LATIN CAP R WITH ACUTE */
-  case 0xC3: u=0x0102; break; /* LATIN CAP A WITH BREVE */
-  case 0xC5: u=0x0139; break; /* LATIN CAP L WITH ACUTE */
-  case 0xC6: u=0x0106; break; /* LATIN CAP C WITH ACUTE */
-  case 0xC8: u=0x010C; break; /* LATIN CAP C WITH CARON */
-  case 0xCA: u=0x0118; break; /* LATIN CAP E WITH OGONEK */
-  case 0xCC: u=0x011A; break; /* LATIN CAP E WITH CARON */
-  case 0xCF: u=0x010E; break; /* LATIN CAP D WITH CARON */
-  case 0xD0: u=0x0110; break; /* LATIN CAP D WITH STROKE */
-  case 0xD1: u=0x0143; break; /* LATIN CAP N WITH ACUTE */
-  case 0xD2: u=0x0147; break; /* LATIN CAP N WITH CARON */
-  case 0xD5: u=0x0150; break; /* LATIN CAP O WITH DOUBLE ACUTE */
-  case 0xD8: u=0x0158; break; /* LATIN CAP R WITH CARON */
-  case 0xD9: u=0x016E; break; /* LATIN CAP U WITH RING ABOVE */
-  case 0xDB: u=0x0170; break; /* LATIN CAP U WITH DOUBLE ACUTE */
-  case 0xDE: u=0x0162; break; /* LATIN CAP T WITH CEDILLA */
-  case 0xE0: u=0x0155; break; /* LATIN SMALL R WITH ACUTE */
-  case 0xE3: u=0x0103; break; /* LATIN SMALL A WITH BREVE */
-  case 0xE5: u=0x013A; break; /* LATIN SMALL L WITH ACUTE */
-  case 0xE6: u=0x0107; break; /* LATIN SMALL C WITH ACUTE */
-  case 0xE8: u=0x010D; break; /* LATIN SMALL C WITH CARON */
-  case 0xEA: u=0x0119; break; /* LATIN SMALL E WITH OGONEK */
-  case 0xEC: u=0x011B; break; /* LATIN SMALL E WITH CARON */
-  case 0xEF: u=0x010F; break; /* LATIN SMALL D WITH CARON */
-  case 0xF0: u=0x0111; break; /* LATIN SMALL D WITH STROKE */
-  case 0xF1: u=0x0144; break; /* LATIN SMALL N WITH ACUTE */
-  case 0xF2: u=0x0148; break; /* LATIN SMALL N WITH CARON */
-  case 0xF5: u=0x0151; break; /* LATIN SMALL O WITH DOUBLE ACUTE */
-  case 0xF8: u=0x0159; break; /* LATIN SMALL R WITH CARON */
-  case 0xF9: u=0x016F; break; /* LATIN SMALL U WITH RING ABOVE */
-  case 0xFB: u=0x0171; break; /* LATIN SMALL U WITH DOUBLE ACUTE */
-  case 0xFE: u=0x0163; break; /* LATIN SMALL T WITH CEDILLA */
-  case 0xFF: u=0x02D9; break; /* DOT ABOVE */
-} break;
-
-  case 3: /* ISO 8859-3: Latin3: central European */
-
-switch(iso)
-{ case 0xA1: u=0x0126; break; /* LATIN CAP H WITH STROKE */
-  case 0xA2: u=0x02D8; break; /* BREVE */
-  case 0xA6: u=0x0124; break; /* LATIN CAP H WITH CIRCUMFLEX */
-  case 0xA9: u=0x0130; break; /* LATIN CAP I WITH DOT ABOVE */
-  case 0xAA: u=0x015E; break; /* LATIN CAP S WITH CEDILLA */
-  case 0xAB: u=0x011E; break; /* LATIN CAP G WITH BREVE */
-  case 0xAC: u=0x0134; break; /* LATIN CAP J WITH CIRCUMFLEX */
-  case 0xAF: u=0x017B; break; /* LATIN CAP Z WITH DOT ABOVE */
-  case 0xB1: u=0x0127; break; /* LATIN SMALL H WITH STROKE */
-  case 0xB6: u=0x0125; break; /* LATIN SMALL H WITH CIRCUMFLEX */
-  case 0xB9: u=0x0131; break; /* LATIN SMALL DOTLESS I */
-  case 0xBA: u=0x015F; break; /* LATIN SMALL S WITH CEDILLA */
-  case 0xBB: u=0x011F; break; /* LATIN SMALL G WITH BREVE */
-  case 0xBC: u=0x0135; break; /* LATIN SMALL J WITH CIRCUMFLEX */
-  case 0xBF: u=0x017C; break; /* LATIN SMALL Z WITH DOT ABOVE */
-  case 0xC5: u=0x010A; break; /* LATIN CAP C WITH DOT ABOVE */
-  case 0xC6: u=0x0108; break; /* LATIN CAP C WITH CIRCUMFLEX */
-  case 0xD5: u=0x0120; break; /* LATIN CAP G WITH DOT ABOVE */
-  case 0xD8: u=0x011C; break; /* LATIN CAP G WITH CIRCUMFLEX */
-  case 0xDD: u=0x016C; break; /* LATIN CAP U WITH BREVE */
-  case 0xDE: u=0x015C; break; /* LATIN CAP S WITH CIRCUMFLEX */
-  case 0xE5: u=0x010B; break; /* LATIN SMALL C WITH DOT ABOVE */
-  case 0xE6: u=0x0109; break; /* LATIN SMALL C WITH CIRCUMFLEX */
-  case 0xF5: u=0x0121; break; /* LATIN SMALL G WITH DOT ABOVE */
-  case 0xF8: u=0x011D; break; /* LATIN SMALL G WITH CIRCUMFLEX */
-  case 0xFD: u=0x016D; break; /* LATIN SMALL U WITH BREVE */
-  case 0xFE: u=0x015D; break; /* LATIN SMALL S WITH CIRCUMFLEX */
-  case 0xFF: u=0x02D9; break; /* DOT ABOVE */
-} break;
-
-  case 4: /* ISO 8859-4: Latin4: central European */
-
-switch(iso)
-{ case 0xA1: u=0x0104; break; /* LATIN CAP A WITH OGONEK */
-  case 0xA2: u=0x0138; break; /* LATIN SMALL KRA */
-  case 0xA3: u=0x0156; break; /* LATIN CAP R WITH CEDILLA */
-  case 0xA5: u=0x0128; break; /* LATIN CAP I WITH TILDE */
-  case 0xA6: u=0x013B; break; /* LATIN CAP L WITH CEDILLA */
-  case 0xA9: u=0x0160; break; /* LATIN CAP S WITH CARON */
-  case 0xAA: u=0x0112; break; /* LATIN CAP E WITH MACRON */
-  case 0xAB: u=0x0122; break; /* LATIN CAP G WITH CEDILLA */
-  case 0xAC: u=0x0166; break; /* LATIN CAP T WITH STROKE */
-  case 0xAE: u=0x017D; break; /* LATIN CAP Z WITH CARON */
-  case 0xB1: u=0x0105; break; /* LATIN SMALL A WITH OGONEK */
-  case 0xB2: u=0x02DB; break; /* OGONEK */
-  case 0xB3: u=0x0157; break; /* LATIN SMALL R WITH CEDILLA */
-  case 0xB5: u=0x0129; break; /* LATIN SMALL I WITH TILDE */
-  case 0xB6: u=0x013C; break; /* LATIN SMALL L WITH CEDILLA */
-  case 0xB7: u=0x02C7; break; /* CARON */
-  case 0xB9: u=0x0161; break; /* LATIN SMALL S WITH CARON */
-  case 0xBA: u=0x0113; break; /* LATIN SMALL E WITH MACRON */
-  case 0xBB: u=0x0123; break; /* LATIN SMALL G WITH CEDILLA */
-  case 0xBC: u=0x0167; break; /* LATIN SMALL T WITH STROKE */
-  case 0xBD: u=0x014A; break; /* LATIN CAP ENG */
-  case 0xBE: u=0x017E; break; /* LATIN SMALL Z WITH CARON */
-  case 0xBF: u=0x014B; break; /* LATIN SMALL ENG */
-  case 0xC0: u=0x0100; break; /* LATIN CAP A WITH MACRON */
-  case 0xC7: u=0x012E; break; /* LATIN CAP I WITH OGONEK */
-  case 0xC8: u=0x010C; break; /* LATIN CAP C WITH CARON */
-  case 0xCA: u=0x0118; break; /* LATIN CAP E WITH OGONEK */
-  case 0xCC: u=0x0116; break; /* LATIN CAP E WITH DOT ABOVE */
-  case 0xCF: u=0x012A; break; /* LATIN CAP I WITH MACRON */
-  case 0xD0: u=0x0110; break; /* LATIN CAP D WITH STROKE */
-  case 0xD1: u=0x0145; break; /* LATIN CAP N WITH CEDILLA */
-  case 0xD2: u=0x014C; break; /* LATIN CAP O WITH MACRON */
-  case 0xD3: u=0x0136; break; /* LATIN CAP K WITH CEDILLA */
-  case 0xD9: u=0x0172; break; /* LATIN CAP U WITH OGONEK */
-  case 0xDD: u=0x0168; break; /* LATIN CAP U WITH TILDE */
-  case 0xDE: u=0x016A; break; /* LATIN CAP U WITH MACRON */
-  case 0xE0: u=0x0101; break; /* LATIN SMALL A WITH MACRON */
-  case 0xE7: u=0x012F; break; /* LATIN SMALL I WITH OGONEK */
-  case 0xE8: u=0x010D; break; /* LATIN SMALL C WITH CARON */
-  case 0xEA: u=0x0119; break; /* LATIN SMALL E WITH OGONEK */
-  case 0xEC: u=0x0117; break; /* LATIN SMALL E WITH DOT ABOVE */
-  case 0xEF: u=0x012B; break; /* LATIN SMALL I WITH MACRON */
-  case 0xF0: u=0x0111; break; /* LATIN SMALL D WITH STROKE */
-  case 0xF1: u=0x0146; break; /* LATIN SMALL N WITH CEDILLA */
-  case 0xF2: u=0x014D; break; /* LATIN SMALL O WITH MACRON */
-  case 0xF3: u=0x0137; break; /* LATIN SMALL K WITH CEDILLA */
-  case 0xF9: u=0x0173; break; /* LATIN SMALL U WITH OGONEK */
-  case 0xFD: u=0x0169; break; /* LATIN SMALL U WITH TILDE */
-  case 0xFE: u=0x016B; break; /* LATIN SMALL U WITH MACRON */
-  case 0xFF: u=0x02D9; break; /* DOT ABOVE */
-} break;
-
-  case 5: /* ISO 8859-5: Cyrillic */
-
-switch(iso)
-{ case 0xA1: u=0x0401; break; /* CYRILLIC CAP IO */
-  case 0xA2: u=0x0402; break; /* CYRILLIC CAP DJE */
-  case 0xA3: u=0x0403; break; /* CYRILLIC CAP GJE */
-  case 0xA4: u=0x0404; break; /* CYRILLIC CAP UKRAINIAN IE */
-  case 0xA5: u=0x0405; break; /* CYRILLIC CAP DZE */
-  case 0xA6: u=0x0406; break; /* CYRILLIC CAP BYELORUSSIAN-UKRAINIAN I */
-  case 0xA7: u=0x0407; break; /* CYRILLIC CAP YI */
-  case 0xA8: u=0x0408; break; /* CYRILLIC CAP JE */
-  case 0xA9: u=0x0409; break; /* CYRILLIC CAP LJE */
-  case 0xAA: u=0x040A; break; /* CYRILLIC CAP NJE */
-  case 0xAB: u=0x040B; break; /* CYRILLIC CAP TSHE */
-  case 0xAC: u=0x040C; break; /* CYRILLIC CAP KJE */
-  case 0xAE: u=0x040E; break; /* CYRILLIC CAP SHORT U */
-  case 0xAF: u=0x040F; break; /* CYRILLIC CAP DZHE */
-  case 0xB0: u=0x0410; break; /* CYRILLIC CAP A */
-  case 0xB1: u=0x0411; break; /* CYRILLIC CAP BE */
-  case 0xB2: u=0x0412; break; /* CYRILLIC CAP VE */
-  case 0xB3: u=0x0413; break; /* CYRILLIC CAP GHE */
-  case 0xB4: u=0x0414; break; /* CYRILLIC CAP DE */
-  case 0xB5: u=0x0415; break; /* CYRILLIC CAP IE */
-  case 0xB6: u=0x0416; break; /* CYRILLIC CAP ZHE */
-  case 0xB7: u=0x0417; break; /* CYRILLIC CAP ZE */
-  case 0xB8: u=0x0418; break; /* CYRILLIC CAP I */
-  case 0xB9: u=0x0419; break; /* CYRILLIC CAP SHORT I */
-  case 0xBA: u=0x041A; break; /* CYRILLIC CAP KA */
-  case 0xBB: u=0x041B; break; /* CYRILLIC CAP EL */
-  case 0xBC: u=0x041C; break; /* CYRILLIC CAP EM */
-  case 0xBD: u=0x041D; break; /* CYRILLIC CAP EN */
-  case 0xBE: u=0x041E; break; /* CYRILLIC CAP O */
-  case 0xBF: u=0x041F; break; /* CYRILLIC CAP PE */
-  case 0xC0: u=0x0420; break; /* CYRILLIC CAP ER */
-  case 0xC1: u=0x0421; break; /* CYRILLIC CAP ES */
-  case 0xC2: u=0x0422; break; /* CYRILLIC CAP TE */
-  case 0xC3: u=0x0423; break; /* CYRILLIC CAP U */
-  case 0xC4: u=0x0424; break; /* CYRILLIC CAP EF */
-  case 0xC5: u=0x0425; break; /* CYRILLIC CAP HA */
-  case 0xC6: u=0x0426; break; /* CYRILLIC CAP TSE */
-  case 0xC7: u=0x0427; break; /* CYRILLIC CAP CHE */
-  case 0xC8: u=0x0428; break; /* CYRILLIC CAP SHA */
-  case 0xC9: u=0x0429; break; /* CYRILLIC CAP SHCHA */
-  case 0xCA: u=0x042A; break; /* CYRILLIC CAP HARD SIGN */
-  case 0xCB: u=0x042B; break; /* CYRILLIC CAP YERU */
-  case 0xCC: u=0x042C; break; /* CYRILLIC CAP SOFT SIGN */
-  case 0xCD: u=0x042D; break; /* CYRILLIC CAP E */
-  case 0xCE: u=0x042E; break; /* CYRILLIC CAP YU */
-  case 0xCF: u=0x042F; break; /* CYRILLIC CAP YA */
-  case 0xD0: u=0x0430; break; /* CYRILLIC SMALL A */
-  case 0xD1: u=0x0431; break; /* CYRILLIC SMALL BE */
-  case 0xD2: u=0x0432; break; /* CYRILLIC SMALL VE */
-  case 0xD3: u=0x0433; break; /* CYRILLIC SMALL GHE */
-  case 0xD4: u=0x0434; break; /* CYRILLIC SMALL DE */
-  case 0xD5: u=0x0435; break; /* CYRILLIC SMALL IE */
-  case 0xD6: u=0x0436; break; /* CYRILLIC SMALL ZHE */
-  case 0xD7: u=0x0437; break; /* CYRILLIC SMALL ZE */
-  case 0xD8: u=0x0438; break; /* CYRILLIC SMALL I */
-  case 0xD9: u=0x0439; break; /* CYRILLIC SMALL SHORT I */
-  case 0xDA: u=0x043A; break; /* CYRILLIC SMALL KA */
-  case 0xDB: u=0x043B; break; /* CYRILLIC SMALL EL */
-  case 0xDC: u=0x043C; break; /* CYRILLIC SMALL EM */
-  case 0xDD: u=0x043D; break; /* CYRILLIC SMALL EN */
-  case 0xDE: u=0x043E; break; /* CYRILLIC SMALL O */
-  case 0xDF: u=0x043F; break; /* CYRILLIC SMALL PE */
-  case 0xE0: u=0x0440; break; /* CYRILLIC SMALL ER */
-  case 0xE1: u=0x0441; break; /* CYRILLIC SMALL ES */
-  case 0xE2: u=0x0442; break; /* CYRILLIC SMALL TE */
-  case 0xE3: u=0x0443; break; /* CYRILLIC SMALL U */
-  case 0xE4: u=0x0444; break; /* CYRILLIC SMALL EF */
-  case 0xE5: u=0x0445; break; /* CYRILLIC SMALL HA */
-  case 0xE6: u=0x0446; break; /* CYRILLIC SMALL TSE */
-  case 0xE7: u=0x0447; break; /* CYRILLIC SMALL CHE */
-  case 0xE8: u=0x0448; break; /* CYRILLIC SMALL SHA */
-  case 0xE9: u=0x0449; break; /* CYRILLIC SMALL SHCHA */
-  case 0xEA: u=0x044A; break; /* CYRILLIC SMALL HARD SIGN */
-  case 0xEB: u=0x044B; break; /* CYRILLIC SMALL YERU */
-  case 0xEC: u=0x044C; break; /* CYRILLIC SMALL SOFT SIGN */
-  case 0xED: u=0x044D; break; /* CYRILLIC SMALL E */
-  case 0xEE: u=0x044E; break; /* CYRILLIC SMALL YU */
-  case 0xEF: u=0x044F; break; /* CYRILLIC SMALL YA */
-  case 0xF0: u=0x2116; break; /* NUMERO SIGN */
-  case 0xF1: u=0x0451; break; /* CYRILLIC SMALL IO */
-  case 0xF2: u=0x0452; break; /* CYRILLIC SMALL DJE */
-  case 0xF3: u=0x0453; break; /* CYRILLIC SMALL GJE */
-  case 0xF4: u=0x0454; break; /* CYRILLIC SMALL UKRAINIAN IE */
-  case 0xF5: u=0x0455; break; /* CYRILLIC SMALL DZE */
-  case 0xF6: u=0x0456; break; /* CYRILLIC SMALL BYELORUSSIAN-UKRAINIAN I */
-  case 0xF7: u=0x0457; break; /* CYRILLIC SMALL YI */
-  case 0xF8: u=0x0458; break; /* CYRILLIC SMALL JE */
-  case 0xF9: u=0x0459; break; /* CYRILLIC SMALL LJE */
-  case 0xFA: u=0x045A; break; /* CYRILLIC SMALL NJE */
-  case 0xFB: u=0x045B; break; /* CYRILLIC SMALL TSHE */
-  case 0xFC: u=0x045C; break; /* CYRILLIC SMALL KJE */
-  case 0xFD: u=0x00A7; break; /* SECTION SIGN */
-  case 0xFE: u=0x045E; break; /* CYRILLIC SMALL SHORT U */
-  case 0xFF: u=0x045F; break; /* CYRILLIC SMALL DZHE */
-} break;
-
-  case 6: /* ISO 8859-6: Arabic */
-
-switch(iso)
-{ case 0xAC: u=0x060C; break; /* ARABIC COMMA */
-  case 0xBB: u=0x061B; break; /* ARABIC SEMICOLON */
-  case 0xBF: u=0x061F; break; /* ARABIC QUESTION MARK */
-  case 0xC1: u=0x0621; break; /* ARABIC HAMZA */
-  case 0xC2: u=0x0622; break; /* ARABIC ALEF WITH MADDA ABOVE */
-  case 0xC3: u=0x0623; break; /* ARABIC ALEF WITH HAMZA ABOVE */
-  case 0xC4: u=0x0624; break; /* ARABIC WAW WITH HAMZA ABOVE */
-  case 0xC5: u=0x0625; break; /* ARABIC ALEF WITH HAMZA BELOW */
-  case 0xC6: u=0x0626; break; /* ARABIC YEH WITH HAMZA ABOVE */
-  case 0xC7: u=0x0627; break; /* ARABIC ALEF */
-  case 0xC8: u=0x0628; break; /* ARABIC BEH */
-  case 0xC9: u=0x0629; break; /* ARABIC TEH MARBUTA */
-  case 0xCA: u=0x062A; break; /* ARABIC TEH */
-  case 0xCB: u=0x062B; break; /* ARABIC THEH */
-  case 0xCC: u=0x062C; break; /* ARABIC JEEM */
-  case 0xCD: u=0x062D; break; /* ARABIC HAH */
-  case 0xCE: u=0x062E; break; /* ARABIC KHAH */
-  case 0xCF: u=0x062F; break; /* ARABIC DAL */
-  case 0xD0: u=0x0630; break; /* ARABIC THAL */
-  case 0xD1: u=0x0631; break; /* ARABIC REH */
-  case 0xD2: u=0x0632; break; /* ARABIC ZAIN */
-  case 0xD3: u=0x0633; break; /* ARABIC SEEN */
-  case 0xD4: u=0x0634; break; /* ARABIC SHEEN */
-  case 0xD5: u=0x0635; break; /* ARABIC SAD */
-  case 0xD6: u=0x0636; break; /* ARABIC DAD */
-  case 0xD7: u=0x0637; break; /* ARABIC TAH */
-  case 0xD8: u=0x0638; break; /* ARABIC ZAH */
-  case 0xD9: u=0x0639; break; /* ARABIC AIN */
-  case 0xDA: u=0x063A; break; /* ARABIC GHAIN */
-  case 0xE0: u=0x0640; break; /* ARABIC TATWEEL */
-  case 0xE1: u=0x0641; break; /* ARABIC FEH */
-  case 0xE2: u=0x0642; break; /* ARABIC QAF */
-  case 0xE3: u=0x0643; break; /* ARABIC KAF */
-  case 0xE4: u=0x0644; break; /* ARABIC LAM */
-  case 0xE5: u=0x0645; break; /* ARABIC MEEM */
-  case 0xE6: u=0x0646; break; /* ARABIC NOON */
-  case 0xE7: u=0x0647; break; /* ARABIC HEH */
-  case 0xE8: u=0x0648; break; /* ARABIC WAW */
-  case 0xE9: u=0x0649; break; /* ARABIC ALEF MAKSURA */
-  case 0xEA: u=0x064A; break; /* ARABIC YEH */
-  case 0xEB: u=0x064B; break; /* ARABIC FATHATAN */
-  case 0xEC: u=0x064C; break; /* ARABIC DAMMATAN */
-  case 0xED: u=0x064D; break; /* ARABIC KASRATAN */
-  case 0xEE: u=0x064E; break; /* ARABIC FATHA */
-  case 0xEF: u=0x064F; break; /* ARABIC DAMMA */
-  case 0xF0: u=0x0650; break; /* ARABIC KASRA */
-  case 0xF1: u=0x0651; break; /* ARABIC SHADDA */
-  case 0xF2: u=0x0652; break; /* ARABIC SUKUN */
-} break;
-
-  case 7: /* ISO 8859-7: Greek */
-
-switch(iso)
-{ case 0xA1: u=0x02BD; break; /* MODIFIER REVERSED COMMA */
-  case 0xA2: u=0x02BC; break; /* MODIFIER APOSTROPHE */
-  case 0xAF: u=0x2015; break; /* HORIZONTAL BAR */
-  case 0xB4: u=0x0384; break; /* GREEK TONOS */
-  case 0xB5: u=0x0385; break; /* GREEK DIALYTIKA TONOS */
-  case 0xB6: u=0x0386; break; /* GREEK CAP ALPHA WITH TONOS */
-  case 0xB8: u=0x0388; break; /* GREEK CAP EPSILON WITH TONOS */
-  case 0xB9: u=0x0389; break; /* GREEK CAP ETA WITH TONOS */
-  case 0xBA: u=0x038A; break; /* GREEK CAP IOTA WITH TONOS */
-  case 0xBC: u=0x038C; break; /* GREEK CAP OMICRON WITH TONOS */
-  case 0xBE: u=0x038E; break; /* GREEK CAP UPSILON WITH TONOS */
-  case 0xBF: u=0x038F; break; /* GREEK CAP OMEGA WITH TONOS */
-  case 0xC0: u=0x0390; break; /* GREEK SMALL IOTA WITH DIALYTIKA AND TONOS */
-  case 0xC1: u=0x0391; break; /* GREEK CAP ALPHA */
-  case 0xC2: u=0x0392; break; /* GREEK CAP BETA */
-  case 0xC3: u=0x0393; break; /* GREEK CAP GAMMA */
-  case 0xC4: u=0x0394; break; /* GREEK CAP DELTA */
-  case 0xC5: u=0x0395; break; /* GREEK CAP EPSILON */
-  case 0xC6: u=0x0396; break; /* GREEK CAP ZETA */
-  case 0xC7: u=0x0397; break; /* GREEK CAP ETA */
-  case 0xC8: u=0x0398; break; /* GREEK CAP THETA */
-  case 0xC9: u=0x0399; break; /* GREEK CAP IOTA */
-  case 0xCA: u=0x039A; break; /* GREEK CAP KAPPA */
-  case 0xCB: u=0x039B; break; /* GREEK CAP LAMDA */
-  case 0xCC: u=0x039C; break; /* GREEK CAP MU */
-  case 0xCD: u=0x039D; break; /* GREEK CAP NU */
-  case 0xCE: u=0x039E; break; /* GREEK CAP XI */
-  case 0xCF: u=0x039F; break; /* GREEK CAP OMICRON */
-  case 0xD0: u=0x03A0; break; /* GREEK CAP PI */
-  case 0xD1: u=0x03A1; break; /* GREEK CAP RHO */
-  case 0xD3: u=0x03A3; break; /* GREEK CAP SIGMA */
-  case 0xD4: u=0x03A4; break; /* GREEK CAP TAU */
-  case 0xD5: u=0x03A5; break; /* GREEK CAP UPSILON */
-  case 0xD6: u=0x03A6; break; /* GREEK CAP PHI */
-  case 0xD7: u=0x03A7; break; /* GREEK CAP CHI */
-  case 0xD8: u=0x03A8; break; /* GREEK CAP PSI */
-  case 0xD9: u=0x03A9; break; /* GREEK CAP OMEGA */
-  case 0xDA: u=0x03AA; break; /* GREEK CAP IOTA WITH DIALYTIKA */
-  case 0xDB: u=0x03AB; break; /* GREEK CAP UPSILON WITH DIALYTIKA */
-  case 0xDC: u=0x03AC; break; /* GREEK SMALL ALPHA WITH TONOS */
-  case 0xDD: u=0x03AD; break; /* GREEK SMALL EPSILON WITH TONOS */
-  case 0xDE: u=0x03AE; break; /* GREEK SMALL ETA WITH TONOS */
-  case 0xDF: u=0x03AF; break; /* GREEK SMALL IOTA WITH TONOS */
-  case 0xE0: u=0x03B0; break; /* GREEK SMALL UPSILON WITH DIALYTIKA AND TONOS */
-  case 0xE1: u=0x03B1; break; /* GREEK SMALL ALPHA */
-  case 0xE2: u=0x03B2; break; /* GREEK SMALL BETA */
-  case 0xE3: u=0x03B3; break; /* GREEK SMALL GAMMA */
-  case 0xE4: u=0x03B4; break; /* GREEK SMALL DELTA */
-  case 0xE5: u=0x03B5; break; /* GREEK SMALL EPSILON */
-  case 0xE6: u=0x03B6; break; /* GREEK SMALL ZETA */
-  case 0xE7: u=0x03B7; break; /* GREEK SMALL ETA */
-  case 0xE8: u=0x03B8; break; /* GREEK SMALL THETA */
-  case 0xE9: u=0x03B9; break; /* GREEK SMALL IOTA */
-  case 0xEA: u=0x03BA; break; /* GREEK SMALL KAPPA */
-  case 0xEB: u=0x03BB; break; /* GREEK SMALL LAMDA */
-  case 0xEC: u=0x03BC; break; /* GREEK SMALL MU */
-  case 0xED: u=0x03BD; break; /* GREEK SMALL NU */
-  case 0xEE: u=0x03BE; break; /* GREEK SMALL XI */
-  case 0xEF: u=0x03BF; break; /* GREEK SMALL OMICRON */
-  case 0xF0: u=0x03C0; break; /* GREEK SMALL PI */
-  case 0xF1: u=0x03C1; break; /* GREEK SMALL RHO */
-  case 0xF2: u=0x03C2; break; /* GREEK SMALL FINAL SIGMA */
-  case 0xF3: u=0x03C3; break; /* GREEK SMALL SIGMA */
-  case 0xF4: u=0x03C4; break; /* GREEK SMALL TAU */
-  case 0xF5: u=0x03C5; break; /* GREEK SMALL UPSILON */
-  case 0xF6: u=0x03C6; break; /* GREEK SMALL PHI */
-  case 0xF7: u=0x03C7; break; /* GREEK SMALL CHI */
-  case 0xF8: u=0x03C8; break; /* GREEK SMALL PSI */
-  case 0xF9: u=0x03C9; break; /* GREEK SMALL OMEGA */
-  case 0xFA: u=0x03CA; break; /* GREEK SMALL IOTA WITH DIALYTIKA */
-  case 0xFB: u=0x03CB; break; /* GREEK SMALL UPSILON WITH DIALYTIKA */
-  case 0xFC: u=0x03CC; break; /* GREEK SMALL OMICRON WITH TONOS */
-  case 0xFD: u=0x03CD; break; /* GREEK SMALL UPSILON WITH TONOS */
-  case 0xFE: u=0x03CE; break; /* GREEK SMALL OMEGA WITH TONOS */
-} break;
-
-  case 8: /* ISO 8859-8: Hebrew */
-
-switch(iso)
-{ case 0xAA: u=0x00D7; break; /* MULTIPLICATION SIGN */
-  case 0xAF: u=0x203E; break; /* OVERLINE */
-  case 0xBA: u=0x00F7; break; /* DIVISION SIGN */
-  case 0xDF: u=0x2017; break; /* DOUBLE LOW LINE */
-  case 0xE0: u=0x05D0; break; /* HEBREW ALEF */
-  case 0xE1: u=0x05D1; break; /* HEBREW BET */
-  case 0xE2: u=0x05D2; break; /* HEBREW GIMEL */
-  case 0xE3: u=0x05D3; break; /* HEBREW DALET */
-  case 0xE4: u=0x05D4; break; /* HEBREW HE */
-  case 0xE5: u=0x05D5; break; /* HEBREW VAV */
-  case 0xE6: u=0x05D6; break; /* HEBREW ZAYIN */
-  case 0xE7: u=0x05D7; break; /* HEBREW HET */
-  case 0xE8: u=0x05D8; break; /* HEBREW TET */
-  case 0xE9: u=0x05D9; break; /* HEBREW YOD */
-  case 0xEA: u=0x05DA; break; /* HEBREW FINAL KAF */
-  case 0xEB: u=0x05DB; break; /* HEBREW KAF */
-  case 0xEC: u=0x05DC; break; /* HEBREW LAMED */
-  case 0xED: u=0x05DD; break; /* HEBREW FINAL MEM */
-  case 0xEE: u=0x05DE; break; /* HEBREW MEM */
-  case 0xEF: u=0x05DF; break; /* HEBREW FINAL NUN */
-  case 0xF0: u=0x05E0; break; /* HEBREW NUN */
-  case 0xF1: u=0x05E1; break; /* HEBREW SAMEKH */
-  case 0xF2: u=0x05E2; break; /* HEBREW AYIN */
-  case 0xF3: u=0x05E3; break; /* HEBREW FINAL PE */
-  case 0xF4: u=0x05E4; break; /* HEBREW PE */
-  case 0xF5: u=0x05E5; break; /* HEBREW FINAL TSADI */
-  case 0xF6: u=0x05E6; break; /* HEBREW TSADI */
-  case 0xF7: u=0x05E7; break; /* HEBREW QOF */
-  case 0xF8: u=0x05E8; break; /* HEBREW RESH */
-  case 0xF9: u=0x05E9; break; /* HEBREW SHIN */
-  case 0xFA: u=0x05EA; break; /* HEBREW TAV */
-} break;
-
-  case 9: /* ISO 8859-9: Latin5: west European without Icelandic */
-
-switch(iso)
-{
-  case 0xD0: u=0x011E; break; /* LATIN CAP G WITH BREVE */
-  case 0xDD: u=0x0130; break; /* LATIN CAP I WITH DOT ABOVE */
-  case 0xDE: u=0x015e; break; /* LATIN CAP S WITH CEDILLA */
-  case 0xF0: u=0x011f; break; /* LATIN SMALL G WITH BREVE */
-  case 0xFD: u=0x0131; break; /* LATIN SMALL DOTLESS I */
-  case 0xFE: u=0x015f; break; /* LATIN SMALL S WITH CEDILLA */
-} break;
-
-    }
-    return u;
-}
-
-/* ------------------------------------------------------------------------- */
-/*  (3) Unicode -> ZSCII and vice versa                                      */
-/*                                                                           */
-/*     Need not be rapid, as the results are mostly cached.                  */
-/*     Unicode chars which can't be fitted into ZSCII are converted to the   */
-/*     value 5 (the pad character used in the dictionary and elsewhere).     */
-/* ------------------------------------------------------------------------- */
-
-int zscii_defn_modified, zscii_high_water_mark;
-
-int32 zscii_to_unicode_grid[0x61];
-
-static void zscii_unicode_map(int zscii, int32 unicode)
-{   if ((zscii < 155) || (zscii > 251))
-    {   compiler_error("Attempted to map a Unicode character into the ZSCII \
-set at an illegal position");
-        return;
-    }
-    zscii_to_unicode_grid[zscii-155] = unicode;
-    zscii_defn_modified = TRUE;
-}
-
-int default_zscii_highset_sizes[] = { 69, 69, 81, 71, 82, 92, 48, 71, 27, 62 };
-
-int32 default_zscii_to_unicode_c01[]
-    = { /* (This ordering is important, unlike those for other char sets)
-           The 69 characters making up the default Unicode translation
-           table (see the Z-Machine Standard 1.0). */
-
-        0xe4, /* a-diaeresis */ 0xf6, /* o-diaeresis */ 0xfc, /* u-diaeresis */
-        0xc4, /* A-diaeresis */ 0xd6, /* O-diaeresis */ 0xdc, /* U-diaeresis */
-        0xdf, /* sz-ligature */ 0xbb, /* >> */ 0xab, /* << */
-        0xeb, /* e-diaeresis */ 0xef, /* i-diaeresis */ 0xff, /* y-diaeresis */
-        0xcb, /* E-diaeresis */ 0xcf, /* I-diaeresis */ 0xe1, /* a-acute */
-        0xe9, /* e-acute */ 0xed, /* i-acute */ 0xf3, /* o-acute */
-        0xfa, /* u-acute */ 0xfd, /* y-acute */ 0xc1, /* A-acute */
-        0xc9, /* E-acute */ 0xcd, /* I-acute */ 0xd3, /* O-acute */
-        0xda, /* U-acute */ 0xdd, /* Y-acute */ 0xe0, /* a-grave */
-        0xe8, /* e-grave */ 0xec, /* i-grave */ 0xf2, /* o-grave */
-        0xf9, /* u-grave */ 0xc0, /* A-grave */ 0xc8, /* E-grave */
-        0xcc, /* I-grave */ 0xd2, /* O-grave */ 0xd9, /* U-grave */
-        0xe2, /* a-circumflex */ 0xea, /* e-circumflex */
-        0xee, /* i-circumflex */ 0xf4, /* o-circumflex */
-        0xfb, /* u-circumflex */ 0xc2, /* A-circumflex */
-        0xca, /* E-circumflex */ 0xce, /* I-circumflex */
-        0xd4, /* O-circumflex */ 0xdb, /* U-circumflex */
-        0xe5, /* a-ring */ 0xc5, /* A-ring */
-        0xf8, /* o-slash */ 0xd8, /* O-slash */
-        0xe3, /* a-tilde */ 0xf1, /* n-tilde */ 0xf5, /* o-tilde */
-        0xc3, /* A-tilde */ 0xd1, /* N-tilde */ 0xd5, /* O-tilde */
-        0xe6, /* ae-ligature */ 0xc6, /* AE-ligature */
-        0xe7, /* c-cedilla */ 0xc7, /* C-cedilla */
-        0xfe, /* thorn */ 0xf0, /* eth */ 0xde, /* Thorn */ 0xd0, /* Eth */
-        0xa3, /* pound symbol */
-        0x0153, /* oe-ligature */ 0x0152, /* OE-ligature */
-        0xa1, /* inverted ! */ 0xbf /* inverted ? */ };
-
-int32 default_zscii_to_unicode_c2[]
-    = { /* The 81 accented letters in Latin2 */
-        0x0104, 0x0141, 0x013D, 0x015A, 0x0160, 0x015E, 0x0164, 0x0179,
-        0x017D, 0x017B, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139,
-        0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD,
-        0x00CE, 0x010E, 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150,
-        0x00D6, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162,
-        0x0105, 0x0142, 0x013E, 0x015B, 0x0161, 0x015F, 0x0165, 0x017A,
-        0x017E, 0x017C, 0x00DF, 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4,
-        0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B,
-        0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4,
-        0x0151, 0x00F6, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD,
-        0x0163 };
-
-int32 default_zscii_to_unicode_c3[]
-    = { /* The 71 accented letters in Latin3 */
-        0x0126, 0x0124, 0x0130, 0x015E, 0x011E, 0x0134, 0x017B, 0x0127,
-        0x0125, 0x0131, 0x015F, 0x011F, 0x0135, 0x017C, 0x00C0, 0x00C1,
-        0x00C2, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA,
-        0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D1, 0x00D2, 0x00D3,
-        0x00D4, 0x0120, 0x00D6, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC,
-        0x016C, 0x015C, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E4, 0x010B,
-        0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED,
-        0x00EE, 0x00EF, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6,
-        0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D };
-
-int32 default_zscii_to_unicode_c4[]
-    = { /* The 82 accented letters in Latin4 */
-        0x0104, 0x0138, 0x0156, 0x0128, 0x013B, 0x0160, 0x0112, 0x0122,
-        0x0166, 0x017D, 0x0105, 0x0157, 0x0129, 0x013C, 0x0161, 0x0113,
-        0x0123, 0x0167, 0x014A, 0x017E, 0x014B, 0x0100, 0x00C1, 0x00C2,
-        0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118,
-        0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, 0x0110, 0x0145, 0x014C,
-        0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x0172, 0x00DA, 0x00DB,
-        0x00DC, 0x0168, 0x016A, 0x00DF, 0x0101, 0x00E1, 0x00E2, 0x00E3,
-        0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB,
-        0x0117, 0x00ED, 0x00EE, 0x012B, 0x0111, 0x0146, 0x014D, 0x0137,
-        0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC,
-        0x0169, 0x016B };
-
-int32 default_zscii_to_unicode_c5[]
-    = { /* The 92 accented letters in Cyrillic */
-        0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408,
-        0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
-        0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419,
-        0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421,
-        0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429,
-        0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431,
-        0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439,
-        0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441,
-        0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
-        0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x0451, 0x0452,
-        0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A,
-        0x045B, 0x045C, 0x045E, 0x045F };
-
-int32 default_zscii_to_unicode_c6[]
-    = { /* The 48 accented letters in Arabic */
-        0x060C, 0x061B, 0x061F, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625,
-        0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D,
-        0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635,
-        0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642,
-        0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
-        0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x0651, 0x0652 };
-
-int32 default_zscii_to_unicode_c7[]
-    = { /* The 71 accented letters in Greek */
-        0x0384, 0x0385, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
-        0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396,
-        0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E,
-        0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
-        0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
-        0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
-        0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
-        0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
-        0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE };
-
-int32 default_zscii_to_unicode_c8[]
-    = { /* The 27 accented letters in Hebrew */
-        0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
-        0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
-        0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
-        0x05E8, 0x05E9, 0x05EA };
-
-int32 default_zscii_to_unicode_c9[]
-    = { /* The 62 accented letters in Latin5 */
-        0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
-        0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
-        0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8,
-        0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, 0x00E0,
-        0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8,
-        0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x011F,
-        0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x00F9,
-        0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF };
-
-static void make_unicode_zscii_map(void)
-{   int i;
-
-    for (i=0; i<0x61; i++) zscii_to_unicode_grid[i] = '?';
-
-    zscii_high_water_mark
-        = default_zscii_highset_sizes[character_set_setting];
-
-    for (i=0; i<zscii_high_water_mark; i++)
-    {   switch(character_set_setting)
-        {   case 0:
-            case 1: zscii_unicode_map(i+155, default_zscii_to_unicode_c01[i]);
-                    break;
-            case 2: zscii_unicode_map(i+155, default_zscii_to_unicode_c2[i]);
-                    break;
-            case 3: zscii_unicode_map(i+155, default_zscii_to_unicode_c3[i]);
-                    break;
-            case 4: zscii_unicode_map(i+155, default_zscii_to_unicode_c4[i]);
-                    break;
-            case 5: zscii_unicode_map(i+155, default_zscii_to_unicode_c5[i]);
-                    break;
-            case 6: zscii_unicode_map(i+155, default_zscii_to_unicode_c6[i]);
-                    break;
-            case 7: zscii_unicode_map(i+155, default_zscii_to_unicode_c7[i]);
-                    break;
-            case 8: zscii_unicode_map(i+155, default_zscii_to_unicode_c8[i]);
-                    break;
-            case 9: zscii_unicode_map(i+155, default_zscii_to_unicode_c9[i]);
-                    break;
-        }
-    }
-    if (character_set_setting < 2) zscii_defn_modified = FALSE;
-    make_iso_to_alphabet_grid();
-}
-
-extern void new_zscii_character(int32 u, int plus_flag)
-{
-    if (u < 0 || u > 0xFFFF)
-        error("Zcharacter table cannot contain Unicode characters beyond $FFFF");
-    if (plus_flag == FALSE)
-        zscii_high_water_mark = 0;
-    if (zscii_high_water_mark == 0x61)
-        error("No more room in the Zcharacter table");
-    else zscii_unicode_map(155 + zscii_high_water_mark++, u);
-}
-
-extern void new_zscii_finished(void)
-{   make_iso_to_alphabet_grid();
-}
-
-extern int unicode_to_zscii(int32 u)
-{   int i;
-    if (u < 0x7f) return u;
-    for (i=0; i<zscii_high_water_mark; i++)
-        if (zscii_to_unicode_grid[i] == u) return i+155;
-    return 5;
-}
-
-extern int32 zscii_to_unicode(int z)
-{   if (z < 0x80) return z;
-    if ((z >= 155) && (z <= 251)) return zscii_to_unicode_grid[z-155];
-    return '?';
-}
-
-/* ------------------------------------------------------------------------- */
-/*  (4) Text -> Unicode                                                      */
-/*                                                                           */
-/*  This routine is not used for ordinary text compilation as it is too      */
-/*  slow, but it's useful for handling @ string escapes, or to avoid writing */
-/*  special code when speed is not especially required.                      */
-/*  Note that the two string escapes which can define Unicode are:           */
-/*                                                                           */
-/*      @..      where .. is an accent                                       */
-/*  and @{...}   where ... specifies a Unicode char in hexadecimal           */
-/*               (1 to 6 digits long)                                        */
-/*                                                                           */
-/*  If either syntax is malformed, an error is generated                     */
-/*  and the Unicode (= ISO = ASCII) character value of '?' is returned       */
-/*                                                                           */
-/*  In Unicode mode (character_set_unicode is true), this handles UTF-8      */
-/*  decoding as well as @-expansion. (So it's called when an '@' appears     */
-/*  *and* when a high-bit character appears.)                                */
-/* ------------------------------------------------------------------------- */
-
-int textual_form_length;
-
-extern int32 text_to_unicode(char *text)
-{   int i;
-
-    if (text[0] != '@')
-    {   if (character_set_unicode)
-        {   if (text[0] & 0x80) /* 8-bit */
-            {   switch (text[0] & 0xF0)
-                {   case 0xf0: /* 4-byte UTF-8 string */
-                        textual_form_length = 4;
-                        if ((text[0] & 0xf8) != 0xf0)
-                        {   error("Invalid 4-byte UTF-8 string.");
-                            return '?';
-                        }
-                        if ((text[1] & 0xc0) != 0x80 || (text[2] & 0xc0) != 0x80 || (text[3] & 0xc0) != 0x80)
-                        {   error("Invalid 4-byte UTF-8 string.");
-                            return '?';
-                        }
-                        return (text[0] & 0x07) << 18
-                            | (text[1] & 0x3f) << 12
-                            | (text[2] & 0x3f) << 6
-                            | (text[3] & 0x3f);
-                        break;
-                    case 0xe0: /* 3-byte UTF-8 string */
-                        textual_form_length = 3;
-                        if ((text[1] & 0xc0) != 0x80 || (text[2] & 0xc0) != 0x80)
-                        {   error("Invalid 3-byte UTF-8 string.");
-                            return '?';
-                        }
-                        return (text[0] & 0x0f) << 12
-                            | (text[1] & 0x3f) << 6
-                            | (text[2] & 0x3f);
-                        break;
-                    case 0xc0: /* 2-byte UTF-8 string */ 
-                    case 0xd0:
-                        textual_form_length = 2;
-                        if ((text[1] & 0xc0) != 0x80)
-                        {   error("Invalid 2-byte UTF-8 string.");
-                            return '?';
-                        }
-                        return (text[0] & 0x1f) << 6
-                            | (text[1] & 0x3f);
-                        break;
-                    default: /* broken */
-                        error("Invalid UTF-8 string.");
-                        textual_form_length = 1;
-                        return '?';
-                        break;
-                }
-            }
-            else /* nice 7-bit */
-            {   textual_form_length = 1;
-                return (uchar) text[0];
-            }
-        }
-        else
-        {
-            textual_form_length = 1;
-            return iso_to_unicode((uchar) text[0]);
-        }
-    }
-
-    if ((isdigit(text[1])) || (text[1] == '@'))
-    {   ebf_error("'@' plus an accent code or '@{...}'", text);
-        textual_form_length = 1;
-        return '?';
-    }
-
-    if (text[1] != '{')
-    {   for (i=0; accents[i] != 0; i+=2)
-            if ((text[1] == accents[i]) && (text[2] == accents[i+1]))
-            {   textual_form_length = 3;
-                return default_zscii_to_unicode_c01[i/2];
-            }
-
-        {   char uac[4];
-            uac[0]='@'; uac[1]=text[1]; uac[2]=text[2]; uac[3]=0;
-            error_named("No such accented character as", uac);
-        }
-    }
-    else
-    {   int32 total = 0;
-        int d=0; i=1;
-        while (text[++i] != '}')
-        {   if (text[i] == 0)
-            {   error("'@{' without matching '}'");
-                total = '?'; break;
-            }
-            if (i == 8)
-            {   error("At most six hexadecimal digits allowed in '@{...}'");
-                total = '?'; break;
-            }
-            d = character_digit_value[(uchar)text[i]];
-            if (d == 127)
-            {   error("'@{...}' may only contain hexadecimal digits");
-                total = '?'; break;
-            }
-            total = total*16 + d;
-        }
-        while ((text[i] != '}') && (text[i] != 0)) i++;
-        if (text[i] == '}') i++;
-        textual_form_length = i;
-        return total;
-    }
-
-    textual_form_length = 1;
-    return '?';
-}
-
-/* ------------------------------------------------------------------------- */
-/*  (5) Zscii -> Text                                                        */
-/*                                                                           */
-/*  Used for printing out dictionary contents into the text transcript file  */
-/*  or on-screen (in response to the Trace dictionary directive).            */
-/*  In either case, output uses the same ISO set as the source code.         */
-/* ------------------------------------------------------------------------- */
-
-extern void zscii_to_text(char *text, int zscii)
-{   int i;
-    int32 unicode;
-
-    if ((zscii < 0x100) && (zscii_to_iso_grid[zscii] != 0))
-    {   text[0] = zscii_to_iso_grid[zscii]; text[1] = 0; return;
-    }
-
-    unicode = zscii_to_unicode(zscii);
-    for (i=0;i<69;i++)
-        if (default_zscii_to_unicode_c01[i] == unicode)
-        {   text[0] = '@';
-            text[1] = accents[2*i];
-            text[2] = accents[2*i+1];
-            text[3] = 0; return;
-        }
-    sprintf(text, "@{%x}", unicode);
-}
-
-/* ========================================================================= */
-
-extern char *name_of_iso_set(int s)
-{   switch(s)
-    {   case 1: return "Latin1";
-        case 2: return "Latin2";
-        case 3: return "Latin3";
-        case 4: return "Latin4";
-        case 5: return "Cyrillic";
-        case 6: return "Arabic";
-        case 7: return "Greek";
-        case 8: return "Hebrew";
-        case 9: return "Latin5";
-    }
-    return "Plain ASCII";
-}
-
-extern void change_character_set(void)
-{   make_source_to_iso_grid();
-    make_unicode_zscii_map();
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Case translation of standard Roman letters within ISO                   */
-/* ------------------------------------------------------------------------- */
-
-extern void make_lower_case(char *str)
-{   int i;
-    for (i=0; str[i]!=0; i++)
-        if ((((uchar)str[i])<128) && (isupper(str[i]))) str[i]=tolower(str[i]);
-}
-
-extern void make_upper_case(char *str)
-{   int i;
-    for (i=0; str[i]!=0; i++)
-        if ((((uchar)str[i])<128) && (islower(str[i]))) str[i]=toupper(str[i]);
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_chars_vars(void)
-{   int n;
-    for (n=0; n<128; n++) character_digit_value[n] = 127;
-    character_digit_value['0'] = 0;
-    character_digit_value['1'] = 1;
-    character_digit_value['2'] = 2;
-    character_digit_value['3'] = 3;
-    character_digit_value['4'] = 4;
-    character_digit_value['5'] = 5;
-    character_digit_value['6'] = 6;
-    character_digit_value['7'] = 7;
-    character_digit_value['8'] = 8;
-    character_digit_value['9'] = 9;
-    character_digit_value['a'] = 10;
-    character_digit_value['b'] = 11;
-    character_digit_value['c'] = 12;
-    character_digit_value['d'] = 13;
-    character_digit_value['e'] = 14;
-    character_digit_value['f'] = 15;
-    character_digit_value['A'] = 10;
-    character_digit_value['B'] = 11;
-    character_digit_value['C'] = 12;
-    character_digit_value['D'] = 13;
-    character_digit_value['E'] = 14;
-    character_digit_value['F'] = 15;
-
-    strcpy((char *) alphabet[0], "abcdefghijklmnopqrstuvwxyz");
-    strcpy((char *) alphabet[1], "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-    strcpy((char *) alphabet[2], " ^0123456789.,!?_#'~/\\-:()");
-
-    alphabet_modified = FALSE;
-
-    for (n=0; n<78; n++) alphabet_used[n] = 'N';
-
-    change_character_set();
-}
-
-extern void chars_begin_pass(void)
-{
-}
-
-extern void chars_allocate_arrays(void)
-{
-}
-
-extern void chars_free_arrays(void)
-{
-}
-
-/* ========================================================================= */
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..0868807
--- /dev/null
@@ -0,0 +1,40 @@
+# Process this file with autoconf to produce a configure script.
+#
+# 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
+# theFree 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/
+
+AC_INIT([inform], m4_esyscmd_s([./version.sh]), [j@jxself.org])
+AM_INIT_AUTOMAKE([foreign])
+AC_OUTPUT(Makefile src/Makefile)
+
+# Checks for programs.
+AC_PROG_CC
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_CHECK_HEADERS([limits.h stdlib.h string.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_CHECK_HEADER_STDBOOL
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS([memmove memset realpath strchr strtol])
+
+AC_OUTPUT
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)
-{
-}
-
-/* ========================================================================= */
diff --git a/errors.c b/errors.c
deleted file mode 100644 (file)
index b76aa7d..0000000
--- a/errors.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "errors" : Warnings, errors and fatal errors                            */
-/*              (with error throwback code for RISC OS machines)             */
-/*                                                                           */
-/* 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"
-
-#define ERROR_BUFLEN (256)
-static char error_message_buff[ERROR_BUFLEN+4]; /* room for ellipsis */
-
-/* ------------------------------------------------------------------------- */
-/*   Error preamble printing.                                                */
-/* ------------------------------------------------------------------------- */
-
-ErrorPosition ErrorReport;             /*  Maintained by "lexer.c"           */
-
-static void print_preamble(void)
-{
-    /*  Only really prints the preamble to an error or warning message:
-
-        e.g.  "jigsaw.apollo", line 24:
-
-        The format is controllable (from an ICL switch) since this assists
-        the working of some development environments.                        */
-
-    int j, with_extension_flag = FALSE; char *p;
-
-    j = ErrorReport.file_number;
-    if (j <= 0 || j > total_files) p = ErrorReport.source;
-    else p = InputFiles[j-1].filename;
-
-    if (!p) p = "";
-    
-    switch(error_format)
-    {
-        case 0:  /* RISC OS error message format */
-
-            if (!(ErrorReport.main_flag)) printf("\"%s\", ", p);
-            printf("line %d: ", ErrorReport.line_number);
-            if (ErrorReport.orig_file) {
-                char *op;
-                if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
-                    op = ErrorReport.orig_source;
-                else
-                    op = InputFiles[ErrorReport.orig_file-1].filename;
-                printf("(\"%s\"", op);
-                if (ErrorReport.orig_line) {
-                    printf(", %d", ErrorReport.orig_line);
-                    if (ErrorReport.orig_char) {
-                        printf(":%d", ErrorReport.orig_char);
-                    }
-                }