Introduction
------------
Small is a simple, typeless, 32-bit extension language with a C-like syntax.
The Small compiler outputs P-code (or bytecode) that subsequently runs on an
abstract machine. Execution speed, stability, simplicity and a small footprint
were essential design criterions for both the language and the abstract
machine.


Acknowledgements
----------------
The assembler version of the abstract machine (five times faster than the ANSI
C version and over two times faster than the GNU C version) was written by
Marc Peter (mrp@rz.uni-jena.de). Marc holds the copyright of the file
AMXEXEC.ASM, but its distribution and license fall under the same condintions
as those stated in LICENSE.TXT.

Note: the precompiled versions of the software are 16-bit DOS programs that
do not use Marc Peter's assembler interface. This was chosen so that the
precompiled programs run on a large number of platforms; do not use these
precompiled samples for benchmarking.


Compiling the software, general notes
-------------------------------------
The C sources contain sections of code that is conditionally compiled. See
your compiler manual how to specify options on the command line or in a
"project" to set these options.

Both the compiler and the abstract machine contain assertions to help me
catch bugs while maintaining the code. In the retail versions, you will want
to compile without assertions, because this code slows down the operation of
the tools. To do so, compile the compiler or the abstract machine with the
NDEBUG definition set.

I personally use "makefiles" and the command line utilities of compilers. It
is partly because of my inexperience with IDE's and "developer studio's", and
partly for the sake of brevity that I only give compiling examples with the
command line tools.


Compiling the Abstract Machine
------------------------------
Compiling the AMX is fairly easy, because it was set up to be small and
portable. The abstract machine was intended to be linked with an application.
The file SRUN is the most primitive application that I could come up with. It
runs a compiled Small program from the command line. All of the example
programs run with SRUN.

Below are a few examples of compiler options:

Borland C++ version 3.1, 16-bit:
        bcc srun.c amx.c amxcore.c amxcons.c

Microsoft Visual C/C++ version 5.0, 32-bit
        cl srun.c amx.c amxcons.c amxcore.c
        (note: when running with warning level 4, option "-W4", Visual C/C++
        issues a few warnings for unused function arguments and changes of
        the default structure alignment)

Watcom C/C++ version 11.0, 32-bit:
        wcl386 /l=nt srun.c amx.c amxcore.c amxcons.c
    or
        wcl386 /l=nt /dASM32 srun.c amx.c amxcore.c amxcons.c amxexec.asm

GNU GCC version 2.8.1 (MS-DOS port by DJ Delorie: DJGPP version 2.01), 32-bit:
        gcc -o srun.exe srun.c amx.c amxcore.c amxcons.c

    (note: when running with all warnings enabled, option "-Wall", the GNU C
    compiler suggests extra parantheses around subexpressions in a logical
    expresion; I do not agree with the desirability of extra parantheses is
    this case, so I have not added them)

Note that the lines above have as few command line options as needed. Consult
the compiler documentation to add debugging information or to enable
optimizations. The source files also contain "assertions" at various places.
Again, consult the compiler documentation to remove the assertions (and get a
modest performance gain).

The AMX.C file has special code for the GNU C compiler (GCC), which makes the
abstract machine about twice as fast as when it is compiled with other
compilers.

The second alternative for Watcom C/C++ 11.0 compiles Marc Peter's assembler
implementation of the abstract machine. It is five times faster than the
ANSI C version. As you can see on the command line, the C files need the
ASM32 macro to be defined.

The "core" AMX routines do not use or depend on dynamic memory allocation or
console IO. The "property" functions in AMXCORE.C use malloc()/free(); you
can remove these property set/retrieval functions by compiling the AMXCORE.C
file with the definition NOPROPLIST.

The console IO functions in AMXCONS.C try to use standard C as much as
possible, but some of the functions also rely on ANSI terminal codes (ANSI.SYS
under DOS). In any case, in a "real" environment, you will probably want to
replace AMXCONS.C with an alternative that fits your application or operating
system.

The abstract machine provides hooks for debugging support. These hooks slow
down the execution of a compiled program somewhat. For optimal performance
and a slightly smaller abstract machine, strip off the debugging support by
defining the macro NODBGCALLS.

Summary of definitions
    ASM32               compile the assembler version
    NDEBUG              compile without assertions
    NODBGCALLS          remove the debugger support
    NOPROPLIST          remove the get/set property functions from AMXCORE.C


Compiling the Small compiler
----------------------------
The Small language is case sensitive, but you can make a case insensitive
version by adding the definition NO_CASE_SENSITIVE.

If you want a 16-bit version, add the definition BIT16 to the compiler options.
The header file boldly assumes that a "short int" is 16-bits and a "long int"
is 32-bits. If this is not true for your compiler, you must change the
definition of the cell type in SC.H, but you must also check the locations
where there is an "#if defined(BIT16)" around some code, because I use the
constants SHORT_MAX and LONG_MAX from LIMITS.H as well.
N.B. I have not ever tested, or even tried to compile, a 16-bit version of
     any of the Small tools.

The basic code generation is followed by a simple peephole optimizer. If you
stumble on a code generation bug, one of the first things that you may want
to find out is whether this bug is in the code generation or in the optimizer.
For that purpose, you can compile the compiler without peephole optimizer,
using the definition NO_OPTIMIZE.

In Small, one creates symbolic constants with the "const" keyword. But Small
also supports "#define" to provide sime level of compatibility with C or other
C like tools. The "#define" directive of Small can only declare numeric
constants, it is much more limited than C's #define. Therefore, may may find
this "portability" clumsy and rather confusing. If so, compiling with option
NO_DEFINE removes the support for the #define directive in the Small compiler.

I have compiled and tested the compiler with:
* Borland C++ 3.1, 16-bit in small and large memory models
* Microsoft C 6.0, 16-bit in small and large memory models
* Watcom C/C++ 11.0, 32-bit flat mode (Executable for Windows NT)
Both 16-bit compilers are old, but this should not matter. The code is
intended to be ANSI C as much as possible.

Summary of definitions
    BIT16               cell is 16-bits, rather than 32-bits
    NDEBUG              compile without assertions
    NO_CASE_SENSITIVE   set compiler to case insensitive
    NO_DEFINE           remove support for #define directive
    NO_OPTIMIZE         remove the peephole optimizer step

