From: Jason Self Date: Sat, 13 Jul 2019 17:16:55 +0000 (-0700) Subject: Implement a Makefile for Inform. X-Git-Tag: v6.35~8 X-Git-Url: https://jxself.org/git/?p=inform.git;a=commitdiff_plain;h=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;ds=sidebyside Implement a Makefile for Inform. Move source code into the src directory, dynamically compute the version number. --- diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d7162af --- /dev/null +++ b/.gitattributes @@ -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 index 0000000..07c7a21 --- /dev/null +++ b/.gitignore @@ -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 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 '' 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 index 0000000..b73d721 --- /dev/null +++ b/Makefile.am @@ -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 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 | */ -/* | = */ -/* | */ -/* */ -/* Array */ -/* */ -/* where an array specification is: */ -/* */ -/* | -> | */ -/* | --> | ... */ -/* | string | [ [,] [;] ... ]; */ -/* | 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(""); - debug_file_printf("%s", global_name); - debug_file_printf("
"); - write_debug_global_backpatch(svals[global_symbol]); - debug_file_printf("
"); - write_debug_locations - (get_token_location_end(beginning_debug_location)); - debug_file_printf("
"); - } - 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(""); - debug_file_printf("%s", global_name); - debug_file_printf("
"); - write_debug_global_backpatch(svals[global_symbol]); - debug_file_printf("
"); - write_debug_locations - (get_token_location_end(beginning_debug_location)); - debug_file_printf("
"); - } - 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= 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(""); - debug_file_printf("%s", global_name); - debug_file_printf(""); - write_debug_array_backpatch(svals[global_symbol]); - debug_file_printf(""); - debug_file_printf - ("%d", - dynamic_array_area_size - array_base); - debug_file_printf - ("%d", - array_entry_size); - debug_file_printf - ("%s", - (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(""); - } - - 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 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= 256 && i < 286) - { if (i - 256 < NUMBER_SYSTEM_FUNCTIONS) return system_functions.keywords[i - 256]; - return ""; - } - } - 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(""); 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(""); - return; - case OMITTED_OT: printf(""); 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=" "; break; - case TWO: p=" "; 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), " "); return; - case LABEL: sprintf(q+strlen(q), "