Removed files for dead branch: faluco faluco
authorScott Ehlert <ds@alliedmods.net>
Sun Sep 14 02:54:50 2008 -0500 (2008-09-14)
branchfaluco
changeset 228205c25f435814
parent 16 1feb2e0ff0ce
child 2285 9dd80a672eb9
Removed files for dead branch: faluco
compiler-init/amx.h
compiler-init/amxdbg.h
compiler-init/libpawnc.c
compiler-init/libpawnc.rc
compiler-init/lstring.c
compiler-init/lstring.h
compiler-init/memfile.c
compiler-init/memfile.h
compiler-init/osdefs.h
compiler-init/pawn.ico
compiler-init/pawncc.c
compiler-init/sc.h
compiler-init/sc1.c
compiler-init/sc2.c
compiler-init/sc3.c
compiler-init/sc4.c
compiler-init/sc5.c
compiler-init/sc5.scp
compiler-init/sc6.c
compiler-init/sc7.c
compiler-init/sc7.scp
compiler-init/scexpand.c
compiler-init/sci18n.c
compiler-init/sclist.c
compiler-init/scmemfil.c
compiler-init/scstate.c
compiler-init/scvars.c
compiler-init/spcomp.sln
compiler-init/spcomp.vcproj
compiler-init/svnrev.h
     1.1 --- a/compiler-init/amx.h	Sat Jul 15 01:36:48 2006 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,462 +0,0 @@
     1.4 -/*  Pawn Abstract Machine (for the Pawn language)
     1.5 - *
     1.6 - *  Copyright (c) ITB CompuPhase, 1997-2006
     1.7 - *
     1.8 - *  This software is provided "as-is", without any express or implied warranty.
     1.9 - *  In no event will the authors be held liable for any damages arising from
    1.10 - *  the use of this software.
    1.11 - *
    1.12 - *  Permission is granted to anyone to use this software for any purpose,
    1.13 - *  including commercial applications, and to alter it and redistribute it
    1.14 - *  freely, subject to the following restrictions:
    1.15 - *
    1.16 - *  1.  The origin of this software must not be misrepresented; you must not
    1.17 - *      claim that you wrote the original software. If you use this software in
    1.18 - *      a product, an acknowledgment in the product documentation would be
    1.19 - *      appreciated but is not required.
    1.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
    1.21 - *      misrepresented as being the original software.
    1.22 - *  3.  This notice may not be removed or altered from any source distribution.
    1.23 - *
    1.24 - *  Version: $Id: amx.h 3579 2006-06-06 13:35:29Z thiadmer $
    1.25 - */
    1.26 -
    1.27 -#ifndef AMX_H_INCLUDED
    1.28 -#define AMX_H_INCLUDED
    1.29 -
    1.30 -#include <stdlib.h>   /* for size_t */
    1.31 -#include <limits.h>
    1.32 -
    1.33 -#if defined FREEBSD && !defined __FreeBSD__
    1.34 -  #define __FreeBSD__
    1.35 -#endif
    1.36 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
    1.37 -  #include <sclinux.h>
    1.38 -#endif
    1.39 -
    1.40 -#if defined HAVE_STDINT_H
    1.41 -  #include <stdint.h>
    1.42 -#else
    1.43 -  #if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200)
    1.44 -    #if defined HAVE_INTTYPES_H
    1.45 -      #include <inttypes.h>
    1.46 -    #else
    1.47 -      #include <stdint.h>
    1.48 -    #endif
    1.49 -  #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
    1.50 -    /* The ISO C99 defines the int16_t and int_32t types. If the compiler got
    1.51 -     * here, these types are probably undefined.
    1.52 -     */
    1.53 -    #if defined __MACH__
    1.54 -      #include <ppc/types.h>
    1.55 -      typedef unsigned short int  uint16_t;
    1.56 -      typedef unsigned long int   uint32_t;
    1.57 -    #elif defined __FreeBSD__
    1.58 -      #include <inttypes.h>
    1.59 -    #else
    1.60 -      typedef short int           int16_t;
    1.61 -      typedef unsigned short int  uint16_t;
    1.62 -      #if defined SN_TARGET_PS2
    1.63 -        typedef int               int32_t;
    1.64 -        typedef unsigned int      uint32_t;
    1.65 -      #else
    1.66 -        typedef long int          int32_t;
    1.67 -        typedef unsigned long int uint32_t;
    1.68 -      #endif
    1.69 -      #if defined __WIN32__ || defined _WIN32 || defined WIN32
    1.70 -        typedef __int64	          int64_t;
    1.71 -        typedef unsigned __int64  uint64_t;
    1.72 -        #define HAVE_I64
    1.73 -      #elif defined __GNUC__
    1.74 -        typedef long long         int64_t;
    1.75 -        typedef unsigned long long uint64_t;
    1.76 -        #define HAVE_I64
    1.77 -      #endif
    1.78 -    #endif
    1.79 -  #endif
    1.80 -  #define HAVE_STDINT_H
    1.81 -#endif
    1.82 -#if defined _LP64 || defined WIN64 || defined _WIN64
    1.83 -  #if !defined __64BIT__
    1.84 -    #define __64BIT__
    1.85 -  #endif
    1.86 -#endif
    1.87 -
    1.88 -#if HAVE_ALLOCA_H
    1.89 -  #include <alloca.h>
    1.90 -#endif
    1.91 -#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
    1.92 -  #if !defined alloca
    1.93 -    #define alloca(n)   _alloca(n)
    1.94 -  #endif
    1.95 -#endif
    1.96 -
    1.97 -#if !defined arraysize
    1.98 -  #define arraysize(array)  (sizeof(array) / sizeof((array)[0]))
    1.99 -#endif
   1.100 -#if !defined assert_static
   1.101 -  /* see "Compile-Time Assertions" by Ralf Holly,
   1.102 -   * C/C++ Users Journal, November 2004
   1.103 -   */
   1.104 -  #define assert_static(e) \
   1.105 -    do { \
   1.106 -      enum { assert_static__ = 1/(e) }; \
   1.107 -    } while (0)
   1.108 -#endif
   1.109 -
   1.110 -#ifdef  __cplusplus
   1.111 -extern  "C" {
   1.112 -#endif
   1.113 -
   1.114 -#if defined PAWN_DLL
   1.115 -  #if !defined AMX_NATIVE_CALL
   1.116 -    #define AMX_NATIVE_CALL __stdcall
   1.117 -  #endif
   1.118 -  #if !defined AMXAPI
   1.119 -    #define AMXAPI          __stdcall
   1.120 -  #endif
   1.121 -#endif
   1.122 -
   1.123 -/* calling convention for native functions */
   1.124 -#if !defined AMX_NATIVE_CALL
   1.125 -  #define AMX_NATIVE_CALL
   1.126 -#endif
   1.127 -/* calling convention for all interface functions and callback functions */
   1.128 -#if !defined AMXAPI
   1.129 -  #if defined STDECL
   1.130 -    #define AMXAPI      __stdcall
   1.131 -  #elif defined CDECL
   1.132 -    #define AMXAPI      __cdecl
   1.133 -  #elif defined GCC_HASCLASSVISIBILITY
   1.134 -    #define AMXAPI __attribute__ ((visibility("default")))
   1.135 -  #else
   1.136 -    #define AMXAPI
   1.137 -  #endif
   1.138 -#endif
   1.139 -#if !defined AMXEXPORT
   1.140 -  #define AMXEXPORT
   1.141 -#endif
   1.142 -
   1.143 -/* File format version (in CUR_FILE_VERSION)
   1.144 - *   0 (original version)
   1.145 - *   1 (opcodes JUMP.pri, SWITCH and CASETBL)
   1.146 - *   2 (compressed files)
   1.147 - *   3 (public variables)
   1.148 - *   4 (opcodes SWAP.pri/alt and PUSHADDR)
   1.149 - *   5 (tagnames table)
   1.150 - *   6 (reformatted header)
   1.151 - *   7 (name table, opcodes SYMTAG & SYSREQ.D)
   1.152 - *   8 (opcode STMT, renewed debug interface)
   1.153 - *   9 (macro opcodes)
   1.154 - * MIN_FILE_VERSION is the lowest file version number that the current AMX
   1.155 - * implementation supports. If the AMX file header gets new fields, this number
   1.156 - * often needs to be incremented. MAX_AMX_VERSION is the lowest AMX version that
   1.157 - * is needed to support the current file version. When there are new opcodes,
   1.158 - * this number needs to be incremented.
   1.159 - * The file version supported by the JIT may run behind MIN_AMX_VERSION. So
   1.160 - * there is an extra constant for it: MAX_FILE_VER_JIT.
   1.161 - */
   1.162 -#define CUR_FILE_VERSION  9     /* current file version; also the current AMX version */
   1.163 -#define MIN_FILE_VERSION  6     /* lowest supported file format version for the current AMX version */
   1.164 -#define MIN_AMX_VERSION   9     /* minimum AMX version needed to support the current file format */
   1.165 -#define MAX_FILE_VER_JIT  8     /* file version supported by the JIT */
   1.166 -#define MIN_AMX_VER_JIT   8     /* AMX version supported by the JIT */
   1.167 -
   1.168 -#if !defined PAWN_CELL_SIZE
   1.169 -  #define PAWN_CELL_SIZE 32     /* by default, use 32-bit cells */
   1.170 -#endif
   1.171 -#if PAWN_CELL_SIZE==16
   1.172 -  typedef uint16_t  ucell;
   1.173 -  typedef int16_t   cell;
   1.174 -#elif PAWN_CELL_SIZE==32
   1.175 -  typedef uint32_t  ucell;
   1.176 -  typedef int32_t   cell;
   1.177 -#elif PAWN_CELL_SIZE==64
   1.178 -  typedef uint64_t  ucell;
   1.179 -  typedef int64_t   cell;
   1.180 -#else
   1.181 -  #error Unsupported cell size (PAWN_CELL_SIZE)
   1.182 -#endif
   1.183 -
   1.184 -#define UNPACKEDMAX   (((cell)1 << (sizeof(cell)-1)*8) - 1)
   1.185 -#define UNLIMITED     (~1u >> 1)
   1.186 -
   1.187 -struct tagAMX;
   1.188 -typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
   1.189 -typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
   1.190 -                                   cell *result, cell *params);
   1.191 -typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
   1.192 -typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX *, cell *, int));
   1.193 -#if !defined _FAR
   1.194 -  #define _FAR
   1.195 -#endif
   1.196 -
   1.197 -#if defined _MSC_VER
   1.198 -  #pragma warning(disable:4103)  /* disable warning message 4103 that complains
   1.199 -                                  * about pragma pack in a header file */
   1.200 -  #pragma warning(disable:4100)  /* "'%$S' : unreferenced formal parameter" */
   1.201 -#endif
   1.202 -
   1.203 -/* Some compilers do not support the #pragma align, which should be fine. Some
   1.204 - * compilers give a warning on unknown #pragmas, which is not so fine...
   1.205 - */
   1.206 -#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
   1.207 -  #define AMX_NO_ALIGN
   1.208 -#endif
   1.209 -
   1.210 -#if defined __GNUC__
   1.211 -  #define PACKED        __attribute__((packed))
   1.212 -#else
   1.213 -  #define PACKED
   1.214 -#endif
   1.215 -
   1.216 -#if !defined AMX_NO_ALIGN
   1.217 -  #if defined LINUX || defined __FreeBSD__
   1.218 -    #pragma pack(1)         /* structures must be packed (byte-aligned) */
   1.219 -  #elif defined MACOS && defined __MWERKS__
   1.220 -	#pragma options align=mac68k
   1.221 -  #else
   1.222 -    #pragma pack(push)
   1.223 -    #pragma pack(1)         /* structures must be packed (byte-aligned) */
   1.224 -    #if defined __TURBOC__
   1.225 -      #pragma option -a-    /* "pack" pragma for older Borland compilers */
   1.226 -    #endif
   1.227 -  #endif
   1.228 -#endif
   1.229 -
   1.230 -typedef struct tagAMX_NATIVE_INFO {
   1.231 -  const char _FAR *name PACKED;
   1.232 -  AMX_NATIVE func       PACKED;
   1.233 -} AMX_NATIVE_INFO;
   1.234 -
   1.235 -#define AMX_USERNUM     4
   1.236 -#define sEXPMAX         19      /* maximum name length for file version <= 6 */
   1.237 -#define sNAMEMAX        31      /* maximum name length of symbol name */
   1.238 -
   1.239 -typedef struct tagAMX_FUNCSTUB {
   1.240 -  ucell address         PACKED;
   1.241 -  char name[sEXPMAX+1]  PACKED;
   1.242 -} AMX_FUNCSTUB;
   1.243 -
   1.244 -typedef struct tagFUNCSTUBNT {
   1.245 -  ucell address         PACKED;
   1.246 -  uint32_t nameofs      PACKED;
   1.247 -} AMX_FUNCSTUBNT;
   1.248 -
   1.249 -/* The AMX structure is the internal structure for many functions. Not all
   1.250 - * fields are valid at all times; many fields are cached in local variables.
   1.251 - */
   1.252 -typedef struct tagAMX {
   1.253 -  unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */
   1.254 -  unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
   1.255 -  AMX_CALLBACK callback PACKED;
   1.256 -  AMX_DEBUG debug       PACKED; /* debug callback */
   1.257 -  /* for external functions a few registers must be accessible from the outside */
   1.258 -  cell cip              PACKED; /* instruction pointer: relative to base + amxhdr->cod */
   1.259 -  cell frm              PACKED; /* stack frame base: relative to base + amxhdr->dat */
   1.260 -  cell hea              PACKED; /* top of the heap: relative to base + amxhdr->dat */
   1.261 -  cell hlw              PACKED; /* bottom of the heap: relative to base + amxhdr->dat */
   1.262 -  cell stk              PACKED; /* stack pointer: relative to base + amxhdr->dat */
   1.263 -  cell stp              PACKED; /* top of the stack: relative to base + amxhdr->dat */
   1.264 -  int flags             PACKED; /* current status, see amx_Flags() */
   1.265 -  /* user data */
   1.266 -  long usertags[AMX_USERNUM] PACKED;
   1.267 -  void _FAR *userdata[AMX_USERNUM] PACKED;
   1.268 -  /* native functions can raise an error */
   1.269 -  int error             PACKED;
   1.270 -  /* passing parameters requires a "count" field */
   1.271 -  int paramcount;
   1.272 -  /* the sleep opcode needs to store the full AMX status */
   1.273 -  cell pri              PACKED;
   1.274 -  cell alt              PACKED;
   1.275 -  cell reset_stk        PACKED;
   1.276 -  cell reset_hea        PACKED;
   1.277 -  cell sysreq_d         PACKED; /* relocated address/value for the SYSREQ.D opcode */
   1.278 -  #if defined JIT
   1.279 -    /* support variables for the JIT */
   1.280 -    int reloc_size      PACKED; /* required temporary buffer for relocations */
   1.281 -    long code_size      PACKED; /* estimated memory footprint of the native code */
   1.282 -  #endif
   1.283 -} AMX;
   1.284 -
   1.285 -/* The AMX_HEADER structure is both the memory format as the file format. The
   1.286 - * structure is used internaly.
   1.287 - */
   1.288 -typedef struct tagAMX_HEADER {
   1.289 -  int32_t size          PACKED; /* size of the "file" */
   1.290 -  uint16_t magic        PACKED; /* signature */
   1.291 -  char    file_version  PACKED; /* file format version */
   1.292 -  char    amx_version   PACKED; /* required version of the AMX */
   1.293 -  int16_t flags         PACKED;
   1.294 -  int16_t defsize       PACKED; /* size of a definition record */
   1.295 -  int32_t cod           PACKED; /* initial value of COD - code block */
   1.296 -  int32_t dat           PACKED; /* initial value of DAT - data block */
   1.297 -  int32_t hea           PACKED; /* initial value of HEA - start of the heap */
   1.298 -  int32_t stp           PACKED; /* initial value of STP - stack top */
   1.299 -  int32_t cip           PACKED; /* initial value of CIP - the instruction pointer */
   1.300 -  int32_t publics       PACKED; /* offset to the "public functions" table */
   1.301 -  int32_t natives       PACKED; /* offset to the "native functions" table */
   1.302 -  int32_t libraries     PACKED; /* offset to the table of libraries */
   1.303 -  int32_t pubvars       PACKED; /* the "public variables" table */
   1.304 -  int32_t tags          PACKED; /* the "public tagnames" table */
   1.305 -  int32_t nametable     PACKED; /* name table */
   1.306 -} AMX_HEADER;
   1.307 -
   1.308 -#if PAWN_CELL_SIZE==16
   1.309 -  #define AMX_MAGIC     0xf1e2
   1.310 -#elif PAWN_CELL_SIZE==32
   1.311 -  #define AMX_MAGIC     0xf1e0
   1.312 -#elif PAWN_CELL_SIZE==64
   1.313 -  #define AMX_MAGIC     0xf1e1
   1.314 -#endif
   1.315 -
   1.316 -enum {
   1.317 -  AMX_ERR_NONE,
   1.318 -  /* reserve the first 15 error codes for exit codes of the abstract machine */
   1.319 -  AMX_ERR_EXIT,         /* forced exit */
   1.320 -  AMX_ERR_ASSERT,       /* assertion failed */
   1.321 -  AMX_ERR_STACKERR,     /* stack/heap collision */
   1.322 -  AMX_ERR_BOUNDS,       /* index out of bounds */
   1.323 -  AMX_ERR_MEMACCESS,    /* invalid memory access */
   1.324 -  AMX_ERR_INVINSTR,     /* invalid instruction */
   1.325 -  AMX_ERR_STACKLOW,     /* stack underflow */
   1.326 -  AMX_ERR_HEAPLOW,      /* heap underflow */
   1.327 -  AMX_ERR_CALLBACK,     /* no callback, or invalid callback */
   1.328 -  AMX_ERR_NATIVE,       /* native function failed */
   1.329 -  AMX_ERR_DIVIDE,       /* divide by zero */
   1.330 -  AMX_ERR_SLEEP,        /* go into sleepmode - code can be restarted */
   1.331 -  AMX_ERR_INVSTATE,     /* invalid state for this access */
   1.332 -
   1.333 -  AMX_ERR_MEMORY = 16,  /* out of memory */
   1.334 -  AMX_ERR_FORMAT,       /* invalid file format */
   1.335 -  AMX_ERR_VERSION,      /* file is for a newer version of the AMX */
   1.336 -  AMX_ERR_NOTFOUND,     /* function not found */
   1.337 -  AMX_ERR_INDEX,        /* invalid index parameter (bad entry point) */
   1.338 -  AMX_ERR_DEBUG,        /* debugger cannot run */
   1.339 -  AMX_ERR_INIT,         /* AMX not initialized (or doubly initialized) */
   1.340 -  AMX_ERR_USERDATA,     /* unable to set user data field (table full) */
   1.341 -  AMX_ERR_INIT_JIT,     /* cannot initialize the JIT */
   1.342 -  AMX_ERR_PARAMS,       /* parameter error */
   1.343 -  AMX_ERR_DOMAIN,       /* domain error, expression result does not fit in range */
   1.344 -  AMX_ERR_GENERAL,      /* general error (unknown or unspecific error) */
   1.345 -};
   1.346 -
   1.347 -/*      AMX_FLAG_CHAR16   0x01     no longer used */
   1.348 -#define AMX_FLAG_DEBUG    0x02  /* symbolic info. available */
   1.349 -#define AMX_FLAG_COMPACT  0x04  /* compact encoding */
   1.350 -#define AMX_FLAG_SLEEP    0x08  /* script uses the sleep instruction (possible re-entry or power-down mode) */
   1.351 -#define AMX_FLAG_NOCHECKS 0x10  /* no array bounds checking; no BREAK opcodes */
   1.352 -#define AMX_FLAG_NTVREG 0x1000  /* all native functions are registered */
   1.353 -#define AMX_FLAG_JITC   0x2000  /* abstract machine is JIT compiled */
   1.354 -#define AMX_FLAG_BROWSE 0x4000  /* busy browsing */
   1.355 -#define AMX_FLAG_RELOC  0x8000  /* jump/call addresses relocated */
   1.356 -
   1.357 -#define AMX_EXEC_MAIN   (-1)    /* start at program entry point */
   1.358 -#define AMX_EXEC_CONT   (-2)    /* continue from last address */
   1.359 -
   1.360 -#define AMX_USERTAG(a,b,c,d)    ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
   1.361 -
   1.362 -#if !defined AMX_COMPACTMARGIN
   1.363 -  #define AMX_COMPACTMARGIN 64
   1.364 -#endif
   1.365 -
   1.366 -/* for native functions that use floating point parameters, the following
   1.367 - * two macros are convenient for casting a "cell" into a "float" type _without_
   1.368 - * changing the bit pattern
   1.369 - */
   1.370 -#if PAWN_CELL_SIZE==32
   1.371 -  #define amx_ftoc(f)   ( * ((cell*)&f) )   /* float to cell */
   1.372 -  #define amx_ctof(c)   ( * ((float*)&c) )  /* cell to float */
   1.373 -#elif PAWN_CELL_SIZE==64
   1.374 -  #define amx_ftoc(f)   ( * ((cell*)&f) )   /* float to cell */
   1.375 -  #define amx_ctof(c)   ( * ((double*)&c) ) /* cell to float */
   1.376 -#else
   1.377 -  #error Unsupported cell size
   1.378 -#endif
   1.379 -
   1.380 -#define amx_StrParam(amx,param,result)                                      \
   1.381 -    do {                                                                    \
   1.382 -      cell *amx_cstr_; int amx_length_;                                     \
   1.383 -      amx_GetAddr((amx), (param), &amx_cstr_);                              \
   1.384 -      amx_StrLen(amx_cstr_, &amx_length_);                                  \
   1.385 -      if (amx_length_ > 0 &&                                                \
   1.386 -          ((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
   1.387 -        amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \
   1.388 -      else (result) = NULL;                                                 \
   1.389 -    } while (0)
   1.390 -
   1.391 -uint16_t * AMXAPI amx_Align16(uint16_t *v);
   1.392 -uint32_t * AMXAPI amx_Align32(uint32_t *v);
   1.393 -#if defined _I64_MAX || defined HAVE_I64
   1.394 -  uint64_t * AMXAPI amx_Align64(uint64_t *v);
   1.395 -#endif
   1.396 -int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
   1.397 -int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
   1.398 -int AMXAPI amx_Cleanup(AMX *amx);
   1.399 -int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
   1.400 -int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
   1.401 -int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
   1.402 -int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
   1.403 -int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr);
   1.404 -int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
   1.405 -int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
   1.406 -int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
   1.407 -int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
   1.408 -int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
   1.409 -int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
   1.410 -int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
   1.411 -int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
   1.412 -int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
   1.413 -int AMXAPI amx_Init(AMX *amx, void *program);
   1.414 -int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
   1.415 -int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
   1.416 -int AMXAPI amx_NameLength(AMX *amx, int *length);
   1.417 -AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func);
   1.418 -int AMXAPI amx_NumNatives(AMX *amx, int *number);
   1.419 -int AMXAPI amx_NumPublics(AMX *amx, int *number);
   1.420 -int AMXAPI amx_NumPubVars(AMX *amx, int *number);
   1.421 -int AMXAPI amx_NumTags(AMX *amx, int *number);
   1.422 -int AMXAPI amx_Push(AMX *amx, cell value);
   1.423 -int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells);
   1.424 -int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
   1.425 -int AMXAPI amx_RaiseError(AMX *amx, int error);
   1.426 -int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
   1.427 -int AMXAPI amx_Release(AMX *amx, cell amx_addr);
   1.428 -int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
   1.429 -int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
   1.430 -int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
   1.431 -int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
   1.432 -int AMXAPI amx_StrLen(const cell *cstring, int *length);
   1.433 -int AMXAPI amx_UTF8Check(const char *string, int *length);
   1.434 -int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
   1.435 -int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
   1.436 -int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
   1.437 -
   1.438 -#if PAWN_CELL_SIZE==16
   1.439 -  #define amx_AlignCell(v) amx_Align16(v)
   1.440 -#elif PAWN_CELL_SIZE==32
   1.441 -  #define amx_AlignCell(v) amx_Align32(v)
   1.442 -#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
   1.443 -  #define amx_AlignCell(v) amx_Align64(v)
   1.444 -#else
   1.445 -  #error Unsupported cell size
   1.446 -#endif
   1.447 -
   1.448 -#define amx_RegisterFunc(amx, name, func) \
   1.449 -  amx_Register((amx), amx_NativeInfo((name),(func)), 1);
   1.450 -
   1.451 -#if !defined AMX_NO_ALIGN
   1.452 -  #if defined LINUX || defined __FreeBSD__
   1.453 -    #pragma pack()    /* reset default packing */
   1.454 -  #elif defined MACOS && defined __MWERKS__
   1.455 -    #pragma options align=reset
   1.456 -  #else
   1.457 -    #pragma pack(pop) /* reset previous packing */
   1.458 -  #endif
   1.459 -#endif
   1.460 -
   1.461 -#ifdef  __cplusplus
   1.462 -}
   1.463 -#endif
   1.464 -
   1.465 -#endif /* AMX_H_INCLUDED */
     2.1 --- a/compiler-init/amxdbg.h	Sat Jul 15 01:36:48 2006 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,172 +0,0 @@
     2.4 -/*  Abstract Machine for the Pawn compiler, debugger support
     2.5 - *
     2.6 - *  This file contains extra definitions that are convenient for debugger
     2.7 - *  support.
     2.8 - *
     2.9 - *  Copyright (c) ITB CompuPhase, 2005-2006
    2.10 - *
    2.11 - *  This software is provided "as-is", without any express or implied warranty.
    2.12 - *  In no event will the authors be held liable for any damages arising from
    2.13 - *  the use of this software.
    2.14 - *
    2.15 - *  Permission is granted to anyone to use this software for any purpose,
    2.16 - *  including commercial applications, and to alter it and redistribute it
    2.17 - *  freely, subject to the following restrictions:
    2.18 - *
    2.19 - *  1.  The origin of this software must not be misrepresented; you must not
    2.20 - *      claim that you wrote the original software. If you use this software in
    2.21 - *      a product, an acknowledgment in the product documentation would be
    2.22 - *      appreciated but is not required.
    2.23 - *  2.  Altered source versions must be plainly marked as such, and must not be
    2.24 - *      misrepresented as being the original software.
    2.25 - *  3.  This notice may not be removed or altered from any source distribution.
    2.26 - *
    2.27 - *  Version: $Id: amxdbg.h 3519 2006-02-17 17:57:04Z thiadmer $
    2.28 - */
    2.29 -
    2.30 -#ifndef AMXDBG_H_INCLUDED
    2.31 -#define AMXDBG_H_INCLUDED
    2.32 -
    2.33 -#ifndef AMX_H_INCLUDED
    2.34 -  #include "amx.h"
    2.35 -#endif
    2.36 -
    2.37 -#ifdef  __cplusplus
    2.38 -extern  "C" {
    2.39 -#endif
    2.40 -
    2.41 -/* Some compilers do not support the #pragma align, which should be fine. Some
    2.42 - * compilers give a warning on unknown #pragmas, which is not so fine...
    2.43 - */
    2.44 -#if defined SN_TARGET_PS2 || defined __GNUC__
    2.45 -  #define AMX_NO_ALIGN
    2.46 -#endif
    2.47 -
    2.48 -#if defined __GNUC__
    2.49 -  #define PACKED        __attribute__((packed))
    2.50 -#else
    2.51 -  #define PACKED
    2.52 -#endif
    2.53 -
    2.54 -#if !defined AMX_NO_ALIGN
    2.55 -  #if defined LINUX || defined __FreeBSD__
    2.56 -    #pragma pack(1)         /* structures must be packed (byte-aligned) */
    2.57 -  #elif defined MACOS && defined __MWERKS__
    2.58 -	#pragma options align=mac68k
    2.59 -  #else
    2.60 -    #pragma pack(push)
    2.61 -    #pragma pack(1)         /* structures must be packed (byte-aligned) */
    2.62 -    #if defined __TURBOC__
    2.63 -      #pragma option -a-    /* "pack" pragma for older Borland compilers */
    2.64 -    #endif
    2.65 -  #endif
    2.66 -#endif
    2.67 -
    2.68 -typedef struct tagAMX_DBG_HDR {
    2.69 -  int32_t size          PACKED; /* size of the debug information chunk */
    2.70 -  uint16_t magic        PACKED; /* signature, must be 0xf1ef */
    2.71 -  char    file_version  PACKED; /* file format version */
    2.72 -  char    amx_version   PACKED; /* required version of the AMX */
    2.73 -  int16_t flags         PACKED; /* currently unused */
    2.74 -  int16_t files         PACKED; /* number of entries in the "file" table */
    2.75 -  int16_t lines         PACKED; /* number of entries in the "line" table */
    2.76 -  int16_t symbols       PACKED; /* number of entries in the "symbol" table */
    2.77 -  int16_t tags          PACKED; /* number of entries in the "tag" table */
    2.78 -  int16_t automatons    PACKED; /* number of entries in the "automaton" table */
    2.79 -  int16_t states        PACKED; /* number of entries in the "state" table */
    2.80 -} PACKED AMX_DBG_HDR;
    2.81 -#define AMX_DBG_MAGIC   0xf1ef
    2.82 -
    2.83 -typedef struct tagAMX_DBG_FILE {
    2.84 -  ucell   address       PACKED; /* address in the code segment where generated code (for this file) starts */
    2.85 -  const char name[1]    PACKED; /* ASCII string, zero-terminated */
    2.86 -} PACKED AMX_DBG_FILE;
    2.87 -
    2.88 -typedef struct tagAMX_DBG_LINE {
    2.89 -  ucell   address       PACKED; /* address in the code segment where generated code (for this line) starts */
    2.90 -  int32_t line          PACKED; /* line number */
    2.91 -} PACKED AMX_DBG_LINE;
    2.92 -
    2.93 -typedef struct tagAMX_DBG_SYMBOL {
    2.94 -  ucell   address       PACKED; /* address in the data segment or relative to the frame */
    2.95 -  int16_t tag           PACKED; /* tag for the symbol */
    2.96 -  ucell   codestart     PACKED; /* address in the code segment from which this symbol is valid (in scope) */
    2.97 -  ucell   codeend       PACKED; /* address in the code segment until which this symbol is valid (in scope) */
    2.98 -  char    ident         PACKED; /* kind of symbol (function/variable) */
    2.99 -  char    vclass        PACKED; /* class of symbol (global/local) */
   2.100 -  int16_t dim           PACKED; /* number of dimensions */
   2.101 -  const char name[1]    PACKED; /* ASCII string, zero-terminated */
   2.102 -} PACKED AMX_DBG_SYMBOL;
   2.103 -
   2.104 -typedef struct tagAMX_DBG_SYMDIM {
   2.105 -  int16_t tag           PACKED; /* tag for the array dimension */
   2.106 -  ucell   size          PACKED; /* size of the array dimension */
   2.107 -} PACKED AMX_DBG_SYMDIM;
   2.108 -
   2.109 -typedef struct tagAMX_DBG_TAG {
   2.110 -  int16_t tag           PACKED; /* tag id */
   2.111 -  const char name[1]    PACKED; /* ASCII string, zero-terminated */
   2.112 -} PACKED AMX_DBG_TAG;
   2.113 -
   2.114 -typedef struct tagAMX_DBG_MACHINE {
   2.115 -  int16_t automaton     PACKED; /* automaton id */
   2.116 -  ucell address         PACKED; /* address of state variable */
   2.117 -  const char name[1]    PACKED; /* ASCII string, zero-terminated */
   2.118 -} PACKED AMX_DBG_MACHINE;
   2.119 -
   2.120 -typedef struct tagAMX_DBG_STATE {
   2.121 -  int16_t state         PACKED; /* state id */
   2.122 -  int16_t automaton     PACKED; /* automaton id */
   2.123 -  const char name[1]    PACKED; /* ASCII string, zero-terminated */
   2.124 -} PACKED AMX_DBG_STATE;
   2.125 -
   2.126 -typedef struct tagAMX_DBG {
   2.127 -  AMX_DBG_HDR     *hdr           PACKED; /* points to the AMX_DBG header */
   2.128 -  AMX_DBG_FILE    **filetbl      PACKED;
   2.129 -  AMX_DBG_LINE    *linetbl       PACKED;
   2.130 -  AMX_DBG_SYMBOL  **symboltbl    PACKED;
   2.131 -  AMX_DBG_TAG     **tagtbl       PACKED;
   2.132 -  AMX_DBG_MACHINE **automatontbl PACKED;
   2.133 -  AMX_DBG_STATE   **statetbl     PACKED;
   2.134 -} PACKED AMX_DBG;
   2.135 -
   2.136 -#if !defined iVARIABLE
   2.137 -  #define iVARIABLE  1  /* cell that has an address and that can be fetched directly (lvalue) */
   2.138 -  #define iREFERENCE 2  /* iVARIABLE, but must be dereferenced */
   2.139 -  #define iARRAY     3
   2.140 -  #define iREFARRAY  4  /* an array passed by reference (i.e. a pointer) */
   2.141 -  #define iFUNCTN    9
   2.142 -#endif
   2.143 -
   2.144 -
   2.145 -int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
   2.146 -int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, FILE *fp);
   2.147 -
   2.148 -int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
   2.149 -int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
   2.150 -int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line);
   2.151 -
   2.152 -int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address);
   2.153 -int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address);
   2.154 -int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
   2.155 -int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name);
   2.156 -int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name);
   2.157 -int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym);
   2.158 -int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
   2.159 -
   2.160 -
   2.161 -#if !defined AMX_NO_ALIGN
   2.162 -  #if defined LINUX || defined __FreeBSD__
   2.163 -    #pragma pack()    /* reset default packing */
   2.164 -  #elif defined MACOS && defined __MWERKS__
   2.165 -    #pragma options align=reset
   2.166 -  #else
   2.167 -    #pragma pack(pop) /* reset previous packing */
   2.168 -  #endif
   2.169 -#endif
   2.170 -
   2.171 -#ifdef  __cplusplus
   2.172 -}
   2.173 -#endif
   2.174 -
   2.175 -#endif /* AMXDBG_H_INCLUDED */
     3.1 --- a/compiler-init/libpawnc.c	Sat Jul 15 01:36:48 2006 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,257 +0,0 @@
     3.4 -/*	LIBPAWNC.C
     3.5 - *
     3.6 - *	A "glue file" for building the Pawn compiler as a DLL or shared library.
     3.7 - *
     3.8 - *	Copyright (c) ITB CompuPhase, 2000-2006
     3.9 - *
    3.10 - *	This software is provided "as-is", without any express or implied warranty.
    3.11 - *	In no event will the authors be held liable for any damages arising from
    3.12 - *	the use of this software.
    3.13 - *
    3.14 - *	Permission is granted to anyone to use this software for any purpose,
    3.15 - *	including commercial applications, and to alter it and redistribute it
    3.16 - *	freely, subject to the following restrictions:
    3.17 - *
    3.18 - *	1.	The origin of this software must not be misrepresented; you must not
    3.19 - *			claim that you wrote the original software. If you use this software in
    3.20 - *			a product, an acknowledgment in the product documentation would be
    3.21 - *			appreciated but is not required.
    3.22 - *	2.	Altered source versions must be plainly marked as such, and must not be
    3.23 - *			misrepresented as being the original software.
    3.24 - *	3.	This notice may not be removed or altered from any source distribution.
    3.25 - *
    3.26 - *	Version: $Id: libsc.c 3114 2005-03-17 14:48:29Z thiadmer $
    3.27 - */
    3.28 -#include <assert.h>
    3.29 -#include <stdio.h>
    3.30 -#include <stdlib.h>
    3.31 -#include <string.h>
    3.32 -#include <malloc.h>
    3.33 -#include "sc.h"
    3.34 -#include "memfile.h"
    3.35 -
    3.36 -/* pc_printf()
    3.37 - * Called for general purpose "console" output. This function prints general
    3.38 - * purpose messages; errors go through pc_error(). The function is modelled
    3.39 - * after printf().
    3.40 - */
    3.41 -int pc_printf(const char *message,...)
    3.42 -{
    3.43 -	int ret;
    3.44 -	va_list argptr;
    3.45 -
    3.46 -	va_start(argptr,message);
    3.47 -	ret=vprintf(message,argptr);
    3.48 -	va_end(argptr);
    3.49 -
    3.50 -	return ret;
    3.51 -}
    3.52 -
    3.53 -/* pc_error()
    3.54 - * Called for producing error output.
    3.55 - *		number			the error number (as documented in the manual)
    3.56 - *		message		 a string describing the error with embedded %d and %s tokens
    3.57 - *		filename		the name of the file currently being parsed
    3.58 - *		firstline	 the line number at which the expression started on which
    3.59 - *								the error was found, or -1 if there is no "starting line"
    3.60 - *		lastline		the line number at which the error was detected
    3.61 - *		argptr			a pointer to the first of a series of arguments (for macro
    3.62 - *								"va_arg")
    3.63 - * Return:
    3.64 - *		If the function returns 0, the parser attempts to continue compilation.
    3.65 - *		On a non-zero return value, the parser aborts.
    3.66 - */
    3.67 -int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr)
    3.68 -{
    3.69 -static char *prefix[3]={ "error", "fatal error", "warning" };
    3.70 -
    3.71 -	if (number!=0) {
    3.72 -		char *pre;
    3.73 -
    3.74 -		pre=prefix[number/100];
    3.75 -		if (firstline>=0)
    3.76 -			fprintf(stderr,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
    3.77 -		else
    3.78 -			fprintf(stderr,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
    3.79 -	} /* if */
    3.80 -	vfprintf(stderr,message,argptr);
    3.81 -	fflush(stderr);
    3.82 -	return 0;
    3.83 -}
    3.84 -
    3.85 -/* pc_opensrc()
    3.86 - * Opens a source file (or include file) for reading. The "file" does not have
    3.87 - * to be a physical file, one might compile from memory.
    3.88 - *		filename		the name of the "file" to read from
    3.89 - * Return:
    3.90 - *		The function must return a pointer, which is used as a "magic cookie" to
    3.91 - *		all I/O functions. When failing to open the file for reading, the
    3.92 - *		function must return NULL.
    3.93 - * Note:
    3.94 - *		Several "source files" may be open at the same time. Specifically, one
    3.95 - *		file can be open for reading and another for writing.
    3.96 - */
    3.97 -void *pc_opensrc(char *filename)
    3.98 -{
    3.99 -	return fopen(filename,"rt");
   3.100 -}
   3.101 -
   3.102 -/* pc_createsrc()
   3.103 - * Creates/overwrites a source file for writing. The "file" does not have
   3.104 - * to be a physical file, one might compile from memory.
   3.105 - *		filename		the name of the "file" to create
   3.106 - * Return:
   3.107 - *		The function must return a pointer which is used as a "magic cookie" to
   3.108 - *		all I/O functions. When failing to open the file for reading, the
   3.109 - *		function must return NULL.
   3.110 - * Note:
   3.111 - *		Several "source files" may be open at the same time. Specifically, one
   3.112 - *		file can be open for reading and another for writing.
   3.113 - */
   3.114 -void *pc_createsrc(char *filename)
   3.115 -{
   3.116 -	return fopen(filename,"wt");
   3.117 -}
   3.118 -
   3.119 -/* pc_closesrc()
   3.120 - * Closes a source file (or include file). The "handle" parameter has the
   3.121 - * value that pc_opensrc() returned in an earlier call.
   3.122 - */
   3.123 -void pc_closesrc(void *handle)
   3.124 -{
   3.125 -	assert(handle!=NULL);
   3.126 -	fclose((FILE*)handle);
   3.127 -}
   3.128 -
   3.129 -/* pc_resetsrc()
   3.130 - * "position" may only hold a pointer that was previously obtained from
   3.131 - * pc_getpossrc()
   3.132 - */
   3.133 -void pc_resetsrc(void *handle,void *position)
   3.134 -{
   3.135 -	assert(handle!=NULL);
   3.136 -	fsetpos((FILE*)handle,(fpos_t *)position);
   3.137 -}
   3.138 -
   3.139 -/* pc_readsrc()
   3.140 - * Reads a single line from the source file (or up to a maximum number of
   3.141 - * characters if the line in the input file is too long).
   3.142 - */
   3.143 -char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
   3.144 -{
   3.145 -	return fgets((char*)target,maxchars,(FILE*)handle);
   3.146 -}
   3.147 -
   3.148 -/* pc_writesrc()
   3.149 - * Writes to to the source file. There is no automatic line ending; to end a
   3.150 - * line, write a "\n".
   3.151 - */
   3.152 -int pc_writesrc(void *handle,unsigned char *source)
   3.153 -{
   3.154 -	return fputs((char*)source,(FILE*)handle) >= 0;
   3.155 -}
   3.156 -
   3.157 -void *pc_getpossrc(void *handle)
   3.158 -{
   3.159 -	static fpos_t lastpos;	/* may need to have a LIFO stack of such positions */
   3.160 -
   3.161 -	fgetpos((FILE*)handle,&lastpos);
   3.162 -	return &lastpos;
   3.163 -}
   3.164 -
   3.165 -int pc_eofsrc(void *handle)
   3.166 -{
   3.167 -	return feof((FILE*)handle);
   3.168 -}
   3.169 -
   3.170 -/* should return a pointer, which is used as a "magic cookie" to all I/O
   3.171 - * functions; return NULL for failure
   3.172 - */
   3.173 -void *pc_openasm(char *filename)
   3.174 -{
   3.175 -	#if defined __MSDOS__ || defined SC_LIGHT
   3.176 -		return fopen(filename,"w+t");
   3.177 -	#else
   3.178 -		return mfcreate(filename);
   3.179 -	#endif
   3.180 -}
   3.181 -
   3.182 -void pc_closeasm(void *handle, int deletefile)
   3.183 -{
   3.184 -	#if defined __MSDOS__ || defined SC_LIGHT
   3.185 -		if (handle!=NULL)
   3.186 -			fclose((FILE*)handle);
   3.187 -		if (deletefile)
   3.188 -			remove(outfname);
   3.189 -	#else
   3.190 -		if (handle!=NULL) {
   3.191 -			if (!deletefile)
   3.192 -				mfdump((MEMFILE*)handle);
   3.193 -			mfclose((MEMFILE*)handle);
   3.194 -		} /* if */
   3.195 -	#endif
   3.196 -}
   3.197 -
   3.198 -void pc_resetasm(void *handle)
   3.199 -{
   3.200 -	assert(handle!=NULL);
   3.201 -	#if defined __MSDOS__ || defined SC_LIGHT
   3.202 -		fflush((FILE*)handle);
   3.203 -		fseek((FILE*)handle,0,SEEK_SET);
   3.204 -	#else
   3.205 -		mfseek((MEMFILE*)handle,0,SEEK_SET);
   3.206 -	#endif
   3.207 -}
   3.208 -
   3.209 -int pc_writeasm(void *handle,char *string)
   3.210 -{
   3.211 -	#if defined __MSDOS__ || defined SC_LIGHT
   3.212 -		return fputs(string,(FILE*)handle) >= 0;
   3.213 -	#else
   3.214 -		return mfputs((MEMFILE*)handle,string);
   3.215 -	#endif
   3.216 -}
   3.217 -
   3.218 -char *pc_readasm(void *handle, char *string, int maxchars)
   3.219 -{
   3.220 -	#if defined __MSDOS__ || defined SC_LIGHT
   3.221 -		return fgets(string,maxchars,(FILE*)handle);
   3.222 -	#else
   3.223 -		return mfgets((MEMFILE*)handle,string,maxchars);
   3.224 -	#endif
   3.225 -}
   3.226 -
   3.227 -/* Should return a pointer, which is used as a "magic cookie" to all I/O
   3.228 - * functions; return NULL for failure.
   3.229 - */
   3.230 -void *pc_openbin(char *filename)
   3.231 -{
   3.232 -	return memfile_creat(filename, 1);
   3.233 -}
   3.234 -
   3.235 -void pc_closebin(void *handle,int deletefile)
   3.236 -{
   3.237 -	if (deletefile)
   3.238 -	{
   3.239 -		memfile_destroy((memfile_t *)handle);
   3.240 -	}
   3.241 -}
   3.242 -
   3.243 -/* pc_resetbin()
   3.244 - * Can seek to any location in the file.
   3.245 - * The offset is always from the start of the file.
   3.246 - */
   3.247 -void pc_resetbin(void *handle,long offset)
   3.248 -{
   3.249 -	memfile_seek((memfile_t *)handle, offset);
   3.250 -}
   3.251 -
   3.252 -int pc_writebin(void *handle,void *buffer,int size)
   3.253 -{
   3.254 -	return memfile_write((memfile_t *)handle, buffer, size);
   3.255 -}
   3.256 -
   3.257 -long pc_lengthbin(void *handle)
   3.258 -{
   3.259 -	return memfile_tell((memfile_t *)handle);
   3.260 -}
     4.1 --- a/compiler-init/libpawnc.rc	Sat Jul 15 01:36:48 2006 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,55 +0,0 @@
     4.4 -#include <windows.h>
     4.5 -#if defined WIN32 || defined _WIN32 || defined __WIN32__
     4.6 -#  include <winver.h>
     4.7 -#else
     4.8 -#  include <ver.h>
     4.9 -#endif
    4.10 -#include "svnrev.h"
    4.11 -
    4.12 -AppIcon ICON "pawn.ico"
    4.13 -
    4.14 -/*  Version information
    4.15 - *
    4.16 - *  All strings MUST have an explicit \0. See the Windows SDK documentation
    4.17 - *  for details on version information and the VERSIONINFO structure.
    4.18 - */
    4.19 -#define VERSION              SMC_VERSION
    4.20 -#define REVISION             SMC_REVISION
    4.21 -#define BUILD                SMC_BUILD
    4.22 -#define VERSIONSTR           SMC_VERSTRING
    4.23 -#define VERSIONNAME          "smcomp.exe\0"
    4.24 -#define VERSIONDESCRIPTION   "SourcePawn Compiler\0"
    4.25 -#define VERSIONPRODUCTNAME   "smcomp\0"
    4.26 -
    4.27 -VS_VERSION_INFO VERSIONINFO
    4.28 -FILEVERSION    VERSION, REVISION, BUILD, 0
    4.29 -PRODUCTVERSION VERSION, REVISION, BUILD, 0
    4.30 -FILEFLAGSMASK  0x0000003FL
    4.31 -FILEFLAGS      0
    4.32 -#if defined(WIN32)
    4.33 -  FILEOS       VOS__WINDOWS32
    4.34 -#else
    4.35 -  FILEOS       VOS__WINDOWS16
    4.36 -#endif
    4.37 -FILETYPE       VFT_DLL
    4.38 -BEGIN
    4.39 -    BLOCK "StringFileInfo"
    4.40 -    BEGIN
    4.41 -        BLOCK "040904E4"
    4.42 -        BEGIN
    4.43 -            VALUE "CompanyName",      "(C)1998-2006 ITB CompuPhase, AlliedModders LLC\0"
    4.44 -            VALUE "FileDescription",  VERSIONDESCRIPTION
    4.45 -            VALUE "FileVersion",      VERSIONSTR
    4.46 -            VALUE "InternalName",     VERSIONNAME
    4.47 -            VALUE "LegalCopyright",   "(C)1998-2006 ITB CompuPhase, AlliedModders LLC\0"
    4.48 -            VALUE "OriginalFilename", VERSIONNAME
    4.49 -            VALUE "ProductName",      VERSIONPRODUCTNAME
    4.50 -            VALUE "ProductVersion",   VERSIONSTR
    4.51 -        END
    4.52 -    END
    4.53 -
    4.54 -    BLOCK "VarFileInfo"
    4.55 -    BEGIN
    4.56 -        VALUE "Translation", 0x409, 1252
    4.57 -    END
    4.58 -END
     5.1 --- a/compiler-init/lstring.c	Sat Jul 15 01:36:48 2006 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,124 +0,0 @@
     5.4 -/* Safe string copying and concatenation
     5.5 - * These routines are originally distributed in two separate files. I have
     5.6 - * copied the files verbatim in this single source file, including all comments.
     5.7 - * The only change is that the second set of include files is commented out
     5.8 - * (there is no need to include the same files twice).
     5.9 - */
    5.10 -
    5.11 -#include "lstring.h"
    5.12 -
    5.13 -#if !defined HAVE_SAFESTR
    5.14 -
    5.15 -/*	$OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $	*/
    5.16 -
    5.17 -/*
    5.18 - * Copyright (c) 1998 Todd C. Miller <[email protected]>
    5.19 - *
    5.20 - * Permission to use, copy, modify, and distribute this software for any
    5.21 - * purpose with or without fee is hereby granted, provided that the above
    5.22 - * copyright notice and this permission notice appear in all copies.
    5.23 - *
    5.24 - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    5.25 - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    5.26 - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    5.27 - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    5.28 - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    5.29 - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    5.30 - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    5.31 - */
    5.32 -
    5.33 -/*
    5.34 -  #include <sys/types.h>  already included through lstring.h
    5.35 - */
    5.36 -#include <string.h>   /* for strlen() */
    5.37 -
    5.38 -/*
    5.39 - * Copy src to string dst of size siz.  At most siz-1 characters
    5.40 - * will be copied.  Always NUL terminates (unless siz == 0).
    5.41 - * Returns strlen(src); if retval >= siz, truncation occurred.
    5.42 - */
    5.43 -size_t
    5.44 -strlcpy(char *dst, const char *src, size_t siz)
    5.45 -{
    5.46 -	char *d = dst;
    5.47 -	const char *s = src;
    5.48 -	size_t n = siz;
    5.49 -
    5.50 -	/* Copy as many bytes as will fit */
    5.51 -	if (n != 0 && --n != 0) {
    5.52 -		do {
    5.53 -			if ((*d++ = *s++) == 0)
    5.54 -				break;
    5.55 -		} while (--n != 0);
    5.56 -	}
    5.57 -
    5.58 -	/* Not enough room in dst, add NUL and traverse rest of src */
    5.59 -	if (n == 0) {
    5.60 -		if (siz != 0)
    5.61 -			*d = '\0';		/* NUL-terminate dst */
    5.62 -		while (*s++)
    5.63 -			;
    5.64 -	}
    5.65 -
    5.66 -	return(s - src - 1);	/* count does not include NUL */
    5.67 -}
    5.68 -
    5.69 -/*	$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $	*/
    5.70 -
    5.71 -/*
    5.72 - * Copyright (c) 1998 Todd C. Miller <[email protected]>
    5.73 - *
    5.74 - * Permission to use, copy, modify, and distribute this software for any
    5.75 - * purpose with or without fee is hereby granted, provided that the above
    5.76 - * copyright notice and this permission notice appear in all copies.
    5.77 - *
    5.78 - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    5.79 - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    5.80 - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    5.81 - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    5.82 - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    5.83 - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    5.84 - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    5.85 - */
    5.86 -
    5.87 -/*
    5.88 -  #include <sys/types.h>    already included
    5.89 -  #include <string.h>       already included
    5.90 -*/
    5.91 -
    5.92 -/*
    5.93 - * Appends src to string dst of size siz (unlike strncat, siz is the
    5.94 - * full size of dst, not space left).  At most siz-1 characters
    5.95 - * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
    5.96 - * Returns strlen(src) + MIN(siz, strlen(initial dst)).
    5.97 - * If retval >= siz, truncation occurred.
    5.98 - */
    5.99 -size_t
   5.100 -strlcat(char *dst, const char *src, size_t siz)
   5.101 -{
   5.102 -	char *d = dst;
   5.103 -	const char *s = src;
   5.104 -	size_t n = siz;
   5.105 -	size_t dlen;
   5.106 -
   5.107 -	/* Find the end of dst and adjust bytes left but don't go past end */
   5.108 -	while (n-- != 0 && *d != '\0')
   5.109 -		d++;
   5.110 -	dlen = d - dst;
   5.111 -	n = siz - dlen;
   5.112 -
   5.113 -	if (n == 0)
   5.114 -		return(dlen + strlen(s));
   5.115 -	while (*s != '\0') {
   5.116 -		if (n != 1) {
   5.117 -			*d++ = *s;
   5.118 -			n--;
   5.119 -		}
   5.120 -		s++;
   5.121 -	}
   5.122 -	*d = '\0';
   5.123 -
   5.124 -	return(dlen + (s - src));	/* count does not include NUL */
   5.125 -}
   5.126 -
   5.127 -#endif /* #if !defined HAVE_SAFESTR */
     6.1 --- a/compiler-init/lstring.h	Sat Jul 15 01:36:48 2006 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,18 +0,0 @@
     6.4 -/* prototypes for strlcpy() and strlcat() */
     6.5 -
     6.6 -#include <stddef.h>
     6.7 -
     6.8 -#if defined __WATCOMC__ && __WATCOMC__ >= 1240
     6.9 -  /* OpenWatcom introduced BSD "safe string functions" with version 1.4 */
    6.10 -  #define HAVE_SAFESTR
    6.11 -#endif
    6.12 -
    6.13 -#if !defined HAVE_SAFESTR
    6.14 -
    6.15 -size_t
    6.16 -strlcpy(char *dst, const char *src, size_t siz);
    6.17 -
    6.18 -size_t
    6.19 -strlcat(char *dst, const char *src, size_t siz);
    6.20 -
    6.21 -#endif
     7.1 --- a/compiler-init/memfile.c	Sat Jul 15 01:36:48 2006 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,105 +0,0 @@
     7.4 -#include "memfile.h"
     7.5 -#include <string.h>
     7.6 -#include "osdefs.h"
     7.7 -
     7.8 -memfile_t *memfile_creat(const char *name, size_t init)
     7.9 -{
    7.10 -	memfile_t mf;
    7.11 -	memfile_t *pmf;
    7.12 -
    7.13 -	mf.size = init;
    7.14 -	mf.base = (char *)malloc(init);
    7.15 -	mf.usedoffs = 0;
    7.16 -	if (!mf.base)
    7.17 -	{
    7.18 -		return NULL;
    7.19 -	}
    7.20 -
    7.21 -	mf.offs = 0;
    7.22 -	mf._static = 0;
    7.23 -
    7.24 -	pmf = (memfile_t *)malloc(sizeof(memfile_t));
    7.25 -	memcpy(pmf, &mf, sizeof(memfile_t));
    7.26 -
    7.27 -	pmf->name = strdup(name);
    7.28 -
    7.29 -	return pmf;
    7.30 -}
    7.31 -
    7.32 -void memfile_destroy(memfile_t *mf)
    7.33 -{
    7.34 -	if (!mf->_static)
    7.35 -	{
    7.36 -		free(mf->name);
    7.37 -		free(mf->base);
    7.38 -		free(mf);
    7.39 -	}
    7.40 -}
    7.41 -
    7.42 -void memfile_seek(memfile_t *mf, long seek)
    7.43 -{
    7.44 -	mf->offs = seek;
    7.45 -}
    7.46 -
    7.47 -long memfile_tell(memfile_t *mf)
    7.48 -{
    7.49 -	return mf->offs;
    7.50 -}
    7.51 -
    7.52 -size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize)
    7.53 -{
    7.54 -	if (!maxsize || mf->offs >= mf->usedoffs)
    7.55 -	{
    7.56 -		return 0;
    7.57 -	}
    7.58 -
    7.59 -	if (mf->usedoffs - mf->offs < (long)maxsize)
    7.60 -	{
    7.61 -		maxsize = mf->usedoffs - mf->offs;
    7.62 -		if (!maxsize)
    7.63 -		{
    7.64 -			return 0;
    7.65 -		}
    7.66 -	}
    7.67 -
    7.68 -	memcpy(buffer, mf->base + mf->offs, maxsize);
    7.69 -
    7.70 -	mf->offs += maxsize;
    7.71 -
    7.72 -	return maxsize;
    7.73 -}
    7.74 -
    7.75 -int memfile_write(memfile_t *mf, void *buffer, size_t size)
    7.76 -{
    7.77 -	if (mf->offs + size > mf->size)
    7.78 -	{
    7.79 -		size_t newsize = (mf->size + size) * 2;
    7.80 -		if (mf->_static)
    7.81 -		{
    7.82 -			char *oldbase = mf->base;
    7.83 -			mf->base = (char *)malloc(newsize);
    7.84 -			if (!mf->base)
    7.85 -			{
    7.86 -				return 0;
    7.87 -			}
    7.88 -			memcpy(mf->base, oldbase, mf->size);
    7.89 -		} else {
    7.90 -			mf->base = (char *)realloc(mf->base, newsize);
    7.91 -			if (!mf->base)
    7.92 -			{
    7.93 -				return 0;
    7.94 -			}
    7.95 -		}
    7.96 -		mf->_static = 0;
    7.97 -		mf->size = newsize;
    7.98 -	}
    7.99 -	memcpy(mf->base + mf->offs, buffer, size);
   7.100 -	mf->offs += size;
   7.101 -
   7.102 -	if (mf->offs > mf->usedoffs)
   7.103 -	{
   7.104 -		mf->usedoffs = mf->offs;
   7.105 -	}
   7.106 -
   7.107 -	return 1;
   7.108 -}
     8.1 --- a/compiler-init/memfile.h	Sat Jul 15 01:36:48 2006 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,23 +0,0 @@
     8.4 -#ifndef _INCLUDE_MEMFILE_H
     8.5 -#define _INCLUDE_MEMFILE_H
     8.6 -
     8.7 -#include <malloc.h>
     8.8 -
     8.9 -typedef struct memfile_s
    8.10 -{
    8.11 -	char *name;
    8.12 -	char *base;
    8.13 -	long offs;
    8.14 -	long usedoffs;
    8.15 -	size_t size;
    8.16 -	int _static;
    8.17 -} memfile_t;
    8.18 -
    8.19 -memfile_t *memfile_creat(const char *name, size_t init);
    8.20 -void memfile_destroy(memfile_t *mf);
    8.21 -void memfile_seek(memfile_t *mf, long seek);
    8.22 -int memfile_write(memfile_t *mf, void *buffer, size_t size);
    8.23 -size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize);
    8.24 -long memfile_tell(memfile_t *mf);
    8.25 -
    8.26 -#endif //_INCLUDE_MEMFILE_H
     9.1 --- a/compiler-init/osdefs.h	Sat Jul 15 01:36:48 2006 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,108 +0,0 @@
     9.4 -/* __MSDOS__    set when compiling for DOS (not Windows)
     9.5 - * _Windows     set when compiling for any version of Microsoft Windows
     9.6 - * __WIN32__    set when compiling for Windows95 or WindowsNT (32 bit mode)
     9.7 - * __32BIT__    set when compiling in 32-bit "flat" mode (DOS or Windows)
     9.8 - *
     9.9 - * Copyright 1998-2005, ITB CompuPhase, The Netherlands.
    9.10 - * [email protected].
    9.11 - */
    9.12 -
    9.13 -#ifndef _OSDEFS_H
    9.14 -#define _OSDEFS_H
    9.15 -
    9.16 -/* Every compiler uses different "default" macros to indicate the mode
    9.17 - * it is in. Throughout the source, we use the Borland C++ macros, so
    9.18 - * the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to
    9.19 - * those of Borland C++.
    9.20 - */
    9.21 -#if defined(__WATCOMC__)
    9.22 -#  if defined(__WINDOWS__) || defined(__NT__)
    9.23 -#    define _Windows    1
    9.24 -#  endif
    9.25 -#  ifdef __386__
    9.26 -#    define __32BIT__   1
    9.27 -#  endif
    9.28 -#  if defined(_Windows) && defined(__32BIT__)
    9.29 -#    define __WIN32__   1
    9.30 -#  endif
    9.31 -#elif defined(_MSC_VER)
    9.32 -#  if defined(_WINDOWS) || defined(_WIN32)
    9.33 -#    define _Windows    1
    9.34 -#  endif
    9.35 -#  ifdef _WIN32
    9.36 -#    define __WIN32__   1
    9.37 -#    define __32BIT__   1
    9.38 -#  endif
    9.39 -#  if _MSC_VER >= 1400
    9.40 -#    if !defined _CRT_SECURE_NO_DEPRECATE
    9.41 -#      define _CRT_SECURE_NO_DEPRECATE
    9.42 -#    endif
    9.43 -#    define strdup		_strdup
    9.44 -#    define stricmp		_stricmp
    9.45 -#    define access		_access
    9.46 -#    define chdir		_chdir
    9.47 -#    define strdup		_strdup
    9.48 -#  endif
    9.49 -#endif
    9.50 -
    9.51 -#if defined __FreeBSD__
    9.52 -   #include <sys/endian.h>
    9.53 -#elif defined LINUX
    9.54 -   #include <endian.h>
    9.55 -#endif
    9.56 -
    9.57 -/* Linux NOW has these */
    9.58 -#if !defined BIG_ENDIAN
    9.59 -  #define BIG_ENDIAN    4321
    9.60 -#endif
    9.61 -#if !defined LITTLE_ENDIAN
    9.62 -  #define LITTLE_ENDIAN 1234
    9.63 -#endif
    9.64 -
    9.65 -/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */
    9.66 -#if !defined BYTE_ORDER
    9.67 -  #if defined UCLINUX
    9.68 -    #define BYTE_ORDER BIG_ENDIAN
    9.69 -  #else
    9.70 -    #define BYTE_ORDER LITTLE_ENDIAN
    9.71 -  #endif
    9.72 -#endif
    9.73 -
    9.74 -#if defined __MSDOS__ || defined __WIN32__ || defined _Windows
    9.75 -  #define DIRSEP_CHAR '\\'
    9.76 -#elif defined macintosh
    9.77 -  #define DIRSEP_CHAR ':'
    9.78 -#else
    9.79 -  #define DIRSEP_CHAR '/'   /* directory separator character */
    9.80 -#endif
    9.81 -
    9.82 -/* _MAX_PATH is sometimes called differently and it may be in limits.h or
    9.83 - * stdlib.h instead of stdio.h.
    9.84 - */
    9.85 -#if !defined _MAX_PATH
    9.86 -  /* not defined, perhaps stdio.h was not included */
    9.87 -  #if !defined PATH_MAX
    9.88 -    #include <stdio.h>
    9.89 -  #endif
    9.90 -  #if !defined _MAX_PATH && !defined PATH_MAX
    9.91 -    /* no _MAX_PATH and no MAX_PATH, perhaps it is in limits.h */
    9.92 -    #include <limits.h>
    9.93 -  #endif
    9.94 -  #if !defined _MAX_PATH && !defined PATH_MAX
    9.95 -    /* no _MAX_PATH and no MAX_PATH, perhaps it is in stdlib.h */
    9.96 -    #include <stdlib.h>
    9.97 -  #endif
    9.98 -  /* if _MAX_PATH is undefined, try common alternative names */
    9.99 -  #if !defined _MAX_PATH
   9.100 -    #if defined MAX_PATH
   9.101 -      #define _MAX_PATH    MAX_PATH
   9.102 -    #elif defined _POSIX_PATH_MAX
   9.103 -      #define _MAX_PATH  _POSIX_PATH_MAX
   9.104 -    #else
   9.105 -      /* everything failed, actually we have a problem here... */
   9.106 -      #define _MAX_PATH  1024
   9.107 -    #endif
   9.108 -  #endif
   9.109 -#endif
   9.110 -
   9.111 -#endif  /* _OSDEFS_H */
    10.1 Binary file compiler-init/pawn.ico has changed
    11.1 --- a/compiler-init/pawncc.c	Sat Jul 15 01:36:48 2006 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,30 +0,0 @@
    11.4 -/*  Pawn compiler driver
    11.5 - *
    11.6 - *  Function and variable definition and declaration, statement parser.
    11.7 - *
    11.8 - *  Copyright (c) ITB CompuPhase, 2006
    11.9 - *
   11.10 - *  This software is provided "as-is", without any express or implied warranty.
   11.11 - *  In no event will the authors be held liable for any damages arising from
   11.12 - *  the use of this software.
   11.13 - *
   11.14 - *  Permission is granted to anyone to use this software for any purpose,
   11.15 - *  including commercial applications, and to alter it and redistribute it
   11.16 - *  freely, subject to the following restrictions:
   11.17 - *
   11.18 - *  1.  The origin of this software must not be misrepresented; you must not
   11.19 - *      claim that you wrote the original software. If you use this software in
   11.20 - *      a product, an acknowledgment in the product documentation would be
   11.21 - *      appreciated but is not required.
   11.22 - *  2.  Altered source versions must be plainly marked as such, and must not be
   11.23 - *      misrepresented as being the original software.
   11.24 - *  3.  This notice may not be removed or altered from any source distribution.
   11.25 - *
   11.26 - *  Version: $Id: Sc1.c 3114 2005-03-17 14:48:29Z thiadmer $
   11.27 - */
   11.28 -#include "sc.h"
   11.29 -
   11.30 -int main(int argc, char *argv[])
   11.31 -{
   11.32 -  return pc_compile(argc,argv);
   11.33 -}
    12.1 --- a/compiler-init/sc.h	Sat Jul 15 01:36:48 2006 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,813 +0,0 @@
    12.4 -/*  Pawn compiler
    12.5 - *
    12.6 - *  Drafted after the Small-C compiler Version 2.01, originally created
    12.7 - *  by Ron Cain, july 1980, and enhanced by James E. Hendrix.
    12.8 - *
    12.9 - *  This version comes close to a complete rewrite.
   12.10 - *
   12.11 - *  Copyright R. Cain, 1980
   12.12 - *  Copyright J.E. Hendrix, 1982, 1983
   12.13 - *  Copyright ITB CompuPhase, 1997-2006
   12.14 - *
   12.15 - *  This software is provided "as-is", without any express or implied warranty.
   12.16 - *  In no event will the authors be held liable for any damages arising from
   12.17 - *  the use of this software.
   12.18 - *
   12.19 - *  Permission is granted to anyone to use this software for any purpose,
   12.20 - *  including commercial applications, and to alter it and redistribute it
   12.21 - *  freely, subject to the following restrictions:
   12.22 - *
   12.23 - *  1.  The origin of this software must not be misrepresented; you must not
   12.24 - *      claim that you wrote the original software. If you use this software in
   12.25 - *      a product, an acknowledgment in the product documentation would be
   12.26 - *      appreciated but is not required.
   12.27 - *  2.  Altered source versions must be plainly marked as such, and must not be
   12.28 - *      misrepresented as being the original software.
   12.29 - *  3.  This notice may not be removed or altered from any source distribution.
   12.30 - *
   12.31 - *  Version: $Id: sc.h 3590 2006-06-24 14:16:39Z thiadmer $
   12.32 - */
   12.33 -#ifndef SC_H_INCLUDED
   12.34 -#define SC_H_INCLUDED
   12.35 -#include <limits.h>
   12.36 -#include <stdarg.h>
   12.37 -#include <stdio.h>
   12.38 -#if defined __BORLANDC__ && defined _Windows && !(defined __32BIT__ || defined __WIN32__)
   12.39 -  /* setjmp() and longjmp() not well supported in 16-bit windows */
   12.40 -  #include <windows.h>
   12.41 -  typedef int jmp_buf[9];
   12.42 -  #define setjmp(b)     Catch(b)
   12.43 -  #define longjmp(b,e)  Throw(b,e)
   12.44 -#else
   12.45 -  #include <setjmp.h>
   12.46 -#endif
   12.47 -#include "osdefs.h"
   12.48 -#include "amx.h"
   12.49 -
   12.50 -/* Note: the "cell" and "ucell" types are defined in AMX.H */
   12.51 -
   12.52 -#define PUBLIC_CHAR '@'     /* character that defines a function "public" */
   12.53 -#define CTRL_CHAR   '\\'    /* default control character */
   12.54 -#define sCHARBITS   8       /* size of a packed character */
   12.55 -
   12.56 -#define sDIMEN_MAX     4    /* maximum number of array dimensions */
   12.57 -#define sLINEMAX     1024   /* input line length (in characters) */
   12.58 -#define sCOMP_STACK   32    /* maximum nesting of #if .. #endif sections */
   12.59 -#define sDEF_LITMAX  500    /* initial size of the literal pool, in "cells" */
   12.60 -#define sDEF_AMXSTACK 4096  /* default stack size for AMX files */
   12.61 -#define PREPROC_TERM  '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
   12.62 -#define sDEF_PREFIX   "sourcemod.inc" /* default prefix filename */
   12.63 -
   12.64 -typedef union {
   12.65 -  void *pv;                 /* e.g. a name */
   12.66 -  int i;
   12.67 -} stkitem;                  /* type of items stored on the compiler stack */
   12.68 -
   12.69 -typedef struct s_arginfo {  /* function argument info */
   12.70 -  char name[sNAMEMAX+1];
   12.71 -  char ident;           /* iVARIABLE, iREFERENCE, iREFARRAY or iVARARGS */
   12.72 -  char usage;           /* uCONST */
   12.73 -  int *tags;            /* argument tag id. list */
   12.74 -  int numtags;          /* number of tags in the tag list */
   12.75 -  int dim[sDIMEN_MAX];
   12.76 -  int idxtag[sDIMEN_MAX];
   12.77 -  int numdim;           /* number of dimensions */
   12.78 -  unsigned char hasdefault; /* bit0: is there a default value? bit6: "tagof"; bit7: "sizeof" */
   12.79 -  union {
   12.80 -    cell val;           /* default value */
   12.81 -    struct {
   12.82 -      char *symname;    /* name of another symbol */
   12.83 -      short level;      /* indirection level for that symbol */
   12.84 -    } size;             /* used for "sizeof" default value */
   12.85 -    struct {
   12.86 -      cell *data;       /* values of default array */
   12.87 -      int size;         /* complete length of default array */
   12.88 -      int arraysize;    /* size to reserve on the heap */
   12.89 -      cell addr;        /* address of the default array in the data segment */
   12.90 -    } array;
   12.91 -  } defvalue;           /* default value, or pointer to default array */
   12.92 -  int defvalue_tag;     /* tag of the default value */
   12.93 -} arginfo;
   12.94 -
   12.95 -/*  Equate table, tagname table, library table */
   12.96 -typedef struct s_constvalue {
   12.97 -  struct s_constvalue *next;
   12.98 -  char name[sNAMEMAX+1];
   12.99 -  cell value;
  12.100 -  int index;            /* index level, for constants referring to array sizes/tags
  12.101 -                         * automaton id. for states and automatons
  12.102 -                         * tag for enumeration lists */
  12.103 -} constvalue;
  12.104 -
  12.105 -/*  Symbol table format
  12.106 - *
  12.107 - *  The symbol name read from the input file is stored in "name", the
  12.108 - *  value of "addr" is written to the output file. The address in "addr"
  12.109 - *  depends on the class of the symbol:
  12.110 - *      global          offset into the data segment
  12.111 - *      local           offset relative to the stack frame
  12.112 - *      label           generated hexadecimal number
  12.113 - *      function        offset into code segment
  12.114 - */
  12.115 -typedef struct s_symbol {
  12.116 -  struct s_symbol *next;
  12.117 -  struct s_symbol *parent;  /* hierarchical types (multi-dimensional arrays) */
  12.118 -  char name[sNAMEMAX+1];
  12.119 -  uint32_t hash;        /* value derived from name, for quicker searching */
  12.120 -  cell addr;            /* address or offset (or value for constant, index for native function) */
  12.121 -  cell codeaddr;        /* address (in the code segment) where the symbol declaration starts */
  12.122 -  char vclass;          /* sLOCAL if "addr" refers to a local symbol */
  12.123 -  char ident;           /* see below for possible values */
  12.124 -  short usage;          /* see below for possible values */
  12.125 -  char flags;           /* see below for possible values */
  12.126 -  int compound;         /* compound level (braces nesting level) */
  12.127 -  int tag;              /* tagname id */
  12.128 -  union {
  12.129 -    int declared;       /* label: how many local variables are declared */
  12.130 -    struct {
  12.131 -      int index;        /* array & enum: tag of array indices or the enum item */
  12.132 -      int field;        /* enumeration fields, where a size is attached to the field */
  12.133 -    } tags;             /* extra tags */
  12.134 -    constvalue *lib;    /* native function: library it is part of */
  12.135 -    long stacksize;     /* normal/public function: stack requirements */
  12.136 -  } x;                  /* 'x' for 'extra' */
  12.137 -  union {
  12.138 -    arginfo *arglist;   /* types of all parameters for functions */
  12.139 -    constvalue *enumlist;/* list of names for the "root" of an enumeration */
  12.140 -    struct {
  12.141 -      cell length;      /* arrays: length (size) */
  12.142 -      short level;      /* number of dimensions below this level */
  12.143 -    } array;
  12.144 -  } dim;                /* for 'dimension', both functions and arrays */
  12.145 -  constvalue *states;   /* list of state function/state variable ids + addresses */
  12.146 -  int fnumber;          /* static global variables: file number in which the declaration is visible */
  12.147 -  int lnumber;          /* line number (in the current source file) for the declaration */
  12.148 -  struct s_symbol **refer;  /* referrer list, functions that "use" this symbol */
  12.149 -  int numrefers;        /* number of entries in the referrer list */
  12.150 -  char *documentation;  /* optional documentation string */
  12.151 -} symbol;
  12.152 -
  12.153 -
  12.154 -/*  Possible entries for "ident". These are used in the "symbol", "value"
  12.155 - *  and arginfo structures. Not every constant is valid for every use.
  12.156 - *  In an argument list, the list is terminated with a "zero" ident; labels
  12.157 - *  cannot be passed as function arguments, so the value 0 is overloaded.
  12.158 - */
  12.159 -#define iLABEL      0
  12.160 -#define iVARIABLE   1   /* cell that has an address and that can be fetched directly (lvalue) */
  12.161 -#define iREFERENCE  2   /* iVARIABLE, but must be dereferenced */
  12.162 -#define iARRAY      3
  12.163 -#define iREFARRAY   4   /* an array passed by reference (i.e. a pointer) */
  12.164 -#define iARRAYCELL  5   /* array element, cell that must be fetched indirectly */
  12.165 -#define iARRAYCHAR  6   /* array element, character from cell from array */
  12.166 -#define iEXPRESSION 7   /* expression result, has no address (rvalue) */
  12.167 -#define iCONSTEXPR  8   /* constant expression (or constant symbol) */
  12.168 -#define iFUNCTN     9
  12.169 -#define iREFFUNC    10
  12.170 -#define iVARARGS    11  /* function specified ... as argument(s) */
  12.171 -
  12.172 -/*  Possible entries for "usage"
  12.173 - *
  12.174 - *  This byte is used as a serie of bits, the syntax is different for
  12.175 - *  functions and other symbols:
  12.176 - *
  12.177 - *  VARIABLE
  12.178 - *  bits: 0     (uDEFINE) the variable is defined in the source file
  12.179 - *        1     (uREAD) the variable is "read" (accessed) in the source file
  12.180 - *        2     (uWRITTEN) the variable is altered (assigned a value)
  12.181 - *        3     (uCONST) the variable is constant (may not be assigned to)
  12.182 - *        4     (uPUBLIC) the variable is public
  12.183 - *        6     (uSTOCK) the variable is discardable (without warning)
  12.184 - *
  12.185 - *  FUNCTION
  12.186 - *  bits: 0     (uDEFINE) the function is defined ("implemented") in the source file
  12.187 - *        1     (uREAD) the function is invoked in the source file
  12.188 - *        2     (uRETVALUE) the function returns a value (or should return a value)
  12.189 - *        3     (uPROTOTYPED) the function was prototyped (implicitly via a definition or explicitly)
  12.190 - *        4     (uPUBLIC) the function is public
  12.191 - *        5     (uNATIVE) the function is native
  12.192 - *        6     (uSTOCK) the function is discardable (without warning)
  12.193 - *        7     (uMISSING) the function is not implemented in this source file
  12.194 - *        8     (uFORWARD) the function is explicitly forwardly declared
  12.195 - *
  12.196 - *  CONSTANT
  12.197 - *  bits: 0     (uDEFINE) the symbol is defined in the source file
  12.198 - *        1     (uREAD) the constant is "read" (accessed) in the source file
  12.199 - *        2     (uWRITTEN) redundant, but may be set for constants passed by reference
  12.200 - *        3     (uPREDEF) the constant is pre-defined and should be kept between passes
  12.201 - *        5     (uENUMROOT) the constant is the "root" of an enumeration
  12.202 - *        6     (uENUMFIELD) the constant is a field in a named enumeration
  12.203 - */
  12.204 -#define uDEFINE   0x001
  12.205 -#define uREAD     0x002
  12.206 -#define uWRITTEN  0x004
  12.207 -#define uRETVALUE 0x004 /* function returns (or should return) a value */
  12.208 -#define uCONST    0x008
  12.209 -#define uPROTOTYPED 0x008
  12.210 -#define uPREDEF   0x008 /* constant is pre-defined */
  12.211 -#define uPUBLIC   0x010
  12.212 -#define uNATIVE   0x020
  12.213 -#define uENUMROOT 0x020
  12.214 -#define uSTOCK    0x040
  12.215 -#define uENUMFIELD 0x040
  12.216 -#define uMISSING  0x080
  12.217 -#define uFORWARD  0x100
  12.218 -/* uRETNONE is not stored in the "usage" field of a symbol. It is
  12.219 - * used during parsing a function, to detect a mix of "return;" and
  12.220 - * "return value;" in a few special cases.
  12.221 - */
  12.222 -#define uRETNONE  0x10
  12.223 -
  12.224 -#define flgDEPRICATED 0x01  /* symbol is depricated (avoid use) */
  12.225 -
  12.226 -#define uTAGOF    0x40  /* set in the "hasdefault" field of the arginfo struct */
  12.227 -#define uSIZEOF   0x80  /* set in the "hasdefault" field of the arginfo struct */
  12.228 -
  12.229 -#define uMAINFUNC "main"
  12.230 -#define uENTRYFUNC "entry"
  12.231 -
  12.232 -#define sGLOBAL   0     /* global variable/constant class (no states) */
  12.233 -#define sLOCAL    1     /* local variable/constant */
  12.234 -#define sSTATIC   2     /* global life, local scope */
  12.235 -
  12.236 -#define sSTATEVAR  3    /* criterion to find variables (sSTATEVAR implies a global variable) */
  12.237 -
  12.238 -typedef struct s_value {
  12.239 -  symbol *sym;          /* symbol in symbol table, NULL for (constant) expression */
  12.240 -  cell constval;        /* value of the constant expression (if ident==iCONSTEXPR)
  12.241 -                         * also used for the size of a literal array */
  12.242 -  int tag;              /* tag (of the expression) */
  12.243 -  int cmptag;           /* for searching symbols: choose the one with the matching tag */
  12.244 -  char ident;           /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
  12.245 -                         * iEXPRESSION or iREFERENCE */
  12.246 -  char boolresult;      /* boolean result for relational operators */
  12.247 -  cell *arrayidx;       /* last used array indices, for checking self assignment */
  12.248 -} value;
  12.249 -
  12.250 -/*  "while" statement queue (also used for "for" and "do - while" loops) */
  12.251 -enum {
  12.252 -  wqBRK,        /* used to restore stack for "break" */
  12.253 -  wqCONT,       /* used to restore stack for "continue" */
  12.254 -  wqLOOP,       /* loop start label number */
  12.255 -  wqEXIT,       /* loop exit label number (jump if false) */
  12.256 -  /* --- */
  12.257 -  wqSIZE        /* "while queue" size */
  12.258 -};
  12.259 -#define wqTABSZ (24*wqSIZE)    /* 24 nested loop statements */
  12.260 -
  12.261 -enum {
  12.262 -  statIDLE,     /* not compiling yet */
  12.263 -  statFIRST,    /* first pass */
  12.264 -  statWRITE,    /* writing output */
  12.265 -  statSKIP,     /* skipping output */
  12.266 -};
  12.267 -
  12.268 -typedef struct s_stringlist {
  12.269 -  struct s_stringlist *next;
  12.270 -  char *line;
  12.271 -} stringlist;
  12.272 -
  12.273 -typedef struct s_stringpair {
  12.274 -  struct s_stringpair *next;
  12.275 -  char *first;
  12.276 -  char *second;
  12.277 -  int matchlength;
  12.278 -} stringpair;
  12.279 -
  12.280 -/* macros for code generation */
  12.281 -#define opcodes(n)      ((n)*sizeof(cell))      /* opcode size */
  12.282 -#define opargs(n)       ((n)*sizeof(cell))      /* size of typical argument */
  12.283 -
  12.284 -/*  Tokens recognized by lex()
  12.285 - *  Some of these constants are assigned as well to the variable "lastst"
  12.286 - */
  12.287 -#define tFIRST   256    /* value of first multi-character operator */
  12.288 -#define tMIDDLE  280    /* value of last multi-character operator */
  12.289 -#define tLAST    326    /* value of last multi-character match-able token */
  12.290 -/* multi-character operators */
  12.291 -#define taMULT   256    /* *= */
  12.292 -#define taDIV    257    /* /= */
  12.293 -#define taMOD    258    /* %= */
  12.294 -#define taADD    259    /* += */
  12.295 -#define taSUB    260    /* -= */
  12.296 -#define taSHL    261    /* <<= */
  12.297 -#define taSHRU   262    /* >>>= */
  12.298 -#define taSHR    263    /* >>= */
  12.299 -#define taAND    264    /* &= */
  12.300 -#define taXOR    265    /* ^= */
  12.301 -#define taOR     266    /* |= */
  12.302 -#define tlOR     267    /* || */
  12.303 -#define tlAND    268    /* && */
  12.304 -#define tlEQ     269    /* == */
  12.305 -#define tlNE     270    /* != */
  12.306 -#define tlLE     271    /* <= */
  12.307 -#define tlGE     272    /* >= */
  12.308 -#define tSHL     273    /* << */
  12.309 -#define tSHRU    274    /* >>> */
  12.310 -#define tSHR     275    /* >> */
  12.311 -#define tINC     276    /* ++ */
  12.312 -#define tDEC     277    /* -- */
  12.313 -#define tELLIPS  278    /* ... */
  12.314 -#define tDBLDOT  279    /* .. */
  12.315 -#define tDBLCOLON 280   /* :: */
  12.316 -/* reserved words (statements) */
  12.317 -#define tASSERT  281
  12.318 -#define tBREAK   282
  12.319 -#define tCASE    283
  12.320 -#define tCHAR    284
  12.321 -#define tCONST   285
  12.322 -#define tCONTINUE 286
  12.323 -#define tDEFAULT 287
  12.324 -#define tDEFINED 288
  12.325 -#define tDO      289
  12.326 -#define tELSE    290
  12.327 -#define tENUM    291
  12.328 -#define tEXIT    292
  12.329 -#define tFOR     293
  12.330 -#define tFORWARD 294
  12.331 -#define tGOTO    295
  12.332 -#define tIF      296
  12.333 -#define tNATIVE  297
  12.334 -#define tNEW     298
  12.335 -#define tDECL    299
  12.336 -#define tOPERATOR 300
  12.337 -#define tPUBLIC  301
  12.338 -#define tRETURN  302
  12.339 -#define tSIZEOF  303
  12.340 -#define tSLEEP   304
  12.341 -#define tSTATE   305
  12.342 -#define tSTATIC  306
  12.343 -#define tSTOCK   307
  12.344 -#define tSWITCH  308
  12.345 -#define tTAGOF   309
  12.346 -#define tWHILE   310
  12.347 -/* compiler directives */
  12.348 -#define tpASSERT 311    /* #assert */
  12.349 -#define tpDEFINE 312
  12.350 -#define tpELSE   313    /* #else */
  12.351 -#define tpELSEIF 314    /* #elseif */
  12.352 -#define tpEMIT   315
  12.353 -#define tpENDIF  316
  12.354 -#define tpENDINPUT 317
  12.355 -#define tpENDSCRPT 318
  12.356 -#define tpERROR  319
  12.357 -#define tpFILE   320
  12.358 -#define tpIF     321    /* #if */
  12.359 -#define tINCLUDE 322
  12.360 -#define tpLINE   323
  12.361 -#define tpPRAGMA 324
  12.362 -#define tpTRYINCLUDE 325
  12.363 -#define tpUNDEF  326
  12.364 -/* semicolon is a special case, because it can be optional */
  12.365 -#define tTERM    327    /* semicolon or newline */
  12.366 -#define tENDEXPR 328    /* forced end of expression */
  12.367 -/* other recognized tokens */
  12.368 -#define tNUMBER  329    /* integer number */
  12.369 -#define tRATIONAL 330   /* rational number */
  12.370 -#define tSYMBOL  331
  12.371 -#define tLABEL   332
  12.372 -#define tSTRING  333
  12.373 -#define tEXPR    334    /* for assigment to "lastst" only */
  12.374 -
  12.375 -/* (reversed) evaluation of staging buffer */
  12.376 -#define sSTARTREORDER 0x01
  12.377 -#define sENDREORDER   0x02
  12.378 -#define sEXPRSTART    0x80      /* top bit set, rest is free */
  12.379 -#define sMAXARGS      127       /* relates to the bit pattern of sEXPRSTART */
  12.380 -
  12.381 -#define sDOCSEP       0x01      /* to separate documentation comments between functions */
  12.382 -
  12.383 -/* codes for ffabort() */
  12.384 -#define xEXIT           1       /* exit code in PRI */
  12.385 -#define xASSERTION      2       /* abort caused by failing assertion */
  12.386 -#define xSTACKERROR     3       /* stack/heap overflow */
  12.387 -#define xBOUNDSERROR    4       /* array index out of bounds */
  12.388 -#define xMEMACCESS      5       /* data access error */
  12.389 -#define xINVINSTR       6       /* invalid instruction */
  12.390 -#define xSTACKUNDERFLOW 7       /* stack underflow */
  12.391 -#define xHEAPUNDERFLOW  8       /* heap underflow */
  12.392 -#define xCALLBACKERR    9       /* no, or invalid, callback */
  12.393 -#define xSLEEP         12       /* sleep, exit code in PRI, tag in ALT */
  12.394 -
  12.395 -/* Miscellaneous  */
  12.396 -#if !defined TRUE
  12.397 -  #define FALSE         0
  12.398 -  #define TRUE          1
  12.399 -#endif
  12.400 -#define sIN_CSEG        1       /* if parsing CODE */
  12.401 -#define sIN_DSEG        2       /* if parsing DATA */
  12.402 -#define sCHKBOUNDS      1       /* bit position in "debug" variable: check bounds */
  12.403 -#define sSYMBOLIC       2       /* bit position in "debug" variable: symbolic info */
  12.404 -#define sRESET          0       /* reset error flag */
  12.405 -#define sFORCESET       1       /* force error flag on */
  12.406 -#define sEXPRMARK       2       /* mark start of expression */
  12.407 -#define sEXPRRELEASE    3       /* mark end of expression */
  12.408 -#define sSETPOS         4       /* set line number for the error */
  12.409 -
  12.410 -enum {
  12.411 -  sOPTIMIZE_NONE,               /* no optimization */
  12.412 -  sOPTIMIZE_NOMACRO,            /* no macro instructions */
  12.413 -  sOPTIMIZE_DEFAULT,            /* full optimization */
  12.414 -  /* ----- */
  12.415 -  sOPTIMIZE_NUMBER
  12.416 -};
  12.417 -
  12.418 -typedef enum s_regid {
  12.419 -  sPRI,                         /* indicates the primary register */
  12.420 -  sALT,                         /* indicates the secundary register */
  12.421 -} regid;
  12.422 -
  12.423 -typedef enum s_optmark {
  12.424 -  sEXPR,                        /* end of expression (for expressions that form a statement) */
  12.425 -  sPARM,                        /* end of parameter (in a function parameter list) */
  12.426 -  sLDECL,                       /* start of local declaration (variable) */
  12.427 -} optmark;
  12.428 -
  12.429 -#define suSLEEP_INSTR 0x01      /* the "sleep" instruction was used */
  12.430 -
  12.431 -#if INT_MAX<0x8000u
  12.432 -  #define PUBLICTAG   0x8000u
  12.433 -  #define FIXEDTAG    0x4000u
  12.434 -#else
  12.435 -  #define PUBLICTAG   0x80000000Lu
  12.436 -  #define FIXEDTAG    0x40000000Lu
  12.437 -#endif
  12.438 -#define TAGMASK       (~PUBLICTAG)
  12.439 -#define CELL_MAX      (((ucell)1 << (sizeof(cell)*8-1)) - 1)
  12.440 -
  12.441 -
  12.442 -/* interface functions */
  12.443 -#if defined __cplusplus
  12.444 -  extern "C" {
  12.445 -#endif
  12.446 -
  12.447 -/*
  12.448 - * Functions you call from the "driver" program
  12.449 - */
  12.450 -int pc_compile(int argc, char **argv);
  12.451 -int pc_addconstant(char *name,cell value,int tag);
  12.452 -int pc_addtag(char *name);
  12.453 -int pc_enablewarning(int number,int enable);
  12.454 -
  12.455 -/*
  12.456 - * Functions called from the compiler (to be implemented by you)
  12.457 - */
  12.458 -
  12.459 -/* general console output */
  12.460 -int pc_printf(const char *message,...);
  12.461 -
  12.462 -/* error report function */
  12.463 -int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr);
  12.464 -
  12.465 -/* input from source file */
  12.466 -void *pc_opensrc(char *filename); /* reading only */
  12.467 -void *pc_createsrc(char *filename);
  12.468 -void pc_closesrc(void *handle);   /* never delete */
  12.469 -void pc_resetsrc(void *handle,void *position);  /* reset to a position marked earlier */
  12.470 -char *pc_readsrc(void *handle,unsigned char *target,int maxchars);
  12.471 -int pc_writesrc(void *handle,unsigned char *source);
  12.472 -void *pc_getpossrc(void *handle); /* mark the current position */
  12.473 -int  pc_eofsrc(void *handle);
  12.474 -
  12.475 -/* output to intermediate (.ASM) file */
  12.476 -void *pc_openasm(char *filename); /* read/write */
  12.477 -void pc_closeasm(void *handle,int deletefile);
  12.478 -void pc_resetasm(void *handle);
  12.479 -int  pc_writeasm(void *handle,char *str);
  12.480 -char *pc_readasm(void *handle,char *target,int maxchars);
  12.481 -
  12.482 -/* output to binary (.AMX) file */
  12.483 -void *pc_openbin(char *filename);
  12.484 -void pc_closebin(void *handle,int deletefile);
  12.485 -void pc_resetbin(void *handle,long offset);
  12.486 -int  pc_writebin(void *handle,void *buffer,int size);
  12.487 -long pc_lengthbin(void *handle); /* return the length of the file */
  12.488 -
  12.489 -#if defined __cplusplus
  12.490 -  }
  12.491 -#endif
  12.492 -
  12.493 -
  12.494 -/* by default, functions and variables used in throughout the compiler
  12.495 - * files are "external"
  12.496 - */
  12.497 -#if !defined SC_FUNC
  12.498 -  #define SC_FUNC
  12.499 -#endif
  12.500 -#if !defined SC_VDECL
  12.501 -  #define SC_VDECL  extern
  12.502 -#endif
  12.503 -#if !defined SC_VDEFINE
  12.504 -  #define SC_VDEFINE
  12.505 -#endif
  12.506 -
  12.507 -/* function prototypes in SC1.C */
  12.508 -SC_FUNC void set_extension(char *filename,char *extension,int force);
  12.509 -SC_FUNC symbol *fetchfunc(char *name,int tag);
  12.510 -SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag);
  12.511 -SC_FUNC char *funcdisplayname(char *dest,char *funcname);
  12.512 -SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr);
  12.513 -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
  12.514 -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index);
  12.515 -SC_FUNC void delete_consttable(constvalue *table);
  12.516 -SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
  12.517 -SC_FUNC void exporttag(int tag);
  12.518 -SC_FUNC void sc_attachdocumentation(symbol *sym);
  12.519 -
  12.520 -/* function prototypes in SC2.C */
  12.521 -#define PUSHSTK_P(v)  { stkitem s_; s_.pv=(v); pushstk(s_); }
  12.522 -#define PUSHSTK_I(v)  { stkitem s_; s_.i=(v); pushstk(s_); }
  12.523 -#define POPSTK_P()    (popstk().pv)
  12.524 -#define POPSTK_I()    (popstk().i)
  12.525 -SC_FUNC void pushstk(stkitem val);
  12.526 -SC_FUNC stkitem popstk(void);
  12.527 -SC_FUNC void clearstk(void);
  12.528 -SC_FUNC int plungequalifiedfile(char *name);  /* explicit path included */
  12.529 -SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths);   /* search through "include" paths */
  12.530 -SC_FUNC void preprocess(void);
  12.531 -SC_FUNC void lexinit(void);
  12.532 -SC_FUNC int lex(cell *lexvalue,char **lexsym);
  12.533 -SC_FUNC void lexpush(void);
  12.534 -SC_FUNC void lexclr(int clreol);
  12.535 -SC_FUNC int matchtoken(int token);
  12.536 -SC_FUNC int tokeninfo(cell *val,char **str);
  12.537 -SC_FUNC int needtoken(int token);
  12.538 -SC_FUNC void litadd(cell value);
  12.539 -SC_FUNC void litinsert(cell value,int pos);
  12.540 -SC_FUNC int alphanum(char c);
  12.541 -SC_FUNC int ishex(char c);
  12.542 -SC_FUNC void delete_symbol(symbol *root,symbol *sym);
  12.543 -SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
  12.544 -SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
  12.545 -SC_FUNC void markusage(symbol *sym,int usage);
  12.546 -SC_FUNC uint32_t namehash(const char *name);
  12.547 -SC_FUNC symbol *findglb(const char *name,int filter);
  12.548 -SC_FUNC symbol *findloc(const char *name);
  12.549 -SC_FUNC symbol *findconst(const char *name,int *matchtag);
  12.550 -SC_FUNC symbol *finddepend(const symbol *parent);
  12.551 -SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,
  12.552 -                       int usage);
  12.553 -SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
  12.554 -                            int dim[],int numdim,int idxtag[]);
  12.555 -SC_FUNC int getlabel(void);
  12.556 -SC_FUNC char *itoh(ucell val);
  12.557 -
  12.558 -/* function prototypes in SC3.C */
  12.559 -SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
  12.560 -                         value *lval,int *resulttag);
  12.561 -SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
  12.562 -SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult);
  12.563 -SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
  12.564 -SC_FUNC cell array_totalsize(symbol *sym);
  12.565 -
  12.566 -/* function prototypes in SC4.C */
  12.567 -SC_FUNC void writeleader(symbol *root);
  12.568 -SC_FUNC void writetrailer(void);
  12.569 -SC_FUNC void begcseg(void);
  12.570 -SC_FUNC void begdseg(void);
  12.571 -SC_FUNC void setline(int chkbounds);
  12.572 -SC_FUNC void setfiledirect(char *name);
  12.573 -SC_FUNC void setlinedirect(int line);
  12.574 -SC_FUNC void setlabel(int index);
  12.575 -SC_FUNC void markexpr(optmark type,const char *name,cell offset);
  12.576 -SC_FUNC void startfunc(char *fname);
  12.577 -SC_FUNC void endfunc(void);
  12.578 -SC_FUNC void alignframe(int numbytes);
  12.579 -SC_FUNC void rvalue(value *lval);
  12.580 -SC_FUNC void address(symbol *ptr,regid reg);
  12.581 -SC_FUNC void store(value *lval);
  12.582 -SC_FUNC void loadreg(cell address,regid reg);
  12.583 -SC_FUNC void storereg(cell address,regid reg);
  12.584 -SC_FUNC void memcopy(cell size);
  12.585 -SC_FUNC void copyarray(symbol *sym,cell size);
  12.586 -SC_FUNC void fillarray(symbol *sym,cell size,cell value);
  12.587 -SC_FUNC void ldconst(cell val,regid reg);
  12.588 -SC_FUNC void moveto1(void);
  12.589 -SC_FUNC void pushreg(regid reg);
  12.590 -SC_FUNC void pushval(cell val);
  12.591 -SC_FUNC void popreg(regid reg);
  12.592 -SC_FUNC void swap1(void);
  12.593 -SC_FUNC void ffswitch(int label);
  12.594 -SC_FUNC void ffcase(cell value,char *labelname,int newtable);
  12.595 -SC_FUNC void ffcall(symbol *sym,const char *label,int numargs);
  12.596 -SC_FUNC void ffret(int remparams);
  12.597 -SC_FUNC void ffabort(int reason);
  12.598 -SC_FUNC void ffbounds(cell size);
  12.599 -SC_FUNC void jumplabel(int number);
  12.600 -SC_FUNC void defstorage(void);
  12.601 -SC_FUNC void modstk(int delta);
  12.602 -SC_FUNC void setstk(cell value);
  12.603 -SC_FUNC void modheap(int delta);
  12.604 -SC_FUNC void setheap_pri(void);
  12.605 -SC_FUNC void setheap(cell value);
  12.606 -SC_FUNC void cell2addr(void);
  12.607 -SC_FUNC void cell2addr_alt(void);
  12.608 -SC_FUNC void addr2cell(void);
  12.609 -SC_FUNC void char2addr(void);
  12.610 -SC_FUNC void charalign(void);
  12.611 -SC_FUNC void addconst(cell value);
  12.612 -
  12.613 -/*  Code generation functions for arithmetic operators.
  12.614 - *
  12.615 - *  Syntax: o[u|s|b]_name
  12.616 - *          |   |   | +--- name of operator
  12.617 - *          |   |   +----- underscore
  12.618 - *          |   +--------- "u"nsigned operator, "s"igned operator or "b"oth
  12.619 - *          +------------- "o"perator
  12.620 - */
  12.621 -SC_FUNC void os_mult(void); /* multiplication (signed) */
  12.622 -SC_FUNC void os_div(void);  /* division (signed) */
  12.623 -SC_FUNC void os_mod(void);  /* modulus (signed) */
  12.624 -SC_FUNC void ob_add(void);  /* addition */
  12.625 -SC_FUNC void ob_sub(void);  /* subtraction */
  12.626 -SC_FUNC void ob_sal(void);  /* shift left (arithmetic) */
  12.627 -SC_FUNC void os_sar(void);  /* shift right (arithmetic, signed) */
  12.628 -SC_FUNC void ou_sar(void);  /* shift right (logical, unsigned) */
  12.629 -SC_FUNC void ob_or(void);   /* bitwise or */
  12.630 -SC_FUNC void ob_xor(void);  /* bitwise xor */
  12.631 -SC_FUNC void ob_and(void);  /* bitwise and */
  12.632 -SC_FUNC void ob_eq(void);   /* equality */
  12.633 -SC_FUNC void ob_ne(void);   /* inequality */
  12.634 -SC_FUNC void relop_prefix(void);
  12.635 -SC_FUNC void relop_suffix(void);
  12.636 -SC_FUNC void os_le(void);   /* less or equal (signed) */
  12.637 -SC_FUNC void os_ge(void);   /* greater or equal (signed) */
  12.638 -SC_FUNC void os_lt(void);   /* less (signed) */
  12.639 -SC_FUNC void os_gt(void);   /* greater (signed) */
  12.640 -
  12.641 -SC_FUNC void lneg(void);
  12.642 -SC_FUNC void neg(void);
  12.643 -SC_FUNC void invert(void);
  12.644 -SC_FUNC void nooperation(void);
  12.645 -SC_FUNC void inc(value *lval);
  12.646 -SC_FUNC void dec(value *lval);
  12.647 -SC_FUNC void jmp_ne0(int number);
  12.648 -SC_FUNC void jmp_eq0(int number);
  12.649 -SC_FUNC void outval(cell val,int newline);
  12.650 -
  12.651 -/* function prototypes in SC5.C */
  12.652 -SC_FUNC int error(int number,...);
  12.653 -SC_FUNC void errorset(int code,int line);
  12.654 -
  12.655 -/* function prototypes in SC6.C */
  12.656 -SC_FUNC int assemble(FILE *fout,FILE *fin);
  12.657 -
  12.658 -/* function prototypes in SC7.C */
  12.659 -SC_FUNC void stgbuffer_cleanup(void);
  12.660 -SC_FUNC void stgmark(char mark);
  12.661 -SC_FUNC void stgwrite(const char *st);
  12.662 -SC_FUNC void stgout(int index);
  12.663 -SC_FUNC void stgdel(int index,cell code_index);
  12.664 -SC_FUNC int stgget(int *index,cell *code_index);
  12.665 -SC_FUNC void stgset(int onoff);
  12.666 -SC_FUNC int phopt_init(void);
  12.667 -SC_FUNC int phopt_cleanup(void);
  12.668 -
  12.669 -/* function prototypes in SCLIST.C */
  12.670 -SC_FUNC char* duplicatestring(const char* sourcestring);
  12.671 -SC_FUNC stringpair *insert_alias(char *name,char *alias);
  12.672 -SC_FUNC stringpair *find_alias(char *name);
  12.673 -SC_FUNC int lookup_alias(char *target,char *name);
  12.674 -SC_FUNC void delete_aliastable(void);
  12.675 -SC_FUNC stringlist *insert_path(char *path);
  12.676 -SC_FUNC char *get_path(int index);
  12.677 -SC_FUNC void delete_pathtable(void);
  12.678 -SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen);
  12.679 -SC_FUNC int get_subst(int index,char **pattern,char **substitution);
  12.680 -SC_FUNC stringpair *find_subst(char *name,int length);
  12.681 -SC_FUNC int delete_subst(char *name,int length);
  12.682 -SC_FUNC void delete_substtable(void);
  12.683 -SC_FUNC stringlist *insert_sourcefile(char *string);
  12.684 -SC_FUNC char *get_sourcefile(int index);
  12.685 -SC_FUNC void delete_sourcefiletable(void);
  12.686 -SC_FUNC stringlist *insert_docstring(char *string);
  12.687 -SC_FUNC char *get_docstring(int index);
  12.688 -SC_FUNC void delete_docstring(int index);
  12.689 -SC_FUNC void delete_docstringtable(void);
  12.690 -SC_FUNC stringlist *insert_autolist(char *string);
  12.691 -SC_FUNC char *get_autolist(int index);
  12.692 -SC_FUNC void delete_autolisttable(void);
  12.693 -SC_FUNC stringlist *insert_dbgfile(const char *filename);
  12.694 -SC_FUNC stringlist *insert_dbgline(int linenr);
  12.695 -SC_FUNC stringlist *insert_dbgsymbol(symbol *sym);
  12.696 -SC_FUNC char *get_dbgstring(int index);
  12.697 -SC_FUNC void delete_dbgstringtable(void);
  12.698 -
  12.699 -/* function prototypes in SCMEMFILE.C */
  12.700 -#if !defined tMEMFILE
  12.701 -  typedef unsigned char MEMFILE;
  12.702 -  #define tMEMFILE  1
  12.703 -#endif
  12.704 -MEMFILE *mfcreate(char *filename);
  12.705 -void mfclose(MEMFILE *mf);
  12.706 -int mfdump(MEMFILE *mf);
  12.707 -long mflength(MEMFILE *mf);
  12.708 -long mfseek(MEMFILE *mf,long offset,int whence);
  12.709 -unsigned int mfwrite(MEMFILE *mf,unsigned char *buffer,unsigned int size);
  12.710 -unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size);
  12.711 -char *mfgets(MEMFILE *mf,char *string,unsigned int size);
  12.712 -int mfputs(MEMFILE *mf,char *string);
  12.713 -
  12.714 -/* function prototypes in SCI18N.C */
  12.715 -#define MAXCODEPAGE 12
  12.716 -SC_FUNC int cp_path(const char *root,const char *directory);
  12.717 -SC_FUNC int cp_set(const char *name);
  12.718 -SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr);
  12.719 -SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
  12.720 -SC_FUNC int scan_utf8(FILE *fp,const char *filename);
  12.721 -
  12.722 -/* function prototypes in SCSTATE.C */
  12.723 -SC_FUNC constvalue *automaton_add(const char *name);
  12.724 -SC_FUNC constvalue *automaton_find(const char *name);
  12.725 -SC_FUNC constvalue *automaton_findid(int id);
  12.726 -SC_FUNC constvalue *state_add(const char *name,int fsa_id);
  12.727 -SC_FUNC constvalue *state_find(const char *name,int fsa_id);
  12.728 -SC_FUNC constvalue *state_findid(int id);
  12.729 -SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid);
  12.730 -SC_FUNC int state_addlist(int *list,int count,int fsa_id);
  12.731 -SC_FUNC void state_deletetable(void);
  12.732 -SC_FUNC int state_getfsa(int listid);
  12.733 -SC_FUNC int state_count(int listid);
  12.734 -SC_FUNC int state_inlist(int listid,int state);
  12.735 -SC_FUNC int state_listitem(int listid,int index);
  12.736 -SC_FUNC void state_conflict(symbol *root);
  12.737 -SC_FUNC int state_conflict_id(int listid1,int listid2);
  12.738 -
  12.739 -/* external variables (defined in scvars.c) */
  12.740 -#if !defined SC_SKIP_VDECL
  12.741 -SC_VDECL symbol loctab;       /* local symbol table */
  12.742 -SC_VDECL symbol glbtab;       /* global symbol table */
  12.743 -SC_VDECL cell *litq;          /* the literal queue */
  12.744 -SC_VDECL unsigned char pline[]; /* the line read from the input file */
  12.745 -SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */
  12.746 -SC_VDECL constvalue tagname_tab;/* tagname table */
  12.747 -SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */
  12.748 -SC_VDECL constvalue *curlibrary;/* current library */
  12.749 -SC_VDECL int pc_addlibtable;  /* is the library table added to the AMX file? */
  12.750 -SC_VDECL symbol *curfunc;     /* pointer to current function */
  12.751 -SC_VDECL char *inpfname;      /* name of the file currently read from */
  12.752 -SC_VDECL char outfname[];     /* intermediate (assembler) file name */
  12.753 -SC_VDECL char binfname[];     /* binary file name */
  12.754 -SC_VDECL char errfname[];     /* error file name */
  12.755 -SC_VDECL char sc_ctrlchar;    /* the control character (or escape character) */
  12.756 -SC_VDECL char sc_ctrlchar_org;/* the default control character */
  12.757 -SC_VDECL int litidx;          /* index to literal table */
  12.758 -SC_VDECL int litmax;          /* current size of the literal table */
  12.759 -SC_VDECL int stgidx;          /* index to the staging buffer */
  12.760 -SC_VDECL int sc_labnum;       /* number of (internal) labels */
  12.761 -SC_VDECL int staging;         /* true if staging output */
  12.762 -SC_VDECL cell declared;       /* number of local cells declared */
  12.763 -SC_VDECL cell glb_declared;   /* number of global cells declared */
  12.764 -SC_VDECL cell code_idx;       /* number of bytes with generated code */
  12.765 -SC_VDECL int ntv_funcid;      /* incremental number of native function */
  12.766 -SC_VDECL int errnum;          /* number of errors */
  12.767 -SC_VDECL int warnnum;         /* number of warnings */
  12.768 -SC_VDECL int sc_debug;        /* debug/optimization options (bit field) */
  12.769 -SC_VDECL int sc_packstr;      /* strings are packed by default? */
  12.770 -SC_VDECL int sc_asmfile;      /* create .ASM file? */
  12.771 -SC_VDECL int sc_listing;      /* create .LST file? */
  12.772 -SC_VDECL int sc_compress;     /* compress bytecode? */
  12.773 -SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */
  12.774 -SC_VDECL int sc_dataalign;    /* data alignment value */
  12.775 -SC_VDECL int sc_alignnext;    /* must frame of the next function be aligned? */
  12.776 -SC_VDECL int pc_docexpr;      /* must expression be attached to documentation comment? */
  12.777 -SC_VDECL int curseg;          /* 1 if currently parsing CODE, 2 if parsing DATA */
  12.778 -SC_VDECL cell pc_stksize;     /* stack size */
  12.779 -SC_VDECL cell pc_amxlimit;    /* abstract machine size limit (code + data, or only code) */
  12.780 -SC_VDECL cell pc_amxram;      /* abstract machine data size limit */
  12.781 -SC_VDECL int freading;        /* is there an input file ready for reading? */
  12.782 -SC_VDECL int fline;           /* the line number in the current file */
  12.783 -SC_VDECL short fnumber;       /* number of files in the file table (debugging) */
  12.784 -SC_VDECL short fcurrent;      /* current file being processed (debugging) */
  12.785 -SC_VDECL short sc_intest;     /* true if inside a test */
  12.786 -SC_VDECL int sideeffect;      /* true if an expression causes a side-effect */
  12.787 -SC_VDECL int stmtindent;      /* current indent of the statement */
  12.788 -SC_VDECL int indent_nowarn;   /* skip warning "217 loose indentation" */
  12.789 -SC_VDECL int sc_tabsize;      /* number of spaces that a TAB represents */
  12.790 -SC_VDECL short sc_allowtags;  /* allow/detect tagnames in lex() */
  12.791 -SC_VDECL int sc_status;       /* read/write status */
  12.792 -SC_VDECL int sc_rationaltag;  /* tag for rational numbers */
  12.793 -SC_VDECL int rational_digits; /* number of fractional digits */
  12.794 -SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */
  12.795 -SC_VDECL short sc_is_utf8;    /* is this source file in UTF-8 encoding */
  12.796 -SC_VDECL char *pc_depricate;  /* if non-NULL, mark next declaration as depricated */
  12.797 -SC_VDECL int sc_curstates;    /* ID of the current state list */
  12.798 -SC_VDECL int pc_optimize;     /* (peephole) optimization level */
  12.799 -SC_VDECL int pc_memflags;     /* special flags for the stack/heap usage */
  12.800 -
  12.801 -SC_VDECL constvalue sc_automaton_tab; /* automaton table */
  12.802 -SC_VDECL constvalue sc_state_tab;     /* state table */
  12.803 -
  12.804 -SC_VDECL FILE *inpf;          /* file read from (source or include) */
  12.805 -SC_VDECL FILE *inpf_org;      /* main source file */
  12.806 -SC_VDECL FILE *outf;          /* file written to */
  12.807 -
  12.808 -SC_VDECL jmp_buf errbuf;      /* target of longjmp() on a fatal error */
  12.809 -
  12.810 -#if !defined SC_LIGHT
  12.811 -  SC_VDECL int sc_makereport; /* generate a cross-reference report */
  12.812 -#endif
  12.813 -
  12.814 -#endif /* SC_SKIP_VDECL */
  12.815 -
  12.816 -#endif /* SC_H_INCLUDED */
    13.1 --- a/compiler-init/sc1.c	Sat Jul 15 01:36:48 2006 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,5626 +0,0 @@
    13.4 -/*  Pawn compiler
    13.5 - *
    13.6 - *  Function and variable definition and declaration, statement parser.
    13.7 - *
    13.8 - *  Copyright (c) ITB CompuPhase, 1997-2006
    13.9 - *
   13.10 - *  This software is provided "as-is", without any express or implied warranty.
   13.11 - *  In no event will the authors be held liable for any damages arising from
   13.12 - *  the use of this software.
   13.13 - *
   13.14 - *  Permission is granted to anyone to use this software for any purpose,
   13.15 - *  including commercial applications, and to alter it and redistribute it
   13.16 - *  freely, subject to the following restrictions:
   13.17 - *
   13.18 - *  1.  The origin of this software must not be misrepresented; you must not
   13.19 - *      claim that you wrote the original software. If you use this software in
   13.20 - *      a product, an acknowledgment in the product documentation would be
   13.21 - *      appreciated but is not required.
   13.22 - *  2.  Altered source versions must be plainly marked as such, and must not be
   13.23 - *      misrepresented as being the original software.
   13.24 - *  3.  This notice may not be removed or altered from any source distribution.
   13.25 - *
   13.26 - *  Version: $Id: sc1.c 3591 2006-06-25 14:30:07Z thiadmer $
   13.27 - */
   13.28 -#include <assert.h>
   13.29 -#include <ctype.h>
   13.30 -#include <limits.h>
   13.31 -#include <stdarg.h>
   13.32 -#include <stdio.h>
   13.33 -#include <stdlib.h>
   13.34 -#include <string.h>
   13.35 -
   13.36 -#if defined	__WIN32__ || defined _WIN32 || defined __MSDOS__
   13.37 -  #include <conio.h>
   13.38 -  #include <io.h>
   13.39 -#endif
   13.40 -
   13.41 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
   13.42 -  #include <sclinux.h>
   13.43 -  #include <binreloc.h> /* from BinReloc, see www.autopackage.org */
   13.44 -#endif
   13.45 -
   13.46 -#if defined FORTIFY
   13.47 -  #include <alloc/fortify.h>
   13.48 -#endif
   13.49 -
   13.50 -#if defined __BORLANDC__ || defined __WATCOMC__
   13.51 -  #include <dos.h>
   13.52 -  static unsigned total_drives; /* dummy variable */
   13.53 -  #define dos_setdrive(i)       _dos_setdrive(i,&total_drives)
   13.54 -#elif defined _MSC_VER && defined _WIN32
   13.55 -  #include <direct.h>           /* for _chdrive() */
   13.56 -  #define dos_setdrive(i)       _chdrive(i)
   13.57 -#endif
   13.58 -#if defined __BORLANDC__
   13.59 -  #include <dir.h>              /* for chdir() */
   13.60 -#elif defined __WATCOMC__
   13.61 -  #include <direct.h>           /* for chdir() */
   13.62 -#endif
   13.63 -#if defined __WIN32__ || defined _WIN32 || defined _Windows
   13.64 -  #include <windows.h>
   13.65 -#endif
   13.66 -
   13.67 -#include "lstring.h"
   13.68 -#include "sc.h"
   13.69 -#include "svnrev.h"
   13.70 -#define VERSION_STR "3.2." SVN_REVSTR
   13.71 -#define VERSION_INT 0x0302
   13.72 -
   13.73 -static void resetglobals(void);
   13.74 -static void initglobals(void);
   13.75 -static char *get_extension(char *filename);
   13.76 -static void setopt(int argc,char **argv,char *oname,char *ename,char *pname,
   13.77 -                   char *rname,char *codepage);
   13.78 -static void setconfig(char *root);
   13.79 -static void setcaption(void);
   13.80 -static void about(void);
   13.81 -static void setconstants(void);
   13.82 -static void parse(void);
   13.83 -static void dumplits(void);
   13.84 -static void dumpzero(int count);
   13.85 -static void declfuncvar(int fpublic,int fstatic,int fstock,int fconst);
   13.86 -static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,
   13.87 -                    int stock,int fconst);
   13.88 -static int declloc(int fstatic);
   13.89 -static void decl_const(int table);
   13.90 -static void decl_enum(int table);
   13.91 -static cell needsub(int *tag,constvalue **enumroot);
   13.92 -static void initials(int ident,int tag,cell *size,int dim[],int numdim,
   13.93 -                     constvalue *enumroot);
   13.94 -static cell initarray(int ident,int tag,int dim[],int numdim,int cur,
   13.95 -                      int startlit,int counteddim[],constvalue *lastdim,
   13.96 -                      constvalue *enumroot,int *errorfound);
   13.97 -static cell initvector(int ident,int tag,cell size,int fillzero,
   13.98 -                       constvalue *enumroot,int *errorfound);
   13.99 -static cell init(int ident,int *tag,int *errorfound);
  13.100 -static int getstates(const char *funcname);
  13.101 -static void attachstatelist(symbol *sym, int state_id);
  13.102 -static void funcstub(int fnative);
  13.103 -static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stock);
  13.104 -static int declargs(symbol *sym,int chkshadow);
  13.105 -static void doarg(char *name,int ident,int offset,int tags[],int numtags,
  13.106 -                  int fpublic,int fconst,int chkshadow,arginfo *arg);
  13.107 -static void make_report(symbol *root,FILE *log,char *sourcefile);
  13.108 -static void reduce_referrers(symbol *root);
  13.109 -static long max_stacksize(symbol *root,int *recursion);
  13.110 -static int testsymbols(symbol *root,int level,int testlabs,int testconst);
  13.111 -static void destructsymbols(symbol *root,int level);
  13.112 -static constvalue *find_constval_byval(constvalue *table,cell val);
  13.113 -static void statement(int *lastindent,int allow_decl);
  13.114 -static void compound(int stmt_sameline);
  13.115 -static int doexpr(int comma,int chkeffect,int allowarray,int mark_endexpr,
  13.116 -                  int *tag,symbol **symptr,int chkfuncresult);
  13.117 -static void doassert(void);
  13.118 -static void doexit(void);
  13.119 -static void test(int label,int parens,int invert);
  13.120 -static void doif(void);
  13.121 -static void dowhile(void);
  13.122 -static void dodo(void);
  13.123 -static void dofor(void);
  13.124 -static void doswitch(void);
  13.125 -static void dogoto(void);
  13.126 -static void dolabel(void);
  13.127 -static symbol *fetchlab(char *name);
  13.128 -static void doreturn(void);
  13.129 -static void dobreak(void);
  13.130 -static void docont(void);
  13.131 -static void dosleep(void);
  13.132 -static void dostate(void);
  13.133 -static void addwhile(int *ptr);
  13.134 -static void delwhile(void);
  13.135 -static int *readwhile(void);
  13.136 -
  13.137 -static int norun      = 0;      /* the compiler never ran */
  13.138 -static int autozero   = 0;      /* if 1 will zero out the variable, if 0 omit the zeroing */ 
  13.139 -static int lastst     = 0;      /* last executed statement type */
  13.140 -static int nestlevel  = 0;      /* number of active (open) compound statements */
  13.141 -static int rettype    = 0;      /* the type that a "return" expression should have */
  13.142 -static int skipinput  = 0;      /* number of lines to skip from the first input file */
  13.143 -static int optproccall = TRUE;  /* support "procedure call" */
  13.144 -static int verbosity  = 1;      /* verbosity level, 0=quiet, 1=normal, 2=verbose */
  13.145 -static int sc_reparse = 0;      /* needs 3th parse because of changed prototypes? */
  13.146 -static int sc_parsenum = 0;     /* number of the extra parses */
  13.147 -static int wq[wqTABSZ];         /* "while queue", internal stack for nested loops */
  13.148 -static int *wqptr;              /* pointer to next entry */
  13.149 -#if !defined SC_LIGHT
  13.150 -  static char sc_rootpath[_MAX_PATH];
  13.151 -  static char *sc_documentation=NULL;/* main documentation */
  13.152 -#endif
  13.153 -#if defined	__WIN32__ || defined _WIN32 || defined _Windows
  13.154 -  static HWND hwndFinish = 0;
  13.155 -#endif
  13.156 -
  13.157 -/*  "main" of the compiler
  13.158 - */
  13.159 -#if defined __cplusplus
  13.160 -  extern "C"
  13.161 -#endif
  13.162 -int pc_compile(int argc, char *argv[])
  13.163 -{
  13.164 -  int entry,i,jmpcode;
  13.165 -  int retcode;
  13.166 -  char incfname[_MAX_PATH];
  13.167 -  char reportname[_MAX_PATH];
  13.168 -  char codepage[MAXCODEPAGE+1];
  13.169 -  FILE *binf;
  13.170 -  void *inpfmark;
  13.171 -  int lcl_packstr,lcl_needsemicolon,lcl_tabsize;
  13.172 -  #if !defined SC_LIGHT
  13.173 -    int hdrsize=0;
  13.174 -  #endif
  13.175 -  char *ptr;
  13.176 -
  13.177 -  /* set global variables to their initial value */
  13.178 -  binf=NULL;
  13.179 -  initglobals();
  13.180 -  errorset(sRESET,0);
  13.181 -  errorset(sEXPRRELEASE,0);
  13.182 -  lexinit();
  13.183 -
  13.184 -  /* make sure that we clean up on a fatal error; do this before the first
  13.185 -   * call to error(). */
  13.186 -  if ((jmpcode=setjmp(errbuf))!=0)
  13.187 -    goto cleanup;
  13.188 -
  13.189 -  /* allocate memory for fixed tables */
  13.190 -  inpfname=(char*)malloc(_MAX_PATH);
  13.191 -  if (inpfname==NULL)
  13.192 -    error(103);         /* insufficient memory */
  13.193 -  litq=(cell*)malloc(litmax*sizeof(cell));
  13.194 -  if (litq==NULL)
  13.195 -    error(103);         /* insufficient memory */
  13.196 -  if (!phopt_init())
  13.197 -    error(103);         /* insufficient memory */
  13.198 -
  13.199 -  setopt(argc,argv,outfname,errfname,incfname,reportname,codepage);
  13.200 -  strcpy(binfname,outfname);
  13.201 -  ptr=get_extension(binfname);
  13.202 -  if (ptr!=NULL && stricmp(ptr,".asm")==0)
  13.203 -    set_extension(binfname,".smx",TRUE);
  13.204 -  else
  13.205 -    set_extension(binfname,".smx",FALSE);
  13.206 -  /* set output names that depend on the input name */
  13.207 -  if (sc_listing)
  13.208 -    set_extension(outfname,".lst",TRUE);
  13.209 -  else
  13.210 -    set_extension(outfname,".asm",TRUE);
  13.211 -  if (strlen(errfname)!=0)
  13.212 -    remove(errfname);   /* delete file on startup */
  13.213 -  else if (verbosity>0)
  13.214 -    setcaption();
  13.215 -  setconfig(argv[0]);   /* the path to the include and codepage files */
  13.216 -  sc_ctrlchar_org=sc_ctrlchar;
  13.217 -  lcl_packstr=sc_packstr;
  13.218 -  lcl_needsemicolon=sc_needsemicolon;
  13.219 -  lcl_tabsize=sc_tabsize;
  13.220 -  #if !defined NO_CODEPAGE
  13.221 -    if (!cp_set(codepage))      /* set codepage */
  13.222 -      error(108);               /* codepage mapping file not found */
  13.223 -  #endif
  13.224 -  /* optionally create a temporary input file that is a collection of all
  13.225 -   * input files
  13.226 -   */
  13.227 -  assert(get_sourcefile(0)!=NULL);  /* there must be at least one source file */
  13.228 -  if (get_sourcefile(1)!=NULL) {
  13.229 -    /* there are at least two or more source files */
  13.230 -    char *tname,*sname;
  13.231 -    FILE *ftmp,*fsrc;
  13.232 -    int fidx;
  13.233 -    #if defined	__WIN32__ || defined _WIN32
  13.234 -      tname=_tempnam(NULL,"pawn");
  13.235 -    #elif defined __MSDOS__ || defined _Windows
  13.236 -      tname=tempnam(NULL,"pawn");
  13.237 -    #elif defined(MACOS) && !defined(__MACH__)
  13.238 -      /* tempnam is not supported for the Macintosh CFM build. */
  13.239 -      error(104,get_sourcefile(1));
  13.240 -      tname=NULL;
  13.241 -      sname=NULL;
  13.242 -    #else
  13.243 -      tname=tempnam(NULL,"pawn");
  13.244 -    #endif
  13.245 -    ftmp=(FILE*)pc_createsrc(tname);
  13.246 -    for (fidx=0; (sname=get_sourcefile(fidx))!=NULL; fidx++) {
  13.247 -      unsigned char tstring[128];
  13.248 -      fsrc=(FILE*)pc_opensrc(sname);
  13.249 -      if (fsrc==NULL) {
  13.250 -        strcpy(inpfname,sname); /* avoid invalid filename */
  13.251 -        error(100,sname);
  13.252 -      } /* if */
  13.253 -      pc_writesrc(ftmp,(unsigned char*)"#file ");
  13.254 -      pc_writesrc(ftmp,(unsigned char*)sname);
  13.255 -      pc_writesrc(ftmp,(unsigned char*)"\n");
  13.256 -      while (!pc_eofsrc(fsrc)) {
  13.257 -        pc_readsrc(fsrc,tstring,sizeof tstring);
  13.258 -        pc_writesrc(ftmp,tstring);
  13.259 -      } /* while */
  13.260 -      pc_closesrc(fsrc);
  13.261 -    } /* for */
  13.262 -    pc_closesrc(ftmp);
  13.263 -    strcpy(inpfname,tname);
  13.264 -    free(tname);
  13.265 -  } else {
  13.266 -    strcpy(inpfname,get_sourcefile(0));
  13.267 -  } /* if */
  13.268 -  inpf_org=(FILE*)pc_opensrc(inpfname);
  13.269 -  if (inpf_org==NULL)
  13.270 -    error(100,inpfname);
  13.271 -  freading=TRUE;
  13.272 -  outf=(FILE*)pc_openasm(outfname); /* first write to assembler file (may be temporary) */
  13.273 -  if (outf==NULL)
  13.274 -    error(101,outfname);
  13.275 -  /* immediately open the binary file, for other programs to check */
  13.276 -  if (sc_asmfile || sc_listing) {
  13.277 -    binf=NULL;
  13.278 -  } else {
  13.279 -    binf=(FILE*)pc_openbin(binfname);
  13.280 -    if (binf==NULL)
  13.281 -      error(101,binfname);
  13.282 -  } /* if */
  13.283 -  setconstants();               /* set predefined constants and tagnames */
  13.284 -  for (i=0; i<skipinput; i++)   /* skip lines in the input file */
  13.285 -    if (pc_readsrc(inpf_org,pline,sLINEMAX)!=NULL)
  13.286 -      fline++;                  /* keep line number up to date */
  13.287 -  skipinput=fline;
  13.288 -  sc_status=statFIRST;
  13.289 -  /* write starting options (from the command line or the configuration file) */
  13.290 -  if (sc_listing) {
  13.291 -    char string[150];
  13.292 -    sprintf(string,"#pragma ctrlchar 0x%02x\n"
  13.293 -                   "#pragma pack %s\n"
  13.294 -                   "#pragma semicolon %s\n"
  13.295 -                   "#pragma tabsize %d\n",
  13.296 -            sc_ctrlchar,
  13.297 -            sc_packstr ? "true" : "false",
  13.298 -            sc_needsemicolon ? "true" : "false",
  13.299 -            sc_tabsize);
  13.300 -    pc_writeasm(outf,string);
  13.301 -    setfiledirect(inpfname);
  13.302 -  } /* if */
  13.303 -  /* do the first pass through the file (or possibly two or more "first passes") */
  13.304 -  sc_parsenum=0;
  13.305 -  inpfmark=pc_getpossrc(inpf_org);
  13.306 -  do {
  13.307 -    /* reset "defined" flag of all functions and global variables */
  13.308 -    reduce_referrers(&glbtab);
  13.309 -    delete_symbols(&glbtab,0,TRUE,FALSE);
  13.310 -    #if !defined NO_DEFINE
  13.311 -      delete_substtable();
  13.312 -    #endif
  13.313 -    resetglobals();
  13.314 -    sc_ctrlchar=sc_ctrlchar_org;
  13.315 -    sc_packstr=lcl_packstr;
  13.316 -    sc_needsemicolon=lcl_needsemicolon;
  13.317 -    sc_tabsize=lcl_tabsize;
  13.318 -    errorset(sRESET,0);
  13.319 -    /* reset the source file */
  13.320 -    inpf=inpf_org;
  13.321 -    freading=TRUE;
  13.322 -    pc_resetsrc(inpf,inpfmark); /* reset file position */
  13.323 -    fline=skipinput;            /* reset line number */
  13.324 -    sc_reparse=FALSE;           /* assume no extra passes */
  13.325 -    sc_status=statFIRST;        /* resetglobals() resets it to IDLE */
  13.326 -
  13.327 -    if (strlen(incfname)>0) {
  13.328 -      if (strcmp(incfname,sDEF_PREFIX)==0) {
  13.329 -        plungefile(incfname,FALSE,TRUE);    /* parse "default.inc" */
  13.330 -      } else {
  13.331 -        if (!plungequalifiedfile(incfname)) /* parse "prefix" include file */
  13.332 -          error(100,incfname);          /* cannot read from ... (fatal error) */
  13.333 -      } /* if */
  13.334 -    } /* if */
  13.335 -    preprocess();                       /* fetch first line */
  13.336 -    parse();                            /* process all input */
  13.337 -    sc_parsenum++;
  13.338 -  } while (sc_reparse);
  13.339 -
  13.340 -  /* second (or third) pass */
  13.341 -  sc_status=statWRITE;                  /* set, to enable warnings */
  13.342 -  state_conflict(&glbtab);
  13.343 -
  13.344 -  /* write a report, if requested */
  13.345 -  #if !defined SC_LIGHT
  13.346 -    if (sc_makereport) {
  13.347 -      FILE *frep=stdout;
  13.348 -      if (strlen(reportname)>0)
  13.349 -        frep=fopen(reportname,"wb");    /* avoid translation of \n to \r\n in DOS/Windows */
  13.350 -      if (frep!=NULL) {
  13.351 -        make_report(&glbtab,frep,get_sourcefile(0));
  13.352 -        if (strlen(reportname)>0)
  13.353 -          fclose(frep);
  13.354 -      } /* if */
  13.355 -      if (sc_documentation!=NULL) {
  13.356 -        free(sc_documentation);
  13.357 -        sc_documentation=NULL;
  13.358 -      } /* if */
  13.359 -    } /* if */
  13.360 -  #endif
  13.361 -  if (sc_listing)
  13.362 -    goto cleanup;
  13.363 -
  13.364 -  /* ??? for re-parsing the listing file instead of the original source
  13.365 -   * file (and doing preprocessing twice):
  13.366 -   * - close input file, close listing file
  13.367 -   * - re-open listing file for reading (inpf)
  13.368 -   * - open assembler file (outf)
  13.369 -   */
  13.370 -
  13.371 -  /* reset "defined" flag of all functions and global variables */
  13.372 -  reduce_referrers(&glbtab);
  13.373 -  delete_symbols(&glbtab,0,TRUE,FALSE);
  13.374 -  #if !defined NO_DEFINE
  13.375 -    delete_substtable();
  13.376 -  #endif
  13.377 -  resetglobals();
  13.378 -  sc_ctrlchar=sc_ctrlchar_org;
  13.379 -  sc_packstr=lcl_packstr;
  13.380 -  sc_needsemicolon=lcl_needsemicolon;
  13.381 -  sc_tabsize=lcl_tabsize;
  13.382 -  errorset(sRESET,0);
  13.383 -  /* reset the source file */
  13.384 -  inpf=inpf_org;
  13.385 -  freading=TRUE;
  13.386 -  pc_resetsrc(inpf,inpfmark);   /* reset file position */
  13.387 -  fline=skipinput;              /* reset line number */
  13.388 -  lexinit();                    /* clear internal flags of lex() */
  13.389 -  sc_status=statWRITE;          /* allow to write --this variable was reset by resetglobals() */
  13.390 -  writeleader(&glbtab);
  13.391 -  insert_dbgfile(inpfname);
  13.392 -  if (strlen(incfname)>0) {
  13.393 -    if (strcmp(incfname,sDEF_PREFIX)==0)
  13.394 -      plungefile(incfname,FALSE,TRUE);  /* parse "default.inc" (again) */
  13.395 -    else
  13.396 -      plungequalifiedfile(incfname);    /* parse implicit include file (again) */
  13.397 -  } /* if */
  13.398 -  preprocess();                         /* fetch first line */
  13.399 -  parse();                              /* process all input */
  13.400 -  /* inpf is already closed when readline() attempts to pop of a file */
  13.401 -  writetrailer();                       /* write remaining stuff */
  13.402 -
  13.403 -  entry=testsymbols(&glbtab,0,TRUE,FALSE);  /* test for unused or undefined
  13.404 -                                             * functions and variables */
  13.405 -  if (!entry)
  13.406 -    error(13);                  /* no entry point (no public functions) */
  13.407 -
  13.408 -cleanup:
  13.409 -  if (inpf!=NULL)               /* main source file is not closed, do it now */
  13.410 -    pc_closesrc(inpf);
  13.411 -  /* write the binary file (the file is already open) */
  13.412 -  if (!(sc_asmfile || sc_listing) && errnum==0 && jmpcode==0) {
  13.413 -    assert(binf!=NULL);
  13.414 -    pc_resetasm(outf);          /* flush and loop back, for reading */
  13.415 -    #if !defined SC_LIGHT
  13.416 -      hdrsize=
  13.417 -    #endif
  13.418 -    assemble(binf,outf);        /* assembler file is now input */
  13.419 -  } /* if */
  13.420 -  if (outf!=NULL) {
  13.421 -    pc_closeasm(outf,!(sc_asmfile || sc_listing));
  13.422 -    outf=NULL;
  13.423 -  } /* if */
  13.424 -  if (binf!=NULL) {
  13.425 -    pc_closebin(binf,errnum!=0);
  13.426 -    binf=NULL;
  13.427 -  } /* if */
  13.428 -
  13.429 -  #if !defined SC_LIGHT
  13.430 -    if (errnum==0 && strlen(errfname)==0) {
  13.431 -      int recursion;
  13.432 -      long stacksize=max_stacksize(&glbtab,&recursion);
  13.433 -      int flag_exceed=0;
  13.434 -      if (pc_amxlimit>0) {
  13.435 -        long totalsize=hdrsize+code_idx;
  13.436 -        if (pc_amxram==0)
  13.437 -          totalsize+=(glb_declared+pc_stksize)*sizeof(cell);
  13.438 -        if (totalsize>=pc_amxlimit)
  13.439 -          flag_exceed=1;
  13.440 -      } /* if */
  13.441 -      if (pc_amxram>0 && (glb_declared+pc_stksize)*sizeof(cell)>=(unsigned long)pc_amxram)
  13.442 -        flag_exceed=1;
  13.443 -      if (!norun && (sc_debug & sSYMBOLIC)!=0 || verbosity>=2 || stacksize+32>=(long)pc_stksize || flag_exceed) {
  13.444 -        pc_printf("Header size:       %8ld bytes\n", (long)hdrsize);
  13.445 -        pc_printf("Code size:         %8ld bytes\n", (long)code_idx);
  13.446 -        pc_printf("Data size:         %8ld bytes\n", (long)glb_declared*sizeof(cell));
  13.447 -        pc_printf("Stack/heap size:   %8ld bytes; ", (long)pc_stksize*sizeof(cell));
  13.448 -        pc_printf("estimated max. usage");
  13.449 -        if (recursion)
  13.450 -          pc_printf(" is unknown, due to recursion\n");
  13.451 -        else if ((pc_memflags & suSLEEP_INSTR)!=0)
  13.452 -          pc_printf(" is unknown, due to the \"sleep\" instruction\n");
  13.453 -        else
  13.454 -          pc_printf("=%ld cells (%ld bytes)\n",stacksize,stacksize*sizeof(cell));
  13.455 -        pc_printf("Total requirements:%8ld bytes\n", (long)hdrsize+(long)code_idx+(long)glb_declared*sizeof(cell)+(long)pc_stksize*sizeof(cell));
  13.456 -      } /* if */
  13.457 -      if (flag_exceed)
  13.458 -        error(106,pc_amxlimit+pc_amxram); /* this causes a jump back to label "cleanup" */
  13.459 -    } /* if */
  13.460 -  #endif
  13.461 -
  13.462 -  if (inpfname!=NULL) {
  13.463 -    if (get_sourcefile(1)!=NULL)
  13.464 -      remove(inpfname);         /* the "input file" was in fact a temporary file */
  13.465 -    free(inpfname);
  13.466 -  } /* if */
  13.467 -  if (litq!=NULL)
  13.468 -    free(litq);
  13.469 -  phopt_cleanup();
  13.470 -  stgbuffer_cleanup();
  13.471 -  clearstk();
  13.472 -  assert(jmpcode!=0 || loctab.next==NULL);/* on normal flow, local symbols
  13.473 -                                           * should already have been deleted */
  13.474 -  delete_symbols(&loctab,0,TRUE,TRUE);    /* delete local variables if not yet
  13.475 -                                           * done (i.e. on a fatal error) */
  13.476 -  delete_symbols(&glbtab,0,TRUE,TRUE);
  13.477 -  delete_consttable(&tagname_tab);
  13.478 -  delete_consttable(&libname_tab);
  13.479 -  delete_consttable(&sc_automaton_tab);
  13.480 -  delete_consttable(&sc_state_tab);
  13.481 -  state_deletetable();
  13.482 -  delete_aliastable();
  13.483 -  delete_pathtable();
  13.484 -  delete_sourcefiletable();
  13.485 -  delete_dbgstringtable();
  13.486 -  #if !defined NO_DEFINE
  13.487 -    delete_substtable();
  13.488 -  #endif
  13.489 -  #if !defined SC_LIGHT
  13.490 -    delete_docstringtable();
  13.491 -    if (sc_documentation!=NULL)
  13.492 -      free(sc_documentation);
  13.493 -  #endif
  13.494 -  delete_autolisttable();
  13.495 -  if (errnum!=0) {
  13.496 -    if (strlen(errfname)==0)
  13.497 -      pc_printf("\n%d Error%s.\n",errnum,(errnum>1) ? "s" : "");
  13.498 -    retcode=1;
  13.499 -  } else if (warnnum!=0){
  13.500 -    if (strlen(errfname)==0)
  13.501 -      pc_printf("\n%d Warning%s.\n",warnnum,(warnnum>1) ? "s" : "");
  13.502 -    retcode=0;          /* use "0", so that MAKE and similar tools continue */
  13.503 -  } else {
  13.504 -    retcode=jmpcode;
  13.505 -    if (retcode==0 && verbosity>=2)
  13.506 -      pc_printf("\nDone.\n");
  13.507 -  } /* if */
  13.508 -  #if defined	__WIN32__ || defined _WIN32 || defined _Windows
  13.509 -    if (IsWindow(hwndFinish))
  13.510 -      PostMessageA(hwndFinish,RegisterWindowMessageA("PawnNotify"),retcode,0L);
  13.511 -  #endif
  13.512 -  #if defined FORTIFY
  13.513 -    Fortify_ListAllMemory();
  13.514 -  #endif
  13.515 -  return retcode;
  13.516 -}
  13.517 -
  13.518 -#if defined __cplusplus
  13.519 -  extern "C"
  13.520 -#endif
  13.521 -int pc_addconstant(char *name,cell value,int tag)
  13.522 -{
  13.523 -  errorset(sFORCESET,0);        /* make sure error engine is silenced */
  13.524 -  sc_status=statIDLE;
  13.525 -  add_constant(name,value,sGLOBAL,tag);
  13.526 -  return 1;
  13.527 -}
  13.528 -
  13.529 -#if defined __cplusplus
  13.530 -  extern "C"
  13.531 -#endif
  13.532 -int pc_addtag(char *name)
  13.533 -{
  13.534 -  cell val;
  13.535 -  constvalue *ptr;
  13.536 -  int last,tag;
  13.537 -
  13.538 -  if (name==NULL) {
  13.539 -    /* no tagname was given, check for one */
  13.540 -    if (lex(&val,&name)!=tLABEL) {
  13.541 -      lexpush();
  13.542 -      return 0;         /* untagged */
  13.543 -    } /* if */
  13.544 -  } /* if */
  13.545 -
  13.546 -  assert(strchr(name,':')==NULL); /* colon should already have been stripped */
  13.547 -  last=0;
  13.548 -  ptr=tagname_tab.next;
  13.549 -  while (ptr!=NULL) {
  13.550 -    tag=(int)(ptr->value & TAGMASK);
  13.551 -    if (strcmp(name,ptr->name)==0)
  13.552 -      return tag;       /* tagname is known, return its sequence number */
  13.553 -    tag &= (int)~FIXEDTAG;
  13.554 -    if (tag>last)
  13.555 -      last=tag;
  13.556 -    ptr=ptr->next;
  13.557 -  } /* while */
  13.558 -
  13.559 -  /* tagname currently unknown, add it */
  13.560 -  tag=last+1;           /* guaranteed not to exist already */
  13.561 -  if (isupper(*name))
  13.562 -    tag |= (int)FIXEDTAG;
  13.563 -  append_constval(&tagname_tab,name,(cell)tag,0);
  13.564 -  return tag;
  13.565 -}
  13.566 -
  13.567 -static void resetglobals(void)
  13.568 -{
  13.569 -  /* reset the subset of global variables that is modified by the first pass */
  13.570 -  curfunc=NULL;         /* pointer to current function */
  13.571 -  lastst=0;             /* last executed statement type */
  13.572 -  nestlevel=0;          /* number of active (open) compound statements */
  13.573 -  rettype=0;            /* the type that a "return" expression should have */
  13.574 -  litidx=0;             /* index to literal table */
  13.575 -  stgidx=0;             /* index to the staging buffer */
  13.576 -  sc_labnum=0;          /* top value of (internal) labels */
  13.577 -  staging=0;            /* true if staging output */
  13.578 -  declared=0;           /* number of local cells declared */
  13.579 -  glb_declared=0;       /* number of global cells declared */
  13.580 -  code_idx=0;           /* number of bytes with generated code */
  13.581 -  ntv_funcid=0;         /* incremental number of native function */
  13.582 -  curseg=0;             /* 1 if currently parsing CODE, 2 if parsing DATA */
  13.583 -  freading=FALSE;       /* no input file ready yet */
  13.584 -  fline=0;              /* the line number in the current file */
  13.585 -  fnumber=0;            /* the file number in the file table (debugging) */
  13.586 -  fcurrent=0;           /* current file being processed (debugging) */
  13.587 -  sc_intest=FALSE;      /* true if inside a test */
  13.588 -  sideeffect=0;         /* true if an expression causes a side-effect */
  13.589 -  stmtindent=0;         /* current indent of the statement */
  13.590 -  indent_nowarn=FALSE;  /* do not skip warning "217 loose indentation" */
  13.591 -  sc_allowtags=TRUE;    /* allow/detect tagnames */
  13.592 -  sc_status=statIDLE;
  13.593 -  sc_allowproccall=FALSE;
  13.594 -  pc_addlibtable=TRUE;  /* by default, add a "library table" to the output file */
  13.595 -  sc_alignnext=FALSE;
  13.596 -  pc_docexpr=FALSE;
  13.597 -  pc_depricate=NULL;
  13.598 -  sc_curstates=0;
  13.599 -  pc_memflags=0;
  13.600 -}
  13.601 -
  13.602 -static void initglobals(void)
  13.603 -{
  13.604 -  resetglobals();
  13.605 -
  13.606 -  sc_asmfile=FALSE;     /* do not create .ASM file */
  13.607 -  sc_listing=FALSE;     /* do not create .LST file */
  13.608 -  skipinput=0;          /* number of lines to skip from the first input file */
  13.609 -  sc_ctrlchar=CTRL_CHAR;/* the escape character */
  13.610 -  litmax=sDEF_LITMAX;   /* current size of the literal table */
  13.611 -  errnum=0;             /* number of errors */
  13.612 -  warnnum=0;            /* number of warnings */
  13.613 -  optproccall=FALSE;    /* sourcemod: do not support "procedure call" */
  13.614 -  verbosity=1;          /* verbosity level, no copyright banner */
  13.615 -  sc_debug=sSYMBOLIC;   /* sourcemod: full debug stuff */
  13.616 -  pc_optimize=sOPTIMIZE_DEFAULT;  /* sourcemod: full optimization */
  13.617 -  sc_packstr=FALSE;     /* strings are unpacked by default */
  13.618 -  #if AMX_COMPACTMARGIN > 2
  13.619 -    sc_compress=TRUE;   /* compress output bytecodes */
  13.620 -  #else
  13.621 -    sc_compress=FALSE;
  13.622 -  #endif
  13.623 -  sc_needsemicolon=FALSE;/* semicolon required to terminate expressions? */
  13.624 -  sc_dataalign=sizeof(cell);
  13.625 -  pc_stksize=sDEF_AMXSTACK;/* default stack size */
  13.626 -  pc_amxlimit=0;        /* no limit on size of the abstract machine */
  13.627 -  pc_amxram=0;          /* no limit on data size of the abstract machine */
  13.628 -  sc_tabsize=8;         /* assume a TAB is 8 spaces */
  13.629 -  sc_rationaltag=0;     /* assume no support for rational numbers */
  13.630 -  rational_digits=0;    /* number of fractional digits */
  13.631 -
  13.632 -  outfname[0]='\0';     /* output file name */
  13.633 -  errfname[0]='\0';     /* error file name */
  13.634 -  inpf=NULL;            /* file read from */
  13.635 -  inpfname=NULL;        /* pointer to name of the file currently read from */
  13.636 -  outf=NULL;            /* file written to */
  13.637 -  litq=NULL;            /* the literal queue */
  13.638 -  glbtab.next=NULL;     /* clear global variables/constants table */
  13.639 -  loctab.next=NULL;     /*   "   local      "    /    "       "   */
  13.640 -  tagname_tab.next=NULL;/* tagname table */
  13.641 -  libname_tab.next=NULL;/* library table (#pragma library "..." syntax) */
  13.642 -
  13.643 -  pline[0]='\0';        /* the line read from the input file */
  13.644 -  lptr=NULL;            /* points to the current position in "pline" */
  13.645 -  curlibrary=NULL;      /* current library */
  13.646 -  inpf_org=NULL;        /* main source file */
  13.647 -
  13.648 -  wqptr=wq;             /* initialize while queue pointer */
  13.649 -
  13.650 -#if !defined SC_LIGHT
  13.651 -  sc_documentation=NULL;
  13.652 -  sc_makereport=FALSE;  /* do not generate a cross-reference report */
  13.653 -#endif
  13.654 -}
  13.655 -
  13.656 -static char *get_extension(char *filename)
  13.657 -{
  13.658 -  char *ptr;
  13.659 -
  13.660 -  assert(filename!=NULL);
  13.661 -  ptr=strrchr(filename,'.');
  13.662 -  if (ptr!=NULL) {
  13.663 -    /* ignore extension on a directory or at the start of the filename */
  13.664 -    if (strchr(ptr,DIRSEP_CHAR)!=NULL || ptr==filename || *(ptr-1)==DIRSEP_CHAR)
  13.665 -      ptr=NULL;
  13.666 -  } /* if */
  13.667 -  return ptr;
  13.668 -}
  13.669 -
  13.670 -/* set_extension
  13.671 - * Set the default extension, or force an extension. To erase the
  13.672 - * extension of a filename, set "extension" to an empty string.
  13.673 - */
  13.674 -SC_FUNC void set_extension(char *filename,char *extension,int force)
  13.675 -{
  13.676 -  char *ptr;
  13.677 -
  13.678 -  assert(extension!=NULL && (*extension=='\0' || *extension=='.'));
  13.679 -  assert(filename!=NULL);
  13.680 -  ptr=get_extension(filename);
  13.681 -  if (force && ptr!=NULL)
  13.682 -    *ptr='\0';          /* set zero terminator at the position of the period */
  13.683 -  if (force || ptr==NULL)
  13.684 -    strcat(filename,extension);
  13.685 -}
  13.686 -
  13.687 -static const char *option_value(const char *optptr)
  13.688 -{
  13.689 -  return (*(optptr+1)=='=' || *(optptr+1)==':') ? optptr+2 : optptr+1;
  13.690 -}
  13.691 -
  13.692 -static int toggle_option(const char *optptr, int option)
  13.693 -{
  13.694 -  switch (*option_value(optptr)) {
  13.695 -  case '\0':
  13.696 -    option=!option;
  13.697 -    break;
  13.698 -  case '-':
  13.699 -    option=FALSE;
  13.700 -    break;
  13.701 -  case '+':
  13.702 -    option=TRUE;
  13.703 -    break;
  13.704 -  default:
  13.705 -    about();
  13.706 -  } /* switch */
  13.707 -  return option;
  13.708 -}
  13.709 -
  13.710 -/* Parsing command line options is indirectly recursive: parseoptions()
  13.711 - * calls parserespf() to handle options in a a response file and
  13.712 - * parserespf() calls parseoptions() at its turn after having created
  13.713 - * an "option list" from the contents of the file.
  13.714 - */
  13.715 -static void parserespf(char *filename,char *oname,char *ename,char *pname,
  13.716 -                       char *rname, char *codepage);
  13.717 -
  13.718 -static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pname,
  13.719 -                         char *rname, char *codepage)
  13.720 -{
  13.721 -  char str[_MAX_PATH],*name;
  13.722 -  const char *ptr;
  13.723 -  int arg,i,isoption;
  13.724 -
  13.725 -  for (arg=1; arg<argc; arg++) {
  13.726 -    #if DIRSEP_CHAR=='/'
  13.727 -      isoption= argv[arg][0]=='-';
  13.728 -    #else
  13.729 -      isoption= argv[arg][0]=='/' || argv[arg][0]=='-';
  13.730 -    #endif
  13.731 -    if (isoption) {
  13.732 -      ptr=&argv[arg][1];
  13.733 -      switch (*ptr) {
  13.734 -      case 'A':
  13.735 -        i=atoi(option_value(ptr));
  13.736 -        if ((i % sizeof(cell))==0)
  13.737 -          sc_dataalign=i;
  13.738 -        else
  13.739 -          about();
  13.740 -        break;
  13.741 -      case 'a':
  13.742 -        if (*(ptr+1)!='\0')
  13.743 -          about();
  13.744 -        sc_asmfile=TRUE;        /* skip last pass of making binary file */
  13.745 -        if (verbosity>1)
  13.746 -          verbosity=1;
  13.747 -        break;
  13.748 -      case 'C':
  13.749 -        #if AMX_COMPACTMARGIN > 2
  13.750 -          sc_compress=toggle_option(ptr,sc_compress);
  13.751 -        #else
  13.752 -          about();
  13.753 -        #endif
  13.754 -        break;
  13.755 -      case 'c':
  13.756 -        strlcpy(codepage,option_value(ptr),MAXCODEPAGE);  /* set name of codepage */
  13.757 -        break;
  13.758 -#if defined dos_setdrive
  13.759 -      case 'D':                 /* set active directory */
  13.760 -        ptr=option_value(ptr);
  13.761 -        if (ptr[1]==':')
  13.762 -          dos_setdrive(toupper(*ptr)-'A'+1);    /* set active drive */
  13.763 -        chdir(ptr);
  13.764 -        break;
  13.765 -#endif
  13.766 -#if 0 /* not allowed to change for SourceMod */
  13.767 -      case 'd':
  13.768 -        switch (*option_value(ptr)) {
  13.769 -        case '0':
  13.770 -          sc_debug=0;
  13.771 -          break;
  13.772 -        case '1':
  13.773 -          sc_debug=sCHKBOUNDS;  /* assertions and bounds checking */
  13.774 -          break;
  13.775 -        case '2':
  13.776 -          sc_debug=sCHKBOUNDS | sSYMBOLIC;  /* also symbolic info */
  13.777 -          break;
  13.778 -        case '3':
  13.779 -          sc_debug=sCHKBOUNDS | sSYMBOLIC;
  13.780 -          pc_optimize=sOPTIMIZE_NONE;
  13.781 -          /* also avoid peephole optimization */
  13.782 -          break;
  13.783 -        default:
  13.784 -          about();
  13.785 -        } /* switch */
  13.786 -        break;
  13.787 -#endif
  13.788 -      case 'e':
  13.789 -        strlcpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */
  13.790 -        break;
  13.791 -#if defined	__WIN32__ || defined _WIN32 || defined _Windows
  13.792 -      case 'H':
  13.793 -        hwndFinish=(HWND)atoi(option_value(ptr));
  13.794 -        if (!IsWindow(hwndFinish))
  13.795 -          hwndFinish=(HWND)0;
  13.796 -        break;
  13.797 -#endif
  13.798 -      case 'i':
  13.799 -        strlcpy(str,option_value(ptr),sizeof str);  /* set name of include directory */
  13.800 -        i=strlen(str);
  13.801 -        if (i>0) {
  13.802 -          if (str[i-1]!=DIRSEP_CHAR) {
  13.803 -            str[i]=DIRSEP_CHAR;
  13.804 -            str[i+1]='\0';
  13.805 -          } /* if */
  13.806 -          insert_path(str);
  13.807 -        } /* if */
  13.808 -        break;
  13.809 -      case 'l':
  13.810 -        if (*(ptr+1)!='\0')
  13.811 -          about();
  13.812 -        sc_listing=TRUE;        /* skip second pass & code generation */
  13.813 -        break;
  13.814 -      case 'o':
  13.815 -        strlcpy(oname,option_value(ptr),_MAX_PATH); /* set name of (binary) output file */
  13.816 -        break;
  13.817 -      case 'O':
  13.818 -        pc_optimize=*option_value(ptr) - '0';
  13.819 -        if (pc_optimize<sOPTIMIZE_NONE || pc_optimize>=sOPTIMIZE_NUMBER || pc_optimize==sOPTIMIZE_NOMACRO)
  13.820 -          about();
  13.821 -        break;
  13.822 -      case 'p':
  13.823 -        strlcpy(pname,option_value(ptr),_MAX_PATH); /* set name of implicit include file */
  13.824 -        break;
  13.825 -#if !defined SC_LIGHT
  13.826 -      case 'r':
  13.827 -        strlcpy(rname,option_value(ptr),_MAX_PATH); /* set name of report file */
  13.828 -        sc_makereport=TRUE;
  13.829 -        if (strlen(rname)>0) {
  13.830 -          set_extension(rname,".xml",FALSE);
  13.831 -        } else if ((name=get_sourcefile(0))!=NULL) {
  13.832 -          assert(strlen(rname)==0);
  13.833 -          assert(strlen(name)<_MAX_PATH);
  13.834 -          if ((ptr=strrchr(name,DIRSEP_CHAR))!=NULL)
  13.835 -            ptr++;          /* strip path */
  13.836 -          else
  13.837 -            ptr=name;
  13.838 -          assert(strlen(ptr)<_MAX_PATH);
  13.839 -          strcpy(rname,ptr);
  13.840 -          set_extension(rname,".xml",TRUE);
  13.841 -        } /* if */
  13.842 -        break;
  13.843 -#endif
  13.844 -      case 'S':
  13.845 -        i=atoi(option_value(ptr));
  13.846 -        if (i>32)
  13.847 -          pc_stksize=(cell)i;   /* stack size has minimum size */
  13.848 -        else
  13.849 -          about();
  13.850 -        break;
  13.851 -      case 's':
  13.852 -        skipinput=atoi(option_value(ptr));
  13.853 -        break;
  13.854 -      case 't':
  13.855 -        sc_tabsize=atoi(option_value(ptr));
  13.856 -        break;
  13.857 -      case 'v':
  13.858 -        verbosity= isdigit(*option_value(ptr)) ? atoi(option_value(ptr)) : 2;
  13.859 -        if (sc_asmfile && verbosity>1)
  13.860 -          verbosity=1;
  13.861 -        break;
  13.862 -      case 'w':
  13.863 -        i=(int)strtol(option_value(ptr),(char **)&ptr,10);
  13.864 -        if (*ptr=='-')
  13.865 -          pc_enablewarning(i,0);
  13.866 -        else if (*ptr=='+')
  13.867 -          pc_enablewarning(i,1);
  13.868 -        else if (*ptr=='\0')
  13.869 -          pc_enablewarning(i,2);
  13.870 -        break;
  13.871 -      case 'X':
  13.872 -        if (*(ptr+1)=='D') {
  13.873 -          i=atoi(option_value(ptr+1));
  13.874 -          if (i>64)
  13.875 -            pc_amxram=(cell)i;  /* abstract machine data/stack has minimum size */
  13.876 -          else
  13.877 -            about();
  13.878 -        } else {
  13.879 -          i=atoi(option_value(ptr));
  13.880 -          if (i>64)
  13.881 -            pc_amxlimit=(cell)i;/* abstract machine has minimum size */
  13.882 -          else
  13.883 -            about();
  13.884 -        } /* if */
  13.885 -        break;
  13.886 -      case '\\':                /* use \ instead for escape characters */
  13.887 -        sc_ctrlchar='\\';
  13.888 -        break;
  13.889 -      case '^':                 /* use ^ instead for escape characters */
  13.890 -        sc_ctrlchar='^';
  13.891 -        break;
  13.892 -      case ';':
  13.893 -        sc_needsemicolon=toggle_option(ptr,sc_needsemicolon);
  13.894 -        break;
  13.895 -#if 0 /* not allowed to change in SourceMod */
  13.896 -      case '(':
  13.897 -        optproccall=!toggle_option(ptr,!optproccall);
  13.898 -        break;
  13.899 -#endif
  13.900 -      default:                  /* wrong option */
  13.901 -        about();
  13.902 -      } /* switch */
  13.903 -    } else if (argv[arg][0]=='@') {
  13.904 -      #if !defined SC_LIGHT
  13.905 -        parserespf(&argv[arg][1],oname,ename,pname,rname,codepage);
  13.906 -      #endif
  13.907 -    } else if ((ptr=strchr(argv[arg],'='))!=NULL) {
  13.908 -      i=(int)(ptr-argv[arg]);
  13.909 -      if (i>sNAMEMAX) {
  13.910 -        i=sNAMEMAX;
  13.911 -        error(200,argv[arg],sNAMEMAX);  /* symbol too long, truncated to sNAMEMAX chars */
  13.912 -      } /* if */
  13.913 -      strlcpy(str,argv[arg],i+1);       /* str holds symbol name */
  13.914 -      i=atoi(ptr+1);
  13.915 -      add_constant(str,i,sGLOBAL,0);
  13.916 -    } else {
  13.917 -      strlcpy(str,argv[arg],sizeof(str)-5); /* -5 because default extension is ".psrc" */
  13.918 -      set_extension(str,".psrc",FALSE);
  13.919 -      insert_sourcefile(str);
  13.920 -      /* The output name is the first input name with a different extension,
  13.921 -       * but it is stored in a different directory
  13.922 -       */
  13.923 -      if (strlen(oname)==0) {
  13.924 -        if ((ptr=strrchr(str,DIRSEP_CHAR))!=NULL)
  13.925 -          ptr++;          /* strip path */
  13.926 -        else
  13.927 -          ptr=str;
  13.928 -        assert(strlen(ptr)<_MAX_PATH);
  13.929 -        strcpy(oname,ptr);
  13.930 -      } /* if */
  13.931 -      set_extension(oname,".asm",TRUE);
  13.932 -#if !defined SC_LIGHT
  13.933 -      if (sc_makereport && strlen(rname)==0) {
  13.934 -        if ((ptr=strrchr(str,DIRSEP_CHAR))!=NULL)
  13.935 -          ptr++;          /* strip path */
  13.936 -        else
  13.937 -          ptr=str;
  13.938 -        assert(strlen(ptr)<_MAX_PATH);
  13.939 -        strcpy(rname,ptr);
  13.940 -        set_extension(rname,".xml",TRUE);
  13.941 -      } /* if */
  13.942 -#endif
  13.943 -    } /* if */
  13.944 -  } /* for */
  13.945 -}
  13.946 -
  13.947 -#if !defined SC_LIGHT
  13.948 -static void parserespf(char *filename,char *oname,char *ename,char *pname,
  13.949 -                       char *rname,char *codepage)
  13.950 -{
  13.951 -#define MAX_OPTIONS     100
  13.952 -  FILE *fp;
  13.953 -  char *string, *ptr, **argv;
  13.954 -  int argc;
  13.955 -  long size;
  13.956 -
  13.957 -  if ((fp=fopen(filename,"r"))==NULL)
  13.958 -    error(100,filename);        /* error reading input file */
  13.959 -  /* load the complete file into memory */
  13.960 -  fseek(fp,0L,SEEK_END);
  13.961 -  size=ftell(fp);
  13.962 -  fseek(fp,0L,SEEK_SET);
  13.963 -  assert(size<INT_MAX);
  13.964 -  if ((string=(char *)malloc((int)size+1))==NULL)
  13.965 -    error(103);                 /* insufficient memory */
  13.966 -  /* fill with zeros; in MS-DOS, fread() may collapse CR/LF pairs to
  13.967 -   * a single '\n', so the string size may be smaller than the file
  13.968 -   * size. */
  13.969 -  memset(string,0,(int)size+1);
  13.970 -  fread(string,1,(int)size,fp);
  13.971 -  fclose(fp);
  13.972 -  /* allocate table for option pointers */
  13.973 -  if ((argv=(char **)malloc(MAX_OPTIONS*sizeof(char*)))==NULL)
  13.974 -    error(103);                 /* insufficient memory */
  13.975 -  /* fill the options table */
  13.976 -  ptr=strtok(string," \t\r\n");
  13.977 -  for (argc=1; argc<MAX_OPTIONS && ptr!=NULL; argc++) {
  13.978 -    /* note: the routine skips argv[0], for compatibility with main() */
  13.979 -    argv[argc]=ptr;
  13.980 -    ptr=strtok(NULL," \t\r\n");
  13.981 -  } /* for */
  13.982 -  if (ptr!=NULL)
  13.983 -    error(102,"option table");   /* table overflow */
  13.984 -  /* parse the option table */
  13.985 -  parseoptions(argc,argv,oname,ename,pname,rname,codepage);
  13.986 -  /* free allocated memory */
  13.987 -  free(argv);
  13.988 -  free(string);
  13.989 -}
  13.990 -#endif
  13.991 -
  13.992 -static void setopt(int argc,char **argv,char *oname,char *ename,char *pname,
  13.993 -                   char *rname,char *codepage)
  13.994 -{
  13.995 -  delete_sourcefiletable(); /* make sure it is empty */
  13.996 -  *oname='\0';
  13.997 -  *ename='\0';
  13.998 -  *pname='\0';
  13.999 -  *rname='\0';
 13.1000 -  *codepage='\0';
 13.1001 -  strcpy(pname,sDEF_PREFIX);
 13.1002 -
 13.1003 -  #if 0 /* needed to test with BoundsChecker for DOS (it does not pass
 13.1004 -         * through arguments) */
 13.1005 -    insert_sourcefile("test.p");
 13.1006 -    strcpy(oname,"test.asm");
 13.1007 -  #endif
 13.1008 -
 13.1009 -  #if !defined SC_LIGHT
 13.1010 -    /* first parse a "config" file with default options */
 13.1011 -    if (argv[0]!=NULL) {
 13.1012 -      char cfgfile[_MAX_PATH];
 13.1013 -      char *ext;
 13.1014 -      strcpy(cfgfile,argv[0]);
 13.1015 -      if ((ext=strrchr(cfgfile,DIRSEP_CHAR))!=NULL) {
 13.1016 -        *(ext+1)='\0';          /* strip the program filename */
 13.1017 -        strcat(cfgfile,"pawn.cfg");
 13.1018 -      } else {
 13.1019 -        strcpy(cfgfile,"pawn.cfg");
 13.1020 -      } /* if */
 13.1021 -      if (access(cfgfile,4)==0)
 13.1022 -        parserespf(cfgfile,oname,ename,pname,rname,codepage);
 13.1023 -    } /* if */
 13.1024 -  #endif
 13.1025 -  parseoptions(argc,argv,oname,ename,pname,rname,codepage);
 13.1026 -  if (get_sourcefile(0)==NULL)
 13.1027 -    about();
 13.1028 -}
 13.1029 -
 13.1030 -#if defined __BORLANDC__ || defined __WATCOMC__
 13.1031 -  #pragma argsused
 13.1032 -#endif
 13.1033 -static void setconfig(char *root)
 13.1034 -{
 13.1035 -  #if defined macintosh
 13.1036 -    insert_path(":include:");
 13.1037 -  #else
 13.1038 -    char path[_MAX_PATH];
 13.1039 -    char *ptr,*base;
 13.1040 -    int len;
 13.1041 -
 13.1042 -    /* add the default "include" directory */
 13.1043 -    #if defined __WIN32__ || defined _WIN32
 13.1044 -      GetModuleFileNameA(NULL,path,_MAX_PATH);
 13.1045 -    #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
 13.1046 -      /* see www.autopackage.org for the BinReloc module */
 13.1047 -      br_init_lib(NULL);
 13.1048 -      ptr=br_find_exe("/opt/pawn/bin/pawncc");
 13.1049 -      strlcpy(path,ptr,sizeof path);
 13.1050 -      free(ptr);
 13.1051 -    #else
 13.1052 -      if (root!=NULL)
 13.1053 -        strlcpy(path,root,sizeof path); /* path + filename (hopefully) */
 13.1054 -    #endif
 13.1055 -    #if defined __MSDOS__
 13.1056 -      /* strip the options (appended to the path + filename) */
 13.1057 -      if ((ptr=strpbrk(path," \t/"))!=NULL)
 13.1058 -        *ptr='\0';
 13.1059 -    #endif
 13.1060 -    /* terminate just behind last \ or : */
 13.1061 -    if ((ptr=strrchr(path,DIRSEP_CHAR))!=NULL || (ptr=strchr(path,':'))!=NULL) {
 13.1062 -      /* If there is no "\" or ":", the string probably does not contain the
 13.1063 -       * path; so we just don't add it to the list in that case
 13.1064 -       */
 13.1065 -      *(ptr+1)='\0';
 13.1066 -      base=ptr;
 13.1067 -      strcat(path,"include");
 13.1068 -      len=strlen(path);
 13.1069 -      path[len]=DIRSEP_CHAR;
 13.1070 -      path[len+1]='\0';
 13.1071 -      /* see if it exists */
 13.1072 -      if (access(path,0)!=0 && *base==DIRSEP_CHAR) {
 13.1073 -        /* There is no "include" directory below the directory where the compiler
 13.1074 -         * is found. This typically means that the compiler is in a "bin" sub-directory
 13.1075 -         * and the "include" is below the *parent*. So find the parent...
 13.1076 -         */
 13.1077 -        *base='\0';
 13.1078 -        if ((ptr=strrchr(path,DIRSEP_CHAR))!=NULL) {
 13.1079 -          *(ptr+1)='\0';
 13.1080 -          strcat(path,"include");
 13.1081 -          len=strlen(path);
 13.1082 -          path[len]=DIRSEP_CHAR;
 13.1083 -          path[len+1]='\0';
 13.1084 -        } else {
 13.1085 -          *base=DIRSEP_CHAR;
 13.1086 -        } /* if */
 13.1087 -      } /* if */
 13.1088 -      insert_path(path);
 13.1089 -      /* same for the codepage root */
 13.1090 -      #if !defined NO_CODEPAGE
 13.1091 -        *ptr='\0';
 13.1092 -        if (!cp_path(path,"codepage"))
 13.1093 -          error(109,path);        /* codepage path */
 13.1094 -      #endif
 13.1095 -      /* also copy the root path (for the XML documentation) */
 13.1096 -      #if !defined SC_LIGHT
 13.1097 -        *ptr='\0';
 13.1098 -        strcpy(sc_rootpath,path);
 13.1099 -      #endif
 13.1100 -    } /* if */
 13.1101 -  #endif /* macintosh */
 13.1102 -}
 13.1103 -
 13.1104 -static void setcaption(void)
 13.1105 -{
 13.1106 -  pc_printf("SourcePawn Compiler " SMC_VERSTRING "\n");
 13.1107 -  pc_printf("Copyright (c) 1997-2006, ITB CompuPhase, (C)2004-2006 AlliedModders, LLC\n\n");
 13.1108 -}
 13.1109 -
 13.1110 -static void about(void)
 13.1111 -{
 13.1112 -  if (strlen(errfname)==0) {
 13.1113 -    setcaption();
 13.1114 -    pc_printf("Usage:   pawncc <filename> [filename...] [options]\n\n");
 13.1115 -    pc_printf("Options:\n");
 13.1116 -    pc_printf("         -A<num>  alignment in bytes of the data segment and the stack\n");
 13.1117 -    pc_printf("         -a       output assembler code\n");
 13.1118 -#if AMX_COMPACTMARGIN > 2
 13.1119 -    pc_printf("         -C[+/-]  compact encoding for output file (default=%c)\n", sc_compress ? '+' : '-');
 13.1120 -#endif
 13.1121 -    pc_printf("         -c<name> codepage name or number; e.g. 1252 for Windows Latin-1\n");
 13.1122 -#if defined dos_setdrive
 13.1123 -    pc_printf("         -Dpath   active directory path\n");
 13.1124 -#endif
 13.1125 -#if 0 /* not used for SourceMod */
 13.1126 -    pc_printf("         -d<num>  debugging level (default=-d%d)\n",sc_debug);
 13.1127 -    pc_printf("             0    no symbolic information, no run-time checks\n");
 13.1128 -    pc_printf("             1    run-time checks, no symbolic information\n");
 13.1129 -    pc_printf("             2    full debug information and dynamic checking\n");
 13.1130 -    pc_printf("             3    same as -d2, but implies -O0\n");
 13.1131 -#endif
 13.1132 -    pc_printf("         -e<name> set name of error file (quiet compile)\n");
 13.1133 -#if defined	__WIN32__ || defined _WIN32 || defined _Windows
 13.1134 -    pc_printf("         -H<hwnd> window handle to send a notification message on finish\n");
 13.1135 -#endif
 13.1136 -    pc_printf("         -i<name> path for include files\n");
 13.1137 -    pc_printf("         -l       create list file (preprocess only)\n");
 13.1138 -    pc_printf("         -o<name> set base name of (P-code) output file\n");
 13.1139 -    pc_printf("         -O<num>  optimization level (default=-O%d)\n",pc_optimize);
 13.1140 -    pc_printf("             0    no optimization\n");
 13.1141 -#if 0 /* not used for SourceMod */
 13.1142 -    pc_printf("             1    JIT-compatible optimizations only\n");
 13.1143 -#endif
 13.1144 -    pc_printf("             2    full optimizations\n");
 13.1145 -    pc_printf("         -p<name> set name of \"prefix\" file\n");
 13.1146 -#if !defined SC_LIGHT
 13.1147 -    pc_printf("         -r[name] write cross reference report to console or to specified file\n");
 13.1148 -#endif
 13.1149 -    pc_printf("         -S<num>  stack/heap size in cells (default=%d)\n",(int)pc_stksize);
 13.1150 -    pc_printf("         -s<num>  skip lines from the input file\n");
 13.1151 -    pc_printf("         -t<num>  TAB indent size (in character positions, default=%d)\n",sc_tabsize);
 13.1152 -    pc_printf("         -v<num>  verbosity level; 0=quiet, 1=normal, 2=verbose (default=%d)\n",verbosity);
 13.1153 -    pc_printf("         -w<num>  disable a specific warning by its number\n");
 13.1154 -    pc_printf("         -X<num>  abstract machine size limit in bytes\n");
 13.1155 -    pc_printf("         -XD<num> abstract machine data/stack size limit in bytes\n");
 13.1156 -    pc_printf("         -\\       use '\\' for escape characters\n");
 13.1157 -    pc_printf("         -^       use '^' for escape characters\n");
 13.1158 -    pc_printf("         -;[+/-]  require a semicolon to end each statement (default=%c)\n", sc_needsemicolon ? '+' : '-');
 13.1159 -#if 0 /* not allowed in SourceMod */
 13.1160 -    pc_printf("         -([+/-]  require parantheses for function invocation (default=%c)\n", optproccall ? '-' : '+');
 13.1161 -#endif
 13.1162 -    pc_printf("         sym=val  define constant \"sym\" with value \"val\"\n");
 13.1163 -    pc_printf("         sym=     define constant \"sym\" with value 0\n");
 13.1164 -#if defined	__WIN32__ || defined _WIN32 || defined _Windows || defined __MSDOS__
 13.1165 -    pc_printf("\nOptions may start with a dash or a slash; the options \"-d0\" and \"/d0\" are\n");
 13.1166 -    pc_printf("equivalent.\n");
 13.1167 -#endif
 13.1168 -    pc_printf("\nOptions with a value may optionally separate the value from the option letter\n");
 13.1169 -    pc_printf("with a colon (\":\") or an equal sign (\"=\"). That is, the options \"-d0\", \"-d=0\"\n");
 13.1170 -    pc_printf("and \"-d:0\" are all equivalent.\n");
 13.1171 -  } /* if */
 13.1172 -  norun = 1;
 13.1173 -  longjmp(errbuf,3);        /* user abort */
 13.1174 -}
 13.1175 -
 13.1176 -static void setconstants(void)
 13.1177 -{
 13.1178 -  int debug;
 13.1179 -
 13.1180 -  assert(sc_status==statIDLE);
 13.1181 -  append_constval(&tagname_tab,"_",0,0);/* "untagged" */
 13.1182 -  append_constval(&tagname_tab,"bool",1,0);
 13.1183 -
 13.1184 -  add_constant("true",1,sGLOBAL,1);     /* boolean flags */
 13.1185 -  add_constant("false",0,sGLOBAL,1);
 13.1186 -  add_constant("EOS",0,sGLOBAL,0);      /* End Of String, or '\0' */
 13.1187 -  #if PAWN_CELL_SIZE==16
 13.1188 -    add_constant("cellbits",16,sGLOBAL,0);
 13.1189 -    #if defined _I16_MAX
 13.1190 -      add_constant("cellmax",_I16_MAX,sGLOBAL,0);
 13.1191 -      add_constant("cellmin",_I16_MIN,sGLOBAL,0);
 13.1192 -    #else
 13.1193 -      add_constant("cellmax",SHRT_MAX,sGLOBAL,0);
 13.1194 -      add_constant("cellmin",SHRT_MIN,sGLOBAL,0);
 13.1195 -    #endif
 13.1196 -  #elif PAWN_CELL_SIZE==32
 13.1197 -    add_constant("cellbits",32,sGLOBAL,0);
 13.1198 -    #if defined _I32_MAX
 13.1199 -      add_constant("cellmax",_I32_MAX,sGLOBAL,0);
 13.1200 -      add_constant("cellmin",_I32_MIN,sGLOBAL,0);
 13.1201 -    #else
 13.1202 -      add_constant("cellmax",LONG_MAX,sGLOBAL,0);
 13.1203 -      add_constant("cellmin",LONG_MIN,sGLOBAL,0);
 13.1204 -    #endif
 13.1205 -  #elif PAWN_CELL_SIZE==64
 13.1206 -    #if !defined _I64_MIN
 13.1207 -      #define _I64_MIN  (-9223372036854775807ULL - 1)
 13.1208 -      #define _I64_MAX    9223372036854775807ULL
 13.1209 -    #endif
 13.1210 -    add_constant("cellbits",64,sGLOBAL,0);
 13.1211 -    add_constant("cellmax",_I64_MAX,sGLOBAL,0);
 13.1212 -    add_constant("cellmin",_I64_MIN,sGLOBAL,0);
 13.1213 -  #else
 13.1214 -    #error Unsupported cell size
 13.1215 -  #endif
 13.1216 -  add_constant("charbits",sCHARBITS,sGLOBAL,0);
 13.1217 -  add_constant("charmin",0,sGLOBAL,0);
 13.1218 -  add_constant("charmax",~(-1 << sCHARBITS) - 1,sGLOBAL,0);
 13.1219 -  add_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0);
 13.1220 -
 13.1221 -  add_constant("__Pawn",VERSION_INT,sGLOBAL,0);
 13.1222 -
 13.1223 -  debug=0;
 13.1224 -  if ((sc_debug & (sCHKBOUNDS | sSYMBOLIC))==(sCHKBOUNDS | sSYMBOLIC))
 13.1225 -    debug=2;
 13.1226 -  else if ((sc_debug & sCHKBOUNDS)==sCHKBOUNDS)
 13.1227 -    debug=1;
 13.1228 -  add_constant("debug",debug,sGLOBAL,0);
 13.1229 -
 13.1230 -  append_constval(&sc_automaton_tab,"",0,0);    /* anonymous automaton */
 13.1231 -}
 13.1232 -
 13.1233 -static int getclassspec(int initialtok,int *fpublic,int *fstatic,int *fstock,int *fconst)
 13.1234 -{
 13.1235 -  int tok,err;
 13.1236 -  cell val;
 13.1237 -  char *str;
 13.1238 -
 13.1239 -  assert(fconst!=NULL);
 13.1240 -  assert(fstock!=NULL);
 13.1241 -  assert(fstatic!=NULL);
 13.1242 -  assert(fpublic!=NULL);
 13.1243 -  *fconst=FALSE;
 13.1244 -  *fstock=FALSE;
 13.1245 -  *fstatic=FALSE;
 13.1246 -  *fpublic=FALSE;
 13.1247 -  switch (initialtok) {
 13.1248 -  case tCONST:
 13.1249 -    *fconst=TRUE;
 13.1250 -    break;
 13.1251 -  case tSTOCK:
 13.1252 -    *fstock=TRUE;
 13.1253 -    break;
 13.1254 -  case tSTATIC:
 13.1255 -    *fstatic=TRUE;
 13.1256 -    break;
 13.1257 -  case tPUBLIC:
 13.1258 -    *fpublic=TRUE;
 13.1259 -    break;
 13.1260 -  } /* switch */
 13.1261 -
 13.1262 -  err=0;
 13.1263 -  do {
 13.1264 -    tok=lex(&val,&str);  /* read in (new) token */
 13.1265 -    switch (tok) {
 13.1266 -    case tCONST:
 13.1267 -      if (*fconst)
 13.1268 -        err=42;          /* invalid combination of class specifiers */
 13.1269 -      *fconst=TRUE;
 13.1270 -      break;
 13.1271 -    case tSTOCK:
 13.1272 -      if (*fstock)
 13.1273 -        err=42;          /* invalid combination of class specifiers */
 13.1274 -      *fstock=TRUE;
 13.1275 -      break;
 13.1276 -    case tSTATIC:
 13.1277 -      if (*fstatic)
 13.1278 -        err=42;          /* invalid combination of class specifiers */
 13.1279 -      *fstatic=TRUE;
 13.1280 -      break;
 13.1281 -    case tPUBLIC:
 13.1282 -      if (*fpublic)
 13.1283 -        err=42;          /* invalid combination of class specifiers */
 13.1284 -      *fpublic=TRUE;
 13.1285 -      break;
 13.1286 -    default:
 13.1287 -      lexpush();
 13.1288 -      tok=0;             /* force break out of loop */
 13.1289 -    } /* switch */
 13.1290 -  } while (tok && err==0);
 13.1291 -
 13.1292 -  /* extra checks */
 13.1293 -  if (*fstatic && *fpublic) {
 13.1294 -    err=42;              /* invalid combination of class specifiers */
 13.1295 -    *fstatic=*fpublic=FALSE;
 13.1296 -  } /* if */
 13.1297 -
 13.1298 -  if (err)
 13.1299 -    error(err);
 13.1300 -  return err==0;
 13.1301 -}
 13.1302 -
 13.1303 -/*  parse       - process all input text
 13.1304 - *
 13.1305 - *  At this level, only static declarations and function definitions are legal.
 13.1306 - */
 13.1307 -static void parse(void)
 13.1308 -{
 13.1309 -  int tok,fconst,fstock,fstatic,fpublic;
 13.1310 -  cell val;
 13.1311 -  char *str;
 13.1312 -
 13.1313 -  while (freading){
 13.1314 -    /* first try whether a declaration possibly is native or public */
 13.1315 -    tok=lex(&val,&str);  /* read in (new) token */
 13.1316 -    switch (tok) {
 13.1317 -    case 0:
 13.1318 -      /* ignore zero's */
 13.1319 -      break;
 13.1320 -    case tNEW:
 13.1321 -      if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst))
 13.1322 -        declglb(NULL,0,fpublic,fstatic,fstock,fconst);
 13.1323 -      break;
 13.1324 -    case tSTATIC:
 13.1325 -      /* This can be a static function or a static global variable; we know
 13.1326 -       * which of the two as soon as we have parsed up to the point where an
 13.1327 -       * opening paranthesis of a function would be expected. To back out after
 13.1328 -       * deciding it was a declaration of a static variable after all, we have
 13.1329 -       * to store the symbol name and tag.
 13.1330 -       */
 13.1331 -      if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) {
 13.1332 -        assert(!fpublic);
 13.1333 -        declfuncvar(fpublic,fstatic,fstock,fconst);
 13.1334 -      } /* if */
 13.1335 -      break;
 13.1336 -    case tCONST:
 13.1337 -      decl_const(sGLOBAL);
 13.1338 -      break;
 13.1339 -    case tENUM:
 13.1340 -      decl_enum(sGLOBAL);
 13.1341 -      break;
 13.1342 -    case tPUBLIC:
 13.1343 -      /* This can be a public function or a public variable; see the comment
 13.1344 -       * above (for static functions/variables) for details.
 13.1345 -       */
 13.1346 -      if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) {
 13.1347 -        assert(!fstatic);
 13.1348 -        declfuncvar(fpublic,fstatic,fstock,fconst);
 13.1349 -      } /* if */
 13.1350 -      break;
 13.1351 -    case tSTOCK:
 13.1352 -      /* This can be a stock function or a stock *global*) variable; see the
 13.1353 -       * comment above (for static functions/variables) for details.
 13.1354 -       */
 13.1355 -      if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) {
 13.1356 -        assert(fstock);
 13.1357 -        declfuncvar(fpublic,fstatic,fstock,fconst);
 13.1358 -      } /* if */
 13.1359 -      break;
 13.1360 -    case tLABEL:
 13.1361 -    case tSYMBOL:
 13.1362 -    case tOPERATOR:
 13.1363 -      lexpush();
 13.1364 -      if (!newfunc(NULL,-1,FALSE,FALSE,FALSE)) {
 13.1365 -        error(10);              /* illegal function or declaration */
 13.1366 -        lexclr(TRUE);           /* drop the rest of the line */
 13.1367 -        litidx=0;               /* drop the literal queue too */
 13.1368 -      } /* if */
 13.1369 -      break;
 13.1370 -    case tNATIVE:
 13.1371 -      funcstub(TRUE);           /* create a dummy function */
 13.1372 -      break;
 13.1373 -    case tFORWARD:
 13.1374 -      funcstub(FALSE);
 13.1375 -      break;
 13.1376 -    case '}':
 13.1377 -      error(54);                /* unmatched closing brace */
 13.1378 -      break;
 13.1379 -    case '{':
 13.1380 -      error(55);                /* start of function body without function header */
 13.1381 -      break;
 13.1382 -    default:
 13.1383 -      if (freading) {
 13.1384 -        error(10);              /* illegal function or declaration */
 13.1385 -        lexclr(TRUE);           /* drop the rest of the line */
 13.1386 -        litidx=0;               /* drop any literal arrays (strings) */
 13.1387 -      } /* if */
 13.1388 -    } /* switch */
 13.1389 -  } /* while */
 13.1390 -}
 13.1391 -
 13.1392 -/*  dumplits
 13.1393 - *
 13.1394 - *  Dump the literal pool (strings etc.)
 13.1395 - *
 13.1396 - *  Global references: litidx (referred to only)
 13.1397 - */
 13.1398 -static void dumplits(void)
 13.1399 -{
 13.1400 -  int j,k;
 13.1401 -
 13.1402 -  k=0;
 13.1403 -  while (k<litidx){
 13.1404 -    /* should be in the data segment */
 13.1405 -    assert(curseg==2);
 13.1406 -    defstorage();
 13.1407 -    j=16;       /* 16 values per line */
 13.1408 -    while (j && k<litidx){
 13.1409 -      outval(litq[k], FALSE);
 13.1410 -      stgwrite(" ");
 13.1411 -      k++;
 13.1412 -      j--;
 13.1413 -      if (j==0 || k>=litidx)
 13.1414 -        stgwrite("\n");         /* force a newline after 10 dumps */
 13.1415 -      /* Note: stgwrite() buffers a line until it is complete. It recognizes
 13.1416 -       * the end of line as a sequence of "\n\0", so something like "\n\t"
 13.1417 -       * so should not be passed to stgwrite().
 13.1418 -       */
 13.1419 -    } /* while */
 13.1420 -  } /* while */
 13.1421 -}
 13.1422 -
 13.1423 -/*  dumpzero
 13.1424 - *
 13.1425 - *  Dump zero's for default initial values
 13.1426 - */
 13.1427 -static void dumpzero(int count)
 13.1428 -{
 13.1429 -  int i;
 13.1430 -
 13.1431 -  if (count<=0)
 13.1432 -    return;
 13.1433 -  assert(curseg==2);
 13.1434 -  defstorage();
 13.1435 -  i=0;
 13.1436 -  while (count-- > 0) {
 13.1437 -    outval(0, FALSE);
 13.1438 -    i=(i+1) % 16;
 13.1439 -    stgwrite((i==0 || count==0) ? "\n" : " ");
 13.1440 -    if (i==0 && count>0)
 13.1441 -      defstorage();
 13.1442 -  } /* while */
 13.1443 -}
 13.1444 -
 13.1445 -static void aligndata(int numbytes)
 13.1446 -{
 13.1447 -  assert(numbytes % sizeof(cell) == 0);   /* alignment must be a multiple of
 13.1448 -                                           * the cell size */
 13.1449 -  assert(numbytes!=0);
 13.1450 -
 13.1451 -  if ((((glb_declared+litidx)*sizeof(cell)) % numbytes)!=0) {
 13.1452 -    while ((((glb_declared+litidx)*sizeof(cell)) % numbytes)!=0)
 13.1453 -      litadd(0);
 13.1454 -  } /* if */
 13.1455 -
 13.1456 -}
 13.1457 -
 13.1458 -#if !defined SC_LIGHT
 13.1459 -/* sc_attachdocumentation()
 13.1460 - * appends documentation comments to the passed-in symbol, or to a global
 13.1461 - * string if "sym" is NULL.
 13.1462 - */
 13.1463 -void sc_attachdocumentation(symbol *sym)
 13.1464 -{
 13.1465 -  int line;
 13.1466 -  size_t length;
 13.1467 -  char *str,*doc;
 13.1468 -
 13.1469 -  if (!sc_makereport || sc_status!=statFIRST || sc_parsenum>0) {
 13.1470 -    /* just clear the entire table */
 13.1471 -    delete_docstringtable();
 13.1472 -    return;
 13.1473 -  } /* if */
 13.1474 -  /* in the case of state functions, multiple documentation sections may
 13.1475 -   * appear; we should concatenate these
 13.1476 -   * (with forward declarations, this is also already the case, so the assertion
 13.1477 -   * below is invalid)
 13.1478 -   */
 13.1479 -  // assert(sym==NULL || sym->documentation==NULL || sym->states!=NULL);
 13.1480 -
 13.1481 -  /* first check the size */
 13.1482 -  length=0;
 13.1483 -  for (line=0; (str=get_docstring(line))!=NULL && *str!=sDOCSEP; line++) {
 13.1484 -    if (length>0)
 13.1485 -      length++;   /* count 1 extra for a separating space */
 13.1486 -    length+=strlen(str);
 13.1487 -  } /* for */
 13.1488 -  if (sym==NULL && sc_documentation!=NULL) {
 13.1489 -    length += strlen(sc_documentation) + 1 + 4; /* plus 4 for "<p/>" */
 13.1490 -    assert(length>strlen(sc_documentation));
 13.1491 -  } /* if */
 13.1492 -
 13.1493 -  if (length>0) {
 13.1494 -    /* allocate memory for the documentation */
 13.1495 -    if (sym!=NULL && sym->documentation!=NULL)
 13.1496 -      length+=strlen(sym->documentation) + 1 + 4;/* plus 4 for "<p/>" */
 13.1497 -    doc=(char*)malloc((length+1)*sizeof(char));
 13.1498 -    if (doc!=NULL) {
 13.1499 -      /* initialize string or concatenate */
 13.1500 -      if (sym==NULL && sc_documentation!=NULL) {
 13.1501 -        strcpy(doc,sc_documentation);
 13.1502 -        strcat(doc,"<p/>");
 13.1503 -      } else if (sym!=NULL && sym->documentation!=NULL) {
 13.1504 -        strcpy(doc,sym->documentation);
 13.1505 -        strcat(doc,"<p/>");
 13.1506 -        free(sym->documentation);
 13.1507 -        sym->documentation=NULL;
 13.1508 -      } else {
 13.1509 -        doc[0]='\0';
 13.1510 -      } /* if */
 13.1511 -      /* collect all documentation */
 13.1512 -      while ((str=get_docstring(0))!=NULL && *str!=sDOCSEP) {
 13.1513 -        if (doc[0]!='\0')
 13.1514 -          strcat(doc," ");
 13.1515 -        strcat(doc,str);
 13.1516 -        delete_docstring(0);
 13.1517 -      } /* while */
 13.1518 -      if (str!=NULL) {
 13.1519 -        /* also delete the separator */
 13.1520 -        assert(*str==sDOCSEP);
 13.1521 -        delete_docstring(0);
 13.1522 -      } /* if */
 13.1523 -      if (sym!=NULL) {
 13.1524 -        assert(sym->documentation==NULL);
 13.1525 -        sym->documentation=doc;
 13.1526 -      } else {
 13.1527 -        if (sc_documentation!=NULL)
 13.1528 -          free(sc_documentation);
 13.1529 -        sc_documentation=doc;
 13.1530 -      } /* if */
 13.1531 -    } /* if */
 13.1532 -  } else {
 13.1533 -    /* delete an empty separator, if present */
 13.1534 -    if ((str=get_docstring(0))!=NULL && *str==sDOCSEP)
 13.1535 -      delete_docstring(0);
 13.1536 -  } /* if */
 13.1537 -}
 13.1538 -
 13.1539 -static void insert_docstring_separator(void)
 13.1540 -{
 13.1541 -  char sep[2]={sDOCSEP,'\0'};
 13.1542 -  insert_docstring(sep);
 13.1543 -}
 13.1544 -#else
 13.1545 -  #define sc_attachdocumentation(s)      (void)(s)
 13.1546 -  #define insert_docstring_separator()
 13.1547 -#endif
 13.1548 -
 13.1549 -static void declfuncvar(int fpublic,int fstatic,int fstock,int fconst)
 13.1550 -{
 13.1551 -  char name[sNAMEMAX+11];
 13.1552 -  int tok,tag;
 13.1553 -  char *str;
 13.1554 -  cell val;
 13.1555 -  int invalidfunc;
 13.1556 -
 13.1557 -  tag=pc_addtag(NULL);
 13.1558 -  tok=lex(&val,&str);
 13.1559 -  /* if we arrived here, this may not be a declaration of a native function
 13.1560 -   * or variable
 13.1561 -   */
 13.1562 -  if (tok==tNATIVE) {
 13.1563 -    error(42);          /* invalid combination of class specifiers */
 13.1564 -    return;
 13.1565 -  } /* if */
 13.1566 -
 13.1567 -  if (tok!=tSYMBOL && tok!=tOPERATOR) {
 13.1568 -    lexpush();
 13.1569 -    needtoken(tSYMBOL);
 13.1570 -    lexclr(TRUE);       /* drop the rest of the line */
 13.1571 -    litidx=0;           /* drop the literal queue too */
 13.1572 -    return;
 13.1573 -  } /* if */
 13.1574 -  if (tok==tOPERATOR) {
 13.1575 -    lexpush();          /* push "operator" keyword back (for later analysis) */
 13.1576 -    if (!newfunc(NULL,tag,fpublic,fstatic,fstock)) {
 13.1577 -      error(10);        /* illegal function or declaration */
 13.1578 -      lexclr(TRUE);     /* drop the rest of the line */
 13.1579 -      litidx=0;         /* drop the literal queue too */
 13.1580 -    } /* if */
 13.1581 -  } else {
 13.1582 -    /* so tok is tSYMBOL */
 13.1583 -    assert(strlen(str)<=sNAMEMAX);
 13.1584 -    strcpy(name,str);
 13.1585 -    /* only variables can be "const" or both "public" and "stock" */
 13.1586 -    invalidfunc= fconst || (fpublic && fstock);
 13.1587 -    if (invalidfunc || !newfunc(name,tag,fpublic,fstatic,fstock)) {
 13.1588 -      /* if not a function, try a global variable */
 13.1589 -      declglb(name,tag,fpublic,fstatic,fstock,fconst);
 13.1590 -    } /* if */
 13.1591 -  } /* if */
 13.1592 -}
 13.1593 -
 13.1594 -/*  declglb     - declare global symbols
 13.1595 - *
 13.1596 - *  Declare a static (global) variable. Global variables are stored in
 13.1597 - *  the DATA segment.
 13.1598 - *
 13.1599 - *  global references: glb_declared     (altered)
 13.1600 - */
 13.1601 -static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fstock,int fconst)
 13.1602 -{
 13.1603 -  int ident,tag,ispublic;
 13.1604 -  int idxtag[sDIMEN_MAX];
 13.1605 -  char name[sNAMEMAX+1];
 13.1606 -  cell val,size,cidx;
 13.1607 -  ucell address;
 13.1608 -  int glb_incr;
 13.1609 -  char *str;
 13.1610 -  int dim[sDIMEN_MAX];
 13.1611 -  int numdim;
 13.1612 -  short filenum;
 13.1613 -  symbol *sym;
 13.1614 -  constvalue *enumroot;
 13.1615 -  #if !defined NDEBUG
 13.1616 -    cell glbdecl=0;
 13.1617 -  #endif
 13.1618 -
 13.1619 -  assert(!fpublic || !fstatic);         /* may not both be set */
 13.1620 -  insert_docstring_separator();         /* see comment in newfunc() */
 13.1621 -  filenum=fcurrent;                     /* save file number at the start of the declaration */
 13.1622 -  do {
 13.1623 -    size=1;                             /* single size (no array) */
 13.1624 -    numdim=0;                           /* no dimensions */
 13.1625 -    ident=iVARIABLE;
 13.1626 -    if (firstname!=NULL) {
 13.1627 -      assert(strlen(firstname)<=sNAMEMAX);
 13.1628 -      strcpy(name,firstname);           /* save symbol name */
 13.1629 -      tag=firsttag;
 13.1630 -      firstname=NULL;
 13.1631 -    } else {
 13.1632 -      tag=pc_addtag(NULL);
 13.1633 -      if (lex(&val,&str)!=tSYMBOL)      /* read in (new) token */
 13.1634 -        error(20,str);                  /* invalid symbol name */
 13.1635 -      assert(strlen(str)<=sNAMEMAX);
 13.1636 -      strcpy(name,str);                 /* save symbol name */
 13.1637 -    } /* if */
 13.1638 -    ispublic=fpublic;
 13.1639 -    if (name[0]==PUBLIC_CHAR) {
 13.1640 -      ispublic=TRUE;                    /* implicitly public variable */
 13.1641 -      assert(!fstatic);
 13.1642 -    } /* if */
 13.1643 -    while (matchtoken('[')) {
 13.1644 -      ident=iARRAY;
 13.1645 -      if (numdim == sDIMEN_MAX) {
 13.1646 -        error(53);                      /* exceeding maximum number of dimensions */
 13.1647 -        return;
 13.1648 -      } /* if */
 13.1649 -      size=needsub(&idxtag[numdim],&enumroot);  /* get size; size==0 for "var[]" */
 13.1650 -      #if INT_MAX < LONG_MAX
 13.1651 -        if (size > INT_MAX)
 13.1652 -          error(105);                   /* overflow, exceeding capacity */
 13.1653 -      #endif
 13.1654 -      if (ispublic)
 13.1655 -        error(56,name);                 /* arrays cannot be public */
 13.1656 -      dim[numdim++]=(int)size;
 13.1657 -    } /* while */
 13.1658 -    assert(sc_curstates==0);
 13.1659 -    sc_curstates=getstates(name);
 13.1660 -    if (sc_curstates<0) {
 13.1661 -      error(85,name);           /* empty state list on declaration */
 13.1662 -      sc_curstates=0;
 13.1663 -    } else if (sc_curstates>0 && ispublic) {
 13.1664 -      error(88,name);           /* public variables may not have states */
 13.1665 -      sc_curstates=0;
 13.1666 -    } /* if */
 13.1667 -    sym=findconst(name,NULL);
 13.1668 -    if (sym==NULL) {
 13.1669 -      sym=findglb(name,sSTATEVAR);
 13.1670 -      /* if a global variable without states is found and this declaration has
 13.1671 -       * states, the declaration is okay
 13.1672 -       */
 13.1673 -      if (sym!=NULL && sym->states==NULL && sc_curstates>0)
 13.1674 -        sym=NULL;               /* set to NULL, we found the global variable */
 13.1675 -      if (sc_curstates>0 && findglb(name,sGLOBAL)!=NULL)
 13.1676 -        error(233,name);        /* state variable shadows a global variable */
 13.1677 -    } /* if */
 13.1678 -    /* we have either:
 13.1679 -     * a) not found a matching variable (or rejected it, because it was a shadow)
 13.1680 -     * b) found a global variable and we were looking for that global variable
 13.1681 -     * c) found a state variable in the automaton that we were looking for
 13.1682 -     */
 13.1683 -    assert(sym==NULL
 13.1684 -           || sym->states==NULL && sc_curstates==0
 13.1685 -           || sym->states!=NULL && sym->next!=NULL && sym->states->next->index==sc_curstates);
 13.1686 -    /* a state variable may only have a single id in its list (so either this
 13.1687 -     * variable has no states, or it has a single list)
 13.1688 -     */
 13.1689 -    assert(sym==NULL || sym->states==NULL || sym->states->next->next==NULL);
 13.1690 -    /* it is okay for the (global) variable to exist, as long as it belongs to
 13.1691 -     * a different automaton
 13.1692 -     */
 13.1693 -    if (sym!=NULL && (sym->usage & uDEFINE)!=0)
 13.1694 -      error(21,name);                   /* symbol already defined */
 13.1695 -    /* if this variable is never used (which can be detected only in the
 13.1696 -     * second stage), shut off code generation
 13.1697 -     */
 13.1698 -    cidx=0;             /* only to avoid a compiler warning */
 13.1699 -    if (sc_status==statWRITE && sym!=NULL && (sym->usage & (uREAD | uWRITTEN))==0) {
 13.1700 -      sc_status=statSKIP;
 13.1701 -      cidx=code_idx;
 13.1702 -      #if !defined NDEBUG
 13.1703 -        glbdecl=glb_declared;
 13.1704 -      #endif
 13.1705 -    } /* if */
 13.1706 -    begdseg();          /* real (initialized) data in data segment */
 13.1707 -    assert(litidx==0);  /* literal queue should be empty */
 13.1708 -    if (sc_alignnext) {
 13.1709 -      litidx=0;
 13.1710 -      aligndata(sc_dataalign);
 13.1711 -      dumplits();       /* dump the literal queue */
 13.1712 -      sc_alignnext=FALSE;
 13.1713 -      litidx=0;         /* global initial data is dumped, so restart at zero */
 13.1714 -    } /* if */
 13.1715 -    assert(litidx==0);  /* literal queue should be empty (again) */
 13.1716 -    initials(ident,tag,&size,dim,numdim,enumroot);/* stores values in the literal queue */
 13.1717 -    assert(size>=litidx);
 13.1718 -    if (numdim==1)
 13.1719 -      dim[0]=(int)size;
 13.1720 -    /* before dumping the initial values (or zeros) check whether this variable
 13.1721 -     * overlaps another
 13.1722 -     */
 13.1723 -    if (sc_curstates>0) {
 13.1724 -      unsigned char *map;
 13.1725 -
 13.1726 -      if (litidx!=0)
 13.1727 -        error(89,name); /* state variables may not be initialized */
 13.1728 -      /* find an appropriate address for the state variable */
 13.1729 -      /* assume that it cannot be found */
 13.1730 -      address=sizeof(cell)*glb_declared;
 13.1731 -      glb_incr=(int)size;
 13.1732 -      /* use a memory map in which every cell occupies one bit */
 13.1733 -      if (glb_declared>0 && (map=(unsigned char*)malloc((glb_declared+7)/8))!=NULL) {
 13.1734 -        int fsa=state_getfsa(sc_curstates);
 13.1735 -        symbol *sweep;
 13.1736 -        cell sweepsize,addr;
 13.1737 -        memset(map,0,(glb_declared+7)/8);
 13.1738 -        assert(fsa>=0);
 13.1739 -        /* fill in all variables belonging to this automaton */
 13.1740 -        for (sweep=glbtab.next; sweep!=NULL; sweep=sweep->next) {
 13.1741 -          if (sweep->parent!=NULL || sweep->states==NULL || sweep==sym)
 13.1742 -            continue;   /* hierarchical type, or no states, or same as this variable */
 13.1743 -          if (sweep->ident!=iVARIABLE && sweep->ident!=iARRAY)
 13.1744 -            continue;   /* a function or a constant */
 13.1745 -          if ((sweep->usage & uDEFINE)==0)
 13.1746 -            continue;   /* undefined variable, ignore */
 13.1747 -          if (fsa!=state_getfsa(sweep->states->next->index))
 13.1748 -            continue;   /* wrong automaton */
 13.1749 -          /* when arrived here, this is a global variable, with states and
 13.1750 -           * belonging to the same automaton as the variable we are declaring
 13.1751 -           */
 13.1752 -          sweepsize=(sweep->ident==iVARIABLE) ? 1 : array_totalsize(sweep);
 13.1753 -          assert(sweep->addr % sizeof(cell) == 0);
 13.1754 -          addr=sweep->addr/sizeof(cell);
 13.1755 -          /* mark this address range */
 13.1756 -          while (sweepsize-->0) {
 13.1757 -            map[addr/8] |= (unsigned char)(1 << (addr % 8));
 13.1758 -            addr++;
 13.1759 -          } /* while */
 13.1760 -        } /* for */
 13.1761 -        /* go over it again, clearing any ranges that have conflicts */
 13.1762 -        for (sweep=glbtab.next; sweep!=NULL; sweep=sweep->next) {
 13.1763 -          if (sweep->parent!=NULL || sweep->states==NULL || sweep==sym)
 13.1764 -            continue;   /* hierarchical type, or no states, or same as this variable */
 13.1765 -          if (sweep->ident!=iVARIABLE && sweep->ident!=iARRAY)
 13.1766 -            continue;   /* a function or a constant */
 13.1767 -          if ((sweep->usage & uDEFINE)==0)
 13.1768 -            continue;   /* undefined variable, ignore */
 13.1769 -          if (fsa!=state_getfsa(sweep->states->next->index))
 13.1770 -            continue;   /* wrong automaton */
 13.1771 -          /* when arrived here, this is a global variable, with states and
 13.1772 -           * belonging to the same automaton as the variable we are declaring
 13.1773 -           */
 13.1774 -          /* if the lists of states of the existing variable and the new
 13.1775 -           * variable have a non-empty intersection, this is not a suitable
 13.1776 -           * overlap point -> wipe the address range
 13.1777 -           */
 13.1778 -          if (state_conflict_id(sc_curstates,sweep->states->next->index)) {
 13.1779 -            sweepsize=(sweep->ident==iVARIABLE) ? 1 : array_totalsize(sweep);
 13.1780 -            assert(sweep->addr % sizeof(cell) == 0);
 13.1781 -            addr=sweep->addr/sizeof(cell);
 13.1782 -            /* mark this address range */
 13.1783 -            while (sweepsize-->0) {
 13.1784 -              map[addr/8] &= (unsigned char)(~(1 << (addr % 8)));
 13.1785 -              addr++;
 13.1786 -            } /* while */
 13.1787 -          } /* if */
 13.1788 -        } /* for */
 13.1789 -        /* now walk through the map and find a starting point that is big enough */
 13.1790 -        sweepsize=0;
 13.1791 -        for (addr=0; addr<glb_declared; addr++) {
 13.1792 -          if ((map[addr/8] & (1 << (addr % 8)))==0)
 13.1793 -            continue;
 13.1794 -          for (sweepsize=addr+1; sweepsize<glb_declared; sweepsize++) {
 13.1795 -            if ((map[sweepsize/8] & (1 << (sweepsize % 8)))==0)
 13.1796 -              break;    /* zero bit found, skip this range */
 13.1797 -            if (sweepsize-addr>=size)
 13.1798 -              break;    /* fitting range found, no need to search further */
 13.1799 -          } /* for */
 13.1800 -          if (sweepsize-addr>=size)
 13.1801 -            break;      /* fitting range found, no need to search further */
 13.1802 -          addr=sweepsize;
 13.1803 -        } /* for */
 13.1804 -        free(map);
 13.1805 -        if (sweepsize-addr>=size) {
 13.1806 -          address=sizeof(cell)*addr;    /* fitting range found, set it */
 13.1807 -          glb_incr=0;
 13.1808 -        } /* if */
 13.1809 -      } /* if */
 13.1810 -    } else {
 13.1811 -      address=sizeof(cell)*glb_declared;
 13.1812 -      glb_incr=(int)size;
 13.1813 -    } /* if */
 13.1814 -    if (address==sizeof(cell)*glb_declared) {
 13.1815 -      dumplits();       /* dump the literal queue */
 13.1816 -      dumpzero((int)size-litidx);
 13.1817 -    } /* if */
 13.1818 -    litidx=0;
 13.1819 -    if (sym==NULL) {    /* define only if not yet defined */
 13.1820 -      sym=addvariable(name,address,ident,sGLOBAL,tag,dim,numdim,idxtag);
 13.1821 -      if (sc_curstates>0)
 13.1822 -        attachstatelist(sym,sc_curstates);
 13.1823 -    } else {            /* if declared but not yet defined, adjust the variable's address */
 13.1824 -      assert(sym->states==NULL && sc_curstates==0
 13.1825 -             || sym->states->next!=NULL && sym->states->next->index==sc_curstates && sym->states->next->next==NULL);
 13.1826 -      sym->addr=address;
 13.1827 -      sym->codeaddr=code_idx;
 13.1828 -      sym->usage|=uDEFINE;
 13.1829 -    } /* if */
 13.1830 -    assert(sym!=NULL);
 13.1831 -    sc_curstates=0;
 13.1832 -    if (ispublic)
 13.1833 -      sym->usage|=uPUBLIC;
 13.1834 -    if (fconst)
 13.1835 -      sym->usage|=uCONST;
 13.1836 -    if (fstock)
 13.1837 -      sym->usage|=uSTOCK;
 13.1838 -    if (fstatic)
 13.1839 -      sym->fnumber=filenum;
 13.1840 -    sc_attachdocumentation(sym);/* attach any documenation to the variable */
 13.1841 -    if (sc_status==statSKIP) {
 13.1842 -      sc_status=statWRITE;
 13.1843 -      code_idx=cidx;
 13.1844 -      assert(glb_declared==glbdecl);
 13.1845 -    } else {
 13.1846 -      glb_declared+=glb_incr;   /* add total number of cells (if added to the end) */
 13.1847 -    } /* if */
 13.1848 -  } while (matchtoken(',')); /* enddo */   /* more? */
 13.1849 -  needtoken(tTERM);    /* if not comma, must be semicolumn */
 13.1850 -}
 13.1851 -
 13.1852 -/*  declloc     - declare local symbols
 13.1853 - *
 13.1854 - *  Declare local (automatic) variables. Since these variables are relative
 13.1855 - *  to the STACK, there is no switch to the DATA segment. These variables
 13.1856 - *  cannot be initialized either.
 13.1857 - *
 13.1858 - *  global references: declared   (altered)
 13.1859 - *                     funcstatus (referred to only)
 13.1860 - */
 13.1861 -static int declloc(int fstatic)
 13.1862 -{
 13.1863 -  int ident,tag;
 13.1864 -  int idxtag[sDIMEN_MAX];
 13.1865 -  char name[sNAMEMAX+1];
 13.1866 -  symbol *sym;
 13.1867 -  constvalue *enumroot;
 13.1868 -  cell val,size;
 13.1869 -  char *str;
 13.1870 -  value lval = {0};
 13.1871 -  int cur_lit=0;
 13.1872 -  int dim[sDIMEN_MAX];
 13.1873 -  int numdim;
 13.1874 -  int fconst;
 13.1875 -  int staging_start;
 13.1876 -
 13.1877 -  fconst=matchtoken(tCONST);
 13.1878 -  do {
 13.1879 -    ident=iVARIABLE;
 13.1880 -    size=1;
 13.1881 -    numdim=0;                           /* no dimensions */
 13.1882 -    tag=pc_addtag(NULL);
 13.1883 -    if (lex(&val,&str)!=tSYMBOL)        /* read in (new) token */
 13.1884 -      error(20,str);                    /* invalid symbol name */
 13.1885 -    assert(strlen(str)<=sNAMEMAX);
 13.1886 -    strcpy(name,str);                   /* save symbol name */
 13.1887 -    if (name[0]==PUBLIC_CHAR)
 13.1888 -      error(56,name);                   /* local variables cannot be public */
 13.1889 -    /* Note: block locals may be named identical to locals at higher
 13.1890 -     * compound blocks (as with standard C); so we must check (and add)
 13.1891 -     * the "nesting level" of local variables to verify the
 13.1892 -     * multi-definition of symbols.
 13.1893 -     */
 13.1894 -    if ((sym=findloc(name))!=NULL && sym->compound==nestlevel)
 13.1895 -      error(21,name);                   /* symbol already defined */
 13.1896 -    /* Although valid, a local variable whose name is equal to that
 13.1897 -     * of a global variable or to that of a local variable at a lower
 13.1898 -     * level might indicate a bug.
 13.1899 -     */
 13.1900 -    if ((sym=findloc(name))!=NULL && sym->compound!=nestlevel || findglb(name,sGLOBAL)!=NULL)
 13.1901 -      error(219,name);                  /* variable shadows another symbol */
 13.1902 -    while (matchtoken('[')){
 13.1903 -      ident=iARRAY;
 13.1904 -      if (numdim == sDIMEN_MAX) {
 13.1905 -        error(53);                      /* exceeding maximum number of dimensions */
 13.1906 -        return ident;
 13.1907 -      } /* if */
 13.1908 -      size=needsub(&idxtag[numdim],&enumroot); /* get size; size==0 for "var[]" */
 13.1909 -      #if INT_MAX < LONG_MAX
 13.1910 -        if (size > INT_MAX)
 13.1911 -          error(105);                   /* overflow, exceeding capacity */
 13.1912 -      #endif
 13.1913 -      dim[numdim++]=(int)size;
 13.1914 -    } /* while */
 13.1915 -    if (getstates(name))
 13.1916 -      error(88,name);           /* local variables may not have states */
 13.1917 -    if (ident==iARRAY || fstatic) {
 13.1918 -      if (sc_alignnext) {
 13.1919 -        aligndata(sc_dataalign);
 13.1920 -        sc_alignnext=FALSE;
 13.1921 -      } /* if */
 13.1922 -      cur_lit=litidx;           /* save current index in the literal table */
 13.1923 -      initials(ident,tag,&size,dim,numdim,enumroot);
 13.1924 -      if (size==0)
 13.1925 -        return ident;           /* error message already given */
 13.1926 -      if (numdim==1)
 13.1927 -        dim[0]=(int)size;
 13.1928 -    } /* if */
 13.1929 -    /* reserve memory (on the stack) for the variable */
 13.1930 -    if (fstatic) {
 13.1931 -      /* write zeros for uninitialized fields */
 13.1932 -      while (litidx<cur_lit+size)
 13.1933 -        litadd(0);
 13.1934 -      sym=addvariable(name,(cur_lit+glb_declared)*sizeof(cell),ident,sSTATIC,
 13.1935 -                      tag,dim,numdim,idxtag);
 13.1936 -    } else {
 13.1937 -      declared+=(int)size;      /* variables are put on stack, adjust "declared" */
 13.1938 -      sym=addvariable(name,-declared*sizeof(cell),ident,sLOCAL,tag,
 13.1939 -                      dim,numdim,idxtag);
 13.1940 -      if (ident==iVARIABLE) {
 13.1941 -        assert(!staging);
 13.1942 -        stgset(TRUE);           /* start stage-buffering */
 13.1943 -        assert(stgidx==0);
 13.1944 -        staging_start=stgidx;
 13.1945 -      } /* if */
 13.1946 -      markexpr(sLDECL,name,-declared*sizeof(cell)); /* mark for better optimization */
 13.1947 -      modstk(-(int)size*sizeof(cell));
 13.1948 -      assert(curfunc!=NULL);
 13.1949 -      assert((curfunc->usage & uNATIVE)==0);
 13.1950 -      if (curfunc->x.stacksize<declared+1)
 13.1951 -        curfunc->x.stacksize=declared+1;  /* +1 for PROC opcode */
 13.1952 -    } /* if */
 13.1953 -    /* now that we have reserved memory for the variable, we can proceed
 13.1954 -     * to initialize it */
 13.1955 -    assert(sym!=NULL);          /* we declared it, it must be there */
 13.1956 -    sym->compound=nestlevel;    /* for multiple declaration/shadowing check */
 13.1957 -    if (fconst)
 13.1958 -      sym->usage|=uCONST;
 13.1959 -    if (!fstatic) {             /* static variables already initialized */
 13.1960 -      if (ident==iVARIABLE) {
 13.1961 -        /* simple variable, also supports initialization */
 13.1962 -        int ctag = tag;         /* set to "tag" by default */
 13.1963 -        int explicit_init=FALSE;/* is the variable explicitly initialized? */
 13.1964 -        if (matchtoken('=')) {
 13.1965 -          if (!autozero)
 13.1966 -            error(10);
 13.1967 -          doexpr(FALSE,FALSE,FALSE,FALSE,&ctag,NULL,TRUE);
 13.1968 -          explicit_init=TRUE;
 13.1969 -        } else {
 13.1970 -          if (autozero)
 13.1971 -            ldconst(0,sPRI);      /* uninitialized variable, set to zero */
 13.1972 -        } /* if */
 13.1973 -        if (autozero) {
 13.1974 -          /* now try to save the value (still in PRI) in the variable */
 13.1975 -          lval.sym=sym;
 13.1976 -          lval.ident=iVARIABLE;
 13.1977 -          lval.constval=0;
 13.1978 -          lval.tag=tag;
 13.1979 -          check_userop(NULL,ctag,lval.tag,2,NULL,&ctag);
 13.1980 -          store(&lval);
 13.1981 -          markexpr(sEXPR,NULL,0); /* full expression ends after the store */
 13.1982 -        }
 13.1983 -        assert(staging);        /* end staging phase (optimize expression) */
 13.1984 -        stgout(staging_start);
 13.1985 -        stgset(FALSE);
 13.1986 -        if (!matchtag(tag,ctag,TRUE))
 13.1987 -          error(213);           /* tag mismatch */
 13.1988 -        /* if the variable was not explicitly initialized, reset the
 13.1989 -         * "uWRITTEN" flag that store() set */
 13.1990 -        if (!explicit_init)
 13.1991 -          sym->usage &= ~uWRITTEN;
 13.1992 -      } else {
 13.1993 -        /* an array */
 13.1994 -        assert(cur_lit>=0 && cur_lit<=litidx && litidx<=litmax);
 13.1995 -        assert(size>0 && size>=sym->dim.array.length);
 13.1996 -        assert(numdim>1 || size==sym->dim.array.length);
 13.1997 -        if (autozero) {
 13.1998 -          /* final literal values that are zero make no sense to put in the literal
 13.1999 -           * pool, because values get zero-initialized anyway; we check for this,
 13.2000 -           * because users often explicitly initialize strings to ""
 13.2001 -           */
 13.2002 -          while (litidx>cur_lit && litq[litidx-1]==0)
 13.2003 -            litidx--;
 13.2004 -          /* if the array is not completely filled, set all values to zero first */
 13.2005 -          if (litidx-cur_lit<size && (ucell)size<CELL_MAX)
 13.2006 -            fillarray(sym,size*sizeof(cell),0);
 13.2007 -        }
 13.2008 -        if (cur_lit<litidx) {
 13.2009 -          /* check whether the complete array is set to a single value; if
 13.2010 -           * it is, more compact code can be generated */
 13.2011 -          cell first=litq[cur_lit];
 13.2012 -          int i;
 13.2013 -          for (i=cur_lit; i<litidx && litq[i]==first; i++)
 13.2014 -            /* nothing */;
 13.2015 -          if (i==litidx) {
 13.2016 -            /* all values are the same */
 13.2017 -            fillarray(sym,(litidx-cur_lit)*sizeof(cell),first);
 13.2018 -            litidx=cur_lit;     /* reset literal table */
 13.2019 -          } else {
 13.2020 -            /* copy the literals to the array */
 13.2021 -            ldconst((cur_lit+glb_declared)*sizeof(cell),sPRI);
 13.2022 -            copyarray(sym,(litidx-cur_lit)*sizeof(cell));
 13.2023 -          } /* if */
 13.2024 -        } /* if */
 13.2025 -      } /* if */
 13.2026 -    } /* if */
 13.2027 -  } while (matchtoken(',')); /* enddo */   /* more? */
 13.2028 -  needtoken(tTERM);    /* if not comma, must be semicolumn */
 13.2029 -  return ident;
 13.2030 -}
 13.2031 -
 13.2032 -/* this function returns the maximum value for a cell in case of an error
 13.2033 - * (invalid dimension).
 13.2034 - */
 13.2035 -static cell calc_arraysize(int dim[],int numdim,int cur)
 13.2036 -{
 13.2037 -  cell subsize;
 13.2038 -  ucell newsize;
 13.2039 -
 13.2040 -  /* the return value is in cells, not bytes */
 13.2041 -  assert(cur>=0 && cur<=numdim);
 13.2042 -  if (cur==numdim)
 13.2043 -    return 0;
 13.2044 -  subsize=calc_arraysize(dim,numdim,cur+1);
 13.2045 -  newsize=dim[cur]+dim[cur]*subsize;
 13.2046 -  if ((ucell)subsize>=CELL_MAX || newsize>=CELL_MAX || newsize<(ucell)subsize
 13.2047 -      || newsize*sizeof(cell)>=CELL_MAX)
 13.2048 -    return CELL_MAX;
 13.2049 -  return newsize;
 13.2050 -}
 13.2051 -
 13.2052 -static cell adjust_indirectiontables(int dim[],int numdim,int cur,cell increment,
 13.2053 -                                     int startlit,constvalue *lastdim,int *skipdim)
 13.2054 -{
 13.2055 -static int base;
 13.2056 -  int d;
 13.2057 -  cell accum;
 13.2058 -
 13.2059 -  assert(cur>=0 && cur<numdim);
 13.2060 -  assert(increment>=0);
 13.2061 -  assert(cur>0 && startlit==-1 || startlit>=0 && startlit<=litidx);
 13.2062 -  if (cur==0)
 13.2063 -    base=startlit;
 13.2064 -  if (cur==numdim-1)
 13.2065 -    return 0;
 13.2066 -  /* 2 or more dimensions left, fill in an indirection vector */
 13.2067 -  assert(dim[cur]>0);
 13.2068 -  if (dim[cur+1]>0) {
 13.2069 -    for (d=0; d<dim[cur]; d++)
 13.2070 -      litq[base++]=(dim[cur]+d*(dim[cur+1]-1)+increment) * sizeof(cell);
 13.2071 -    accum=dim[cur]*(dim[cur+1]-1);
 13.2072 -  } else {
 13.2073 -    /* final dimension is variable length */
 13.2074 -    constvalue *ld;
 13.2075 -    assert(dim[cur+1]==0);
 13.2076 -    assert(lastdim!=NULL);
 13.2077 -    assert(skipdim!=NULL);
 13.2078 -    accum=0;
 13.2079 -    /* skip the final dimension sizes for all earlier major dimensions */
 13.2080 -    for (d=0,ld=lastdim->next; d<*skipdim; d++,ld=ld->next) {
 13.2081 -      assert(ld!=NULL);
 13.2082 -    } /* for */
 13.2083 -    for (d=0; d<dim[cur]; d++) {
 13.2084 -      assert(ld!=NULL);
 13.2085 -      assert(strtol(ld->name,NULL,16)==d);
 13.2086 -      litq[base++]=(dim[cur]+accum+increment) * sizeof(cell);
 13.2087 -      accum+=ld->value-1;
 13.2088 -      *skipdim+=1;
 13.2089 -      ld=ld->next;
 13.2090 -    } /* for */
 13.2091 -  } /* if */
 13.2092 -  /* create the indirection tables for the lower level */
 13.2093 -  if (cur+2<numdim) {   /* are there at least 2 dimensions below this one? */
 13.2094 -    increment+=(dim[cur]-1)*dim[cur+1]; /* this many indirection tables follow */
 13.2095 -    for (d=0; d<dim[cur]; d++)
 13.2096 -      increment+=adjust_indirectiontables(dim,numdim,cur+1,increment,-1,lastdim,skipdim);
 13.2097 -  } /* if */
 13.2098 -  return accum;
 13.2099 -}
 13.2100 -
 13.2101 -/*  initials
 13.2102 - *
 13.2103 - *  Initialize global objects and local arrays.
 13.2104 - *    size==array cells (count), if 0 on input, the routine counts the number of elements
 13.2105 - *    tag==required tagname id (not the returned tag)
 13.2106 - *
 13.2107 - *  Global references: litidx (altered)
 13.2108 - */
 13.2109 -static void initials(int ident,int tag,cell *size,int dim[],int numdim,
 13.2110 -                     constvalue *enumroot)
 13.2111 -{
 13.2112 -  int ctag;
 13.2113 -  cell tablesize;
 13.2114 -  int curlit=litidx;
 13.2115 -  int err=0;
 13.2116 -
 13.2117 -  if (!matchtoken('=')) {
 13.2118 -    assert(ident!=iARRAY || numdim>0);
 13.2119 -    if (ident==iARRAY && dim[numdim-1]==0) {
 13.2120 -      /* declared as "myvar[];" which is senseless (note: this *does* make
 13.2121 -       * sense in the case of a iREFARRAY, which is a function parameter)
 13.2122 -       */
 13.2123 -      error(9);         /* array has zero length -> invalid size */
 13.2124 -    } /* if */
 13.2125 -    if (ident==iARRAY) {
 13.2126 -      assert(numdim>0 && numdim<=sDIMEN_MAX);
 13.2127 -      *size=calc_arraysize(dim,numdim,0);
 13.2128 -      if (*size==(cell)CELL_MAX) {
 13.2129 -        error(9);       /* array is too big -> invalid size */
 13.2130 -        return;
 13.2131 -      } /* if */
 13.2132 -      /* first reserve space for the indirection vectors of the array, then
 13.2133 -       * adjust it to contain the proper values
 13.2134 -       * (do not use dumpzero(), as it bypasses the literal queue)
 13.2135 -       */
 13.2136 -      for (tablesize=calc_arraysize(dim,numdim-1,0); tablesize>0; tablesize--)
 13.2137 -        litadd(0);
 13.2138 -      if (dim[numdim-1]!=0)     /* error 9 has already been given */
 13.2139 -        adjust_indirectiontables(dim,numdim,0,0,curlit,NULL,NULL);
 13.2140 -    } /* if */
 13.2141 -    return;
 13.2142 -  } /* if */
 13.2143 -
 13.2144 -  if (ident==iVARIABLE) {
 13.2145 -    assert(*size==1);
 13.2146 -    init(ident,&ctag,NULL);
 13.2147 -    if (!matchtag(tag,ctag,TRUE))
 13.2148 -      error(213);       /* tag mismatch */
 13.2149 -  } else {
 13.2150 -    assert(numdim>0);
 13.2151 -    if (numdim==1) {
 13.2152 -      *size=initvector(ident,tag,dim[0],FALSE,enumroot,NULL);
 13.2153 -    } else {
 13.2154 -      int errorfound=FALSE;
 13.2155 -      int counteddim[sDIMEN_MAX];
 13.2156 -      int idx;
 13.2157 -      constvalue lastdim={NULL,"",0,0};     /* sizes of the final dimension */
 13.2158 -      int skipdim=0;
 13.2159 -
 13.2160 -      if (dim[numdim-1]!=0)
 13.2161 -        *size=calc_arraysize(dim,numdim,0); /* calc. full size, if known */
 13.2162 -      /* already reserve space for the indirection tables (for an array with
 13.2163 -       * known dimensions)
 13.2164 -       * (do not use dumpzero(), as it bypasses the literal queue)
 13.2165 -       */
 13.2166 -      for (tablesize=calc_arraysize(dim,numdim-1,0); tablesize>0; tablesize--)
 13.2167 -        litadd(0);
 13.2168 -      /* now initialize the sub-arrays */
 13.2169 -      memset(counteddim,0,sizeof counteddim);
 13.2170 -      initarray(ident,tag,dim,numdim,0,curlit,counteddim,&lastdim,enumroot,&errorfound);
 13.2171 -      /* check the specified array dimensions with the initialler counts */
 13.2172 -      for (idx=0; idx<numdim-1; idx++) {
 13.2173 -        if (dim[idx]==0) {
 13.2174 -          dim[idx]=counteddim[idx];
 13.2175 -        } else if (counteddim[idx]<dim[idx]) {
 13.2176 -          error(52);            /* array is not fully initialized */
 13.2177 -          err++;
 13.2178 -        } else if (counteddim[idx]>dim[idx]) {
 13.2179 -          error(18);            /* initialization data exceeds declared size */
 13.2180 -          err++;
 13.2181 -        } /* if */
 13.2182 -      } /* for */
 13.2183 -      /* after all arrays have been initalized, we know the (major) dimensions
 13.2184 -       * of the array and we can properly adjust the indirection vectors
 13.2185 -       */
 13.2186 -      if (err==0)
 13.2187 -        adjust_indirectiontables(dim,numdim,0,0,curlit,&lastdim,&skipdim);
 13.2188 -      delete_consttable(&lastdim);  /* clear list of minor dimension sizes */
 13.2189 -    } /* if */
 13.2190 -  } /* if */
 13.2191 -
 13.2192 -  if (*size==0)
 13.2193 -    *size=litidx-curlit;        /* number of elements defined */
 13.2194 -}
 13.2195 -
 13.2196 -static cell initarray(int ident,int tag,int dim[],int numdim,int cur,
 13.2197 -                      int startlit,int counteddim[],constvalue *lastdim,
 13.2198 -                      constvalue *enumroot,int *errorfound)
 13.2199 -{
 13.2200 -  cell dsize,totalsize;
 13.2201 -  int idx,abortparse;
 13.2202 -
 13.2203 -  assert(cur>=0 && cur<numdim);
 13.2204 -  assert(startlit>=0);
 13.2205 -  assert(cur+2<=numdim);/* there must be 2 dimensions or more to do */
 13.2206 -  assert(errorfound!=NULL && *errorfound==FALSE);
 13.2207 -  totalsize=0;
 13.2208 -  needtoken('{');
 13.2209 -  for (idx=0,abortparse=FALSE; !abortparse; idx++) {
 13.2210 -    /* In case the major dimension is zero, we need to store the offset
 13.2211 -     * to the newly detected sub-array into the indirection table; i.e.
 13.2212 -     * this table needs to be expanded and updated.
 13.2213 -     * In the current design, the indirection vectors for a multi-dimensional
 13.2214 -     * array are adjusted after parsing all initiallers. Hence, it is only
 13.2215 -     * necessary at this point to reserve space for an extra cell in the
 13.2216 -     * indirection vector.
 13.2217 -     */
 13.2218 -    if (dim[cur]==0) {
 13.2219 -      litinsert(0,startlit);
 13.2220 -    } else if (idx>=dim[cur]) {
 13.2221 -      error(18);            /* initialization data exceeds array size */
 13.2222 -      break;
 13.2223 -    } /* if */
 13.2224 -    if (cur+2<numdim) {
 13.2225 -      dsize=initarray(ident,tag,dim,numdim,cur+1,startlit,counteddim,
 13.2226 -                      lastdim,enumroot,errorfound);
 13.2227 -    } else {
 13.2228 -      dsize=initvector(ident,tag,dim[cur+1],TRUE,enumroot,errorfound);
 13.2229 -      /* The final dimension may be variable length. We need to keep the
 13.2230 -       * lengths of the final dimensions in order to set the indirection
 13.2231 -       * vectors for the next-to-last dimension.
 13.2232 -       */
 13.2233 -      append_constval(lastdim,itoh(idx),dsize,0);
 13.2234 -    } /* if */
 13.2235 -    totalsize+=dsize;
 13.2236 -    if (*errorfound || !matchtoken(','))
 13.2237 -      abortparse=TRUE;
 13.2238 -  } /* for */
 13.2239 -  needtoken('}');
 13.2240 -  assert(counteddim!=NULL);
 13.2241 -  if (counteddim[cur]>0) {
 13.2242 -    if (idx<counteddim[cur])
 13.2243 -      error(52);                /* array is not fully initialized */
 13.2244 -    else if (idx>counteddim[cur])
 13.2245 -      error(18);                /* initialization data exceeds declared size */
 13.2246 -  } /* if */
 13.2247 -  counteddim[cur]=idx;
 13.2248 -
 13.2249 -  return totalsize+dim[cur];    /* size of sub-arrays + indirection vector */
 13.2250 -}
 13.2251 -
 13.2252 -/*  initvector
 13.2253 - *  Initialize a single dimensional array
 13.2254 - */
 13.2255 -static cell initvector(int ident,int tag,cell size,int fillzero,
 13.2256 -                       constvalue *enumroot,int *errorfound)
 13.2257 -{
 13.2258 -  cell prev1=0,prev2=0;
 13.2259 -  int ellips=FALSE,hadtoken=0;
 13.2260 -  int curlit=litidx;
 13.2261 -  int rtag,ctag;
 13.2262 -
 13.2263 -  assert(ident==iARRAY || ident==iREFARRAY);
 13.2264 -  if ((hadtoken=matchtoken('{')) && autozero) {
 13.2265 -    constvalue *enumfield=(enumroot!=NULL) ? enumroot->next : NULL;
 13.2266 -    do {
 13.2267 -      int fieldlit=litidx;
 13.2268 -      int matchbrace,i;
 13.2269 -      if (matchtoken('}')) {    /* to allow for trailing ',' after the initialization */
 13.2270 -        lexpush();
 13.2271 -        break;
 13.2272 -      } /* if */
 13.2273 -      if ((ellips=matchtoken(tELLIPS))!=0)
 13.2274 -        break;
 13.2275 -      /* for enumeration fields, allow another level of braces ("{...}") */
 13.2276 -      matchbrace=0;             /* preset */
 13.2277 -      ellips=0;
 13.2278 -      if (enumfield!=NULL)
 13.2279 -        matchbrace=matchtoken('{');
 13.2280 -      for ( ;; ) {
 13.2281 -        prev2=prev1;
 13.2282 -        prev1=init(ident,&ctag,errorfound);
 13.2283 -        if (!matchbrace)
 13.2284 -          break;
 13.2285 -        if ((ellips=matchtoken(tELLIPS))!=0)
 13.2286 -          break;
 13.2287 -        if (!matchtoken(',')) {
 13.2288 -          needtoken('}');
 13.2289 -          break;
 13.2290 -        } /* for */
 13.2291 -      } /* for */
 13.2292 -      /* if this array is based on an enumeration, fill the "field" up with
 13.2293 -       * zeros, and toggle the tag
 13.2294 -       */
 13.2295 -      if (enumroot!=NULL && enumfield==NULL)
 13.2296 -        error(227);             /* more initiallers than enum fields */
 13.2297 -      rtag=tag;                 /* preset, may be overridden by enum field tag */
 13.2298 -      if (enumfield!=NULL) {
 13.2299 -        cell step;
 13.2300 -        int cmptag=enumfield->index;
 13.2301 -        symbol *symfield=findconst(enumfield->name,&cmptag);
 13.2302 -        if (cmptag>1)
 13.2303 -          error(91,enumfield->name); /* ambiguous constant, needs tag override */
 13.2304 -        assert(symfield!=NULL);
 13.2305 -        assert(fieldlit<litidx);
 13.2306 -        if (litidx-fieldlit>symfield->dim.array.length)
 13.2307 -          error(228);           /* length of initialler exceeds size of the enum field */
 13.2308 -        if (ellips) {
 13.2309 -          step=prev1-prev2;
 13.2310 -        } else {
 13.2311 -          step=0;
 13.2312 -          prev1=0;
 13.2313 -        } /* if */
 13.2314 -        for (i=litidx-fieldlit; i<symfield->dim.array.length; i++) {
 13.2315 -          prev1+=step;
 13.2316 -          litadd(prev1);
 13.2317 -        } /* for */
 13.2318 -        rtag=symfield->x.tags.index;  /* set the expected tag to the index tag */
 13.2319 -        enumfield=enumfield->next;
 13.2320 -      } /* if */
 13.2321 -      if (!matchtag(rtag,ctag,TRUE))
 13.2322 -        error(213);             /* tag mismatch */
 13.2323 -    } while (matchtoken(',')); /* do */
 13.2324 -    needtoken('}');
 13.2325 -  } else {
 13.2326 -    if (hadtoken && !autozero)
 13.2327 -      error(10);
 13.2328 -    init(ident,&ctag,errorfound);
 13.2329 -    if (!matchtag(tag,ctag,TRUE))
 13.2330 -      error(213);               /* tagname mismatch */
 13.2331 -  } /* if */
 13.2332 -  /* fill up the literal queue with a series */
 13.2333 -  if (ellips) {
 13.2334 -    cell step=((litidx-curlit)==1) ? (cell)0 : prev1-prev2;
 13.2335 -    if (size==0 || (litidx-curlit)==0)
 13.2336 -      error(41);                /* invalid ellipsis, array size unknown */
 13.2337 -    else if ((litidx-curlit)==(int)size)
 13.2338 -      error(18);                /* initialisation data exceeds declared size */
 13.2339 -    while ((litidx-curlit)<(int)size) {
 13.2340 -      prev1+=step;
 13.2341 -      litadd(prev1);
 13.2342 -    } /* while */
 13.2343 -  } /* if */
 13.2344 -  if (fillzero && size>0) {
 13.2345 -    while ((litidx-curlit)<(int)size)
 13.2346 -      litadd(0);
 13.2347 -  } /* if */
 13.2348 -  if (size==0) {
 13.2349 -    size=litidx-curlit;                 /* number of elements defined */
 13.2350 -  } else if (litidx-curlit>(int)size) { /* e.g. "myvar[3]={1,2,3,4};" */
 13.2351 -    error(18);                  /* initialisation data exceeds declared size */
 13.2352 -    litidx=(int)size+curlit;    /* avoid overflow in memory moves */
 13.2353 -  } /* if */
 13.2354 -  return size;
 13.2355 -}
 13.2356 -
 13.2357 -/*  init
 13.2358 - *
 13.2359 - *  Evaluate one initializer.
 13.2360 - */
 13.2361 -static cell init(int ident,int *tag,int *errorfound)
 13.2362 -{
 13.2363 -  cell i = 0;
 13.2364 -
 13.2365 -  if (matchtoken(tSTRING)){
 13.2366 -    /* lex() automatically stores strings in the literal table (and
 13.2367 -     * increases "litidx") */
 13.2368 -    if (ident==iVARIABLE) {
 13.2369 -      error(6);         /* must be assigned to an array */
 13.2370 -      litidx=1;         /* reset literal queue */
 13.2371 -    } /* if */
 13.2372 -    *tag=0;
 13.2373 -  } else if (constexpr(&i,tag,NULL)){
 13.2374 -    litadd(i);          /* store expression result in literal table */
 13.2375 -  } else {
 13.2376 -    if (errorfound!=NULL)
 13.2377 -      *errorfound=TRUE;
 13.2378 -  } /* if */
 13.2379 -  return i;
 13.2380 -}
 13.2381 -
 13.2382 -/*  needsub
 13.2383 - *
 13.2384 - *  Get required array size
 13.2385 - */
 13.2386 -static cell needsub(int *tag,constvalue **enumroot)
 13.2387 -{
 13.2388 -  cell val;
 13.2389 -  symbol *sym;
 13.2390 -
 13.2391 -  assert(tag!=NULL);
 13.2392 -  *tag=0;
 13.2393 -  if (enumroot!=NULL)
 13.2394 -    *enumroot=NULL;         /* preset */
 13.2395 -  if (matchtoken(']'))      /* we have already seen "[" */
 13.2396 -    return 0;               /* zero size (like "char msg[]") */
 13.2397 -
 13.2398 -  constexpr(&val,tag,&sym); /* get value (must be constant expression) */
 13.2399 -  if (val<0) {
 13.2400 -    error(9);               /* negative array size is invalid; assumed zero */
 13.2401 -    val=0;
 13.2402 -  } /* if */
 13.2403 -  needtoken(']');
 13.2404 -
 13.2405 -  if (enumroot!=NULL) {
 13.2406 -    /* get the field list for an enumeration */
 13.2407 -    assert(*enumroot==NULL);/* should have been preset */
 13.2408 -    assert(sym==NULL || sym->ident==iCONSTEXPR);
 13.2409 -    if (sym!=NULL && (sym->usage & uENUMROOT)==uENUMROOT) {
 13.2410 -      assert(sym->dim.enumlist!=NULL);
 13.2411 -      *enumroot=sym->dim.enumlist;
 13.2412 -    } /* if */
 13.2413 -  } /* if */
 13.2414 -
 13.2415 -  return val;               /* return array size */
 13.2416 -}
 13.2417 -
 13.2418 -/*  decl_const  - declare a single constant
 13.2419 - *
 13.2420 - */
 13.2421 -static void decl_const(int vclass)
 13.2422 -{
 13.2423 -  char constname[sNAMEMAX+1];
 13.2424 -  cell val;
 13.2425 -  char *str;
 13.2426 -  int tag,exprtag;
 13.2427 -  int symbolline;
 13.2428 -  symbol *sym;
 13.2429 -
 13.2430 -  insert_docstring_separator(); /* see comment in newfunc() */
 13.2431 -  tag=pc_addtag(NULL);
 13.2432 -  if (lex(&val,&str)!=tSYMBOL)  /* read in (new) token */
 13.2433 -    error(20,str);              /* invalid symbol name */
 13.2434 -  symbolline=fline;             /* save line where symbol was found */
 13.2435 -  strcpy(constname,str);        /* save symbol name */
 13.2436 -  needtoken('=');
 13.2437 -  constexpr(&val,&exprtag,NULL);/* get value */
 13.2438 -  needtoken(tTERM);
 13.2439 -  /* add_constant() checks for duplicate definitions */
 13.2440 -  if (!matchtag(tag,exprtag,FALSE)) {
 13.2441 -    /* temporarily reset the line number to where the symbol was defined */
 13.2442 -    int orgfline=fline;
 13.2443 -    fline=symbolline;
 13.2444 -    error(213);                 /* tagname mismatch */
 13.2445 -    fline=orgfline;
 13.2446 -  } /* if */
 13.2447 -  sym=add_constant(constname,val,vclass,tag);
 13.2448 -  if (sym!=NULL)
 13.2449 -    sc_attachdocumentation(sym);/* attach any documenation to the function */
 13.2450 -}
 13.2451 -
 13.2452 -/*  decl_enum   - declare enumerated constants
 13.2453 - *
 13.2454 - */
 13.2455 -static void decl_enum(int vclass)
 13.2456 -{
 13.2457 -  char enumname[sNAMEMAX+1],constname[sNAMEMAX+1];
 13.2458 -  cell val,value,size;
 13.2459 -  char *str;
 13.2460 -  int tag,explicittag;
 13.2461 -  cell increment,multiplier;
 13.2462 -  constvalue *enumroot;
 13.2463 -  symbol *enumsym;
 13.2464 -
 13.2465 -  /* get an explicit tag, if any (we need to remember whether an explicit
 13.2466 -   * tag was passed, even if that explicit tag was "_:", so we cannot call
 13.2467 -   * pc_addtag() here
 13.2468 -   */
 13.2469 -  if (lex(&val,&str)==tLABEL) {
 13.2470 -    tag=pc_addtag(str);
 13.2471 -    explicittag=TRUE;
 13.2472 -  } else {
 13.2473 -    lexpush();
 13.2474 -    tag=0;
 13.2475 -    explicittag=FALSE;
 13.2476 -  } /* if */
 13.2477 -
 13.2478 -  /* get optional enum name (also serves as a tag if no explicit tag was set) */
 13.2479 -  if (lex(&val,&str)==tSYMBOL) {        /* read in (new) token */
 13.2480 -    strcpy(enumname,str);               /* save enum name (last constant) */
 13.2481 -    if (!explicittag)
 13.2482 -      tag=pc_addtag(enumname);
 13.2483 -  } else {
 13.2484 -    lexpush();                          /* analyze again */
 13.2485 -    enumname[0]='\0';
 13.2486 -  } /* if */
 13.2487 -
 13.2488 -  /* get increment and multiplier */
 13.2489 -  increment=1;
 13.2490 -  multiplier=1;
 13.2491 -  if (matchtoken('(')) {
 13.2492 -    if (matchtoken(taADD)) {
 13.2493 -      constexpr(&increment,NULL,NULL);
 13.2494 -    } else if (matchtoken(taMULT)) {
 13.2495 -      constexpr(&multiplier,NULL,NULL);
 13.2496 -    } else if (matchtoken(taSHL)) {
 13.2497 -      constexpr(&val,NULL,NULL);
 13.2498 -      while (val-->0)
 13.2499 -        multiplier*=2;
 13.2500 -    } /* if */
 13.2501 -    needtoken(')');
 13.2502 -  } /* if */
 13.2503 -
 13.2504 -  if (strlen(enumname)>0) {
 13.2505 -    /* already create the root symbol, so the fields can have it as their "parent" */
 13.2506 -    enumsym=add_constant(enumname,0,vclass,tag);
 13.2507 -    if (enumsym!=NULL)
 13.2508 -      enumsym->usage |= uENUMROOT;
 13.2509 -    /* start a new list for the element names */
 13.2510 -    if ((enumroot=(constvalue*)malloc(sizeof(constvalue)))==NULL)
 13.2511 -      error(103);                       /* insufficient memory (fatal error) */
 13.2512 -    memset(enumroot,0,sizeof(constvalue));
 13.2513 -  } else {
 13.2514 -    enumsym=NULL;
 13.2515 -    enumroot=NULL;
 13.2516 -  } /* if */
 13.2517 -
 13.2518 -  needtoken('{');
 13.2519 -  /* go through all constants */
 13.2520 -  value=0;                              /* default starting value */
 13.2521 -  do {
 13.2522 -    int idxtag,fieldtag;
 13.2523 -    symbol *sym;
 13.2524 -    if (matchtoken('}')) {              /* quick exit if '}' follows ',' */
 13.2525 -      lexpush();
 13.2526 -      break;
 13.2527 -    } /* if */
 13.2528 -    idxtag=pc_addtag(NULL);             /* optional explicit item tag */
 13.2529 -    if (needtoken(tSYMBOL)) {           /* read in (new) token */
 13.2530 -      tokeninfo(&val,&str);             /* get the information */
 13.2531 -      strcpy(constname,str);            /* save symbol name */
 13.2532 -    } else {
 13.2533 -      constname[0]='\0';
 13.2534 -    } /* if */
 13.2535 -    size=increment;                     /* default increment of 'val' */
 13.2536 -    fieldtag=0;                         /* default field tag */
 13.2537 -    if (matchtoken('[')) {
 13.2538 -      constexpr(&size,&fieldtag,NULL);  /* get size */
 13.2539 -      needtoken(']');
 13.2540 -    } /* if */
 13.2541 -    if (matchtoken('='))
 13.2542 -      constexpr(&value,NULL,NULL);      /* get value */
 13.2543 -    /* add_constant() checks whether a variable (global or local) or
 13.2544 -     * a constant with the same name already exists
 13.2545 -     */
 13.2546 -    sym=add_constant(constname,value,vclass,tag);
 13.2547 -    if (sym==NULL)
 13.2548 -      continue;                         /* error message already given */
 13.2549 -    /* set the item tag and the item size, for use in indexing arrays */
 13.2550 -    sym->x.tags.index=idxtag;
 13.2551 -    sym->x.tags.field=fieldtag;
 13.2552 -    sym->dim.array.length=size;
 13.2553 -    sym->dim.array.level=0;
 13.2554 -    sym->parent=enumsym;
 13.2555 -    /* add the constant to a separate list as well */
 13.2556 -    if (enumroot!=NULL) {
 13.2557 -      sym->usage |= uENUMFIELD;
 13.2558 -      append_constval(enumroot,constname,value,tag);
 13.2559 -    } /* if */
 13.2560 -    if (multiplier==1)
 13.2561 -      value+=size;
 13.2562 -    else
 13.2563 -      value*=size*multiplier;
 13.2564 -  } while (matchtoken(','));
 13.2565 -  needtoken('}');       /* terminates the constant list */
 13.2566 -  matchtoken(';');      /* eat an optional ; */
 13.2567 -
 13.2568 -  /* set the enum name to the "next" value (typically the last value plus one) */
 13.2569 -  if (enumsym!=NULL) {
 13.2570 -    assert((enumsym->usage & uENUMROOT)!=0);
 13.2571 -    enumsym->addr=value;
 13.2572 -    /* assign the constant list */
 13.2573 -    assert(enumroot!=NULL);
 13.2574 -    enumsym->dim.enumlist=enumroot;
 13.2575 -    sc_attachdocumentation(enumsym);  /* attach any documenation to the enumeration */
 13.2576 -  } /* if */
 13.2577 -}
 13.2578 -
 13.2579 -static int getstates(const char *funcname)
 13.2580 -{
 13.2581 -  char fsaname[sNAMEMAX+1],statename[sNAMEMAX+1];
 13.2582 -  cell val;
 13.2583 -  char *str;
 13.2584 -  constvalue *automaton;
 13.2585 -  constvalue *state;
 13.2586 -  int fsa,islabel;
 13.2587 -  int *list;
 13.2588 -  int count,listsize,state_id;
 13.2589 -
 13.2590 -  if (!matchtoken('<'))
 13.2591 -    return 0;
 13.2592 -  if (matchtoken('>'))
 13.2593 -    return -1;          /* special construct: all other states (fall-back) */
 13.2594 -
 13.2595 -  count=0;
 13.2596 -  listsize=0;
 13.2597 -  list=NULL;
 13.2598 -  fsa=-1;
 13.2599 -
 13.2600 -  do {
 13.2601 -    if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
 13.2602 -      break;
 13.2603 -    tokeninfo(&val,&str);
 13.2604 -    assert(strlen(str)<sizeof fsaname);
 13.2605 -    strcpy(fsaname,str);  /* assume this is the name of the automaton */
 13.2606 -    if (islabel || matchtoken(':')) {
 13.2607 -      /* token is an automaton name, add the name and get a new token */
 13.2608 -      if (!needtoken(tSYMBOL))
 13.2609 -        break;
 13.2610 -      tokeninfo(&val,&str);
 13.2611 -      assert(strlen(str)<sizeof statename);
 13.2612 -      strcpy(statename,str);
 13.2613 -    } else {
 13.2614 -      /* the token was the state name (part of an anynymous automaton) */
 13.2615 -      assert(strlen(fsaname)<sizeof statename);
 13.2616 -      strcpy(statename,fsaname);
 13.2617 -      fsaname[0]='\0';
 13.2618 -    } /* if */
 13.2619 -    if (fsa<0 || fsaname[0]!='\0') {
 13.2620 -      automaton=automaton_add(fsaname);
 13.2621 -      assert(automaton!=NULL);
 13.2622 -      if (fsa>=0 && automaton->index!=fsa)
 13.2623 -        error(83,funcname); /* multiple automatons for a single function/variable */
 13.2624 -      fsa=automaton->index;
 13.2625 -    } /* if */
 13.2626 -    state=state_add(statename,fsa);
 13.2627 -    /* add this state to the state combination list (it will be attached to the
 13.2628 -     * automaton later) */
 13.2629 -    state_buildlist(&list,&listsize,&count,(int)state->value);
 13.2630 -  } while (matchtoken(','));
 13.2631 -  needtoken('>');
 13.2632 -
 13.2633 -  if (count>0) {
 13.2634 -    assert(automaton!=NULL);
 13.2635 -    assert(fsa>=0);
 13.2636 -    state_id=state_addlist(list,count,fsa);
 13.2637 -    assert(state_id>0);
 13.2638 -  } else {
 13.2639 -    /* error is already given */
 13.2640 -    state_id=0;
 13.2641 -  } /* if */
 13.2642 -  if (list!=NULL)
 13.2643 -    free(list);
 13.2644 -
 13.2645 -  return state_id;
 13.2646 -}
 13.2647 -
 13.2648 -static void attachstatelist(symbol *sym, int state_id)
 13.2649 -{
 13.2650 -  assert(sym!=NULL);
 13.2651 -  if ((sym->usage & uDEFINE)!=0 && (sym->states==NULL || state_id==0))
 13.2652 -    error(21,sym->name); /* function already defined, either without states or the current definition has no states */
 13.2653 -
 13.2654 -  if (state_id!=0) {
 13.2655 -    /* add the state list id */
 13.2656 -    constvalue *stateptr;
 13.2657 -    if (sym->states==NULL) {
 13.2658 -      if ((sym->states=(constvalue*)malloc(sizeof(constvalue)))==NULL)
 13.2659 -        error(103);             /* insufficient memory (fatal error) */
 13.2660 -      memset(sym->states,0,sizeof(constvalue));
 13.2661 -    } /* if */
 13.2662 -    /* see whether the id already exists (add new state only if it does not
 13.2663 -     * yet exist
 13.2664 -     */
 13.2665 -    assert(sym->states!=NULL);
 13.2666 -    for (stateptr=sym->states->next; stateptr!=NULL && stateptr->index!=state_id; stateptr=stateptr->next)
 13.2667 -      /* nothing */;
 13.2668 -    assert(state_id<=SHRT_MAX);
 13.2669 -    if (stateptr==NULL)
 13.2670 -      append_constval(sym->states,"",code_idx,(short)state_id);
 13.2671 -    else if (stateptr->value==0)
 13.2672 -      stateptr->value=code_idx;
 13.2673 -    else
 13.2674 -      error(84,sym->name);
 13.2675 -    /* also check for another conflicting situation: a fallback function
 13.2676 -     * without any states
 13.2677 -     */
 13.2678 -    if (state_id==-1 && sc_status!=statFIRST) {
 13.2679 -      /* in the second round, all states should have been accumulated */
 13.2680 -      assert(sym->states!=NULL);
 13.2681 -      for (stateptr=sym->states->next; stateptr!=NULL && stateptr->index==-1; stateptr=stateptr->next)
 13.2682 -        /* nothing */;
 13.2683 -      if (stateptr==NULL)
 13.2684 -        error(85,sym->name);      /* no states are defined for this function */
 13.2685 -    } /* if */
 13.2686 -  } /* if */
 13.2687 -}
 13.2688 -
 13.2689 -/*
 13.2690 - *  Finds a function in the global symbol table or creates a new entry.
 13.2691 - *  It does some basic processing and error checking.
 13.2692 - */
 13.2693 -SC_FUNC symbol *fetchfunc(char *name,int tag)
 13.2694 -{
 13.2695 -  symbol *sym;
 13.2696 -
 13.2697 -  if ((sym=findglb(name,sGLOBAL))!=0) {   /* already in symbol table? */
 13.2698 -    if (sym->ident!=iFUNCTN) {
 13.2699 -      error(21,name);                     /* yes, but not as a function */
 13.2700 -      return NULL;                        /* make sure the old symbol is not damaged */
 13.2701 -    } else if ((sym->usage & uNATIVE)!=0) {
 13.2702 -      error(21,name);                     /* yes, and it is a native */
 13.2703 -    } /* if */
 13.2704 -    assert(sym->vclass==sGLOBAL);
 13.2705 -    if ((sym->usage & uPROTOTYPED)!=0 && sym->tag!=tag)
 13.2706 -      error(25);                          /* mismatch from earlier prototype */
 13.2707 -    if ((sym->usage & uDEFINE)==0) {
 13.2708 -      /* as long as the function stays undefined, update the address and the tag */
 13.2709 -      if (sym->states==NULL)
 13.2710 -        sym->addr=code_idx;
 13.2711 -      sym->tag=tag;
 13.2712 -    } /* if */
 13.2713 -  } else {
 13.2714 -    /* don't set the "uDEFINE" flag; it may be a prototype */
 13.2715 -    sym=addsym(name,code_idx,iFUNCTN,sGLOBAL,tag,0);
 13.2716 -    assert(sym!=NULL);          /* fatal error 103 must be given on error */
 13.2717 -    /* assume no arguments */
 13.2718 -    sym->dim.arglist=(arginfo*)malloc(1*sizeof(arginfo));
 13.2719 -    sym->dim.arglist[0].ident=0;
 13.2720 -    /* set library ID to NULL (only for native functions) */
 13.2721 -    sym->x.lib=NULL;
 13.2722 -    /* set the required stack size to zero (only for non-native functions) */
 13.2723 -    sym->x.stacksize=1;         /* 1 for PROC opcode */
 13.2724 -  } /* if */
 13.2725 -  if (pc_depricate!=NULL) {
 13.2726 -    assert(sym!=NULL);
 13.2727 -    sym->flags|=flgDEPRICATED;
 13.2728 -    if (sc_status==statWRITE) {
 13.2729 -      if (sym->documentation!=NULL) {
 13.2730 -        free(sym->documentation);
 13.2731 -        sym->documentation=NULL;
 13.2732 -      } /* if */
 13.2733 -      sym->documentation=pc_depricate;
 13.2734 -    } else {
 13.2735 -      free(pc_depricate);
 13.2736 -    } /* if */
 13.2737 -    pc_depricate=NULL;
 13.2738 -  } /* if */
 13.2739 -
 13.2740 -  return sym;
 13.2741 -}
 13.2742 -
 13.2743 -/* This routine adds symbolic information for each argument.
 13.2744 - */
 13.2745 -static void define_args(void)
 13.2746 -{
 13.2747 -  symbol *sym;
 13.2748 -
 13.2749 -  /* At this point, no local variables have been declared. All
 13.2750 -   * local symbols are function arguments.
 13.2751 -   */
 13.2752 -  sym=loctab.next;
 13.2753 -  while (sym!=NULL) {
 13.2754 -    assert(sym->ident!=iLABEL);
 13.2755 -    assert(sym->vclass==sLOCAL);
 13.2756 -    markexpr(sLDECL,sym->name,sym->addr); /* mark for better optimization */
 13.2757 -    sym=sym->next;
 13.2758 -  } /* while */
 13.2759 -}
 13.2760 -
 13.2761 -static int operatorname(char *name)
 13.2762 -{
 13.2763 -  int opertok;
 13.2764 -  char *str;
 13.2765 -  cell val;
 13.2766 -
 13.2767 -  assert(name!=NULL);
 13.2768 -
 13.2769 -  /* check the operator */
 13.2770 -  opertok=lex(&val,&str);
 13.2771 -  switch (opertok) {
 13.2772 -  case '+':
 13.2773 -  case '-':
 13.2774 -  case '*':
 13.2775 -  case '/':
 13.2776 -  case '%':
 13.2777 -  case '>':
 13.2778 -  case '<':
 13.2779 -  case '!':
 13.2780 -  case '~':
 13.2781 -  case '=':
 13.2782 -    name[0]=(char)opertok;
 13.2783 -    name[1]='\0';
 13.2784 -    break;
 13.2785 -  case tINC:
 13.2786 -    strcpy(name,"++");
 13.2787 -    break;
 13.2788 -  case tDEC:
 13.2789 -    strcpy(name,"--");
 13.2790 -    break;
 13.2791 -  case tlEQ:
 13.2792 -    strcpy(name,"==");
 13.2793 -    break;
 13.2794 -  case tlNE:
 13.2795 -    strcpy(name,"!=");
 13.2796 -    break;
 13.2797 -  case tlLE:
 13.2798 -    strcpy(name,"<=");
 13.2799 -    break;
 13.2800 -  case tlGE:
 13.2801 -    strcpy(name,">=");
 13.2802 -    break;
 13.2803 -  default:
 13.2804 -    name[0]='\0';
 13.2805 -    error(7);           /* operator cannot be redefined (or bad operator name) */
 13.2806 -    return 0;
 13.2807 -  } /* switch */
 13.2808 -
 13.2809 -  return opertok;
 13.2810 -}
 13.2811 -
 13.2812 -static int operatoradjust(int opertok,symbol *sym,char *opername,int resulttag)
 13.2813 -{
 13.2814 -  int tags[2]={0,0};
 13.2815 -  int count=0;
 13.2816 -  arginfo *arg;
 13.2817 -  char tmpname[sNAMEMAX+1];
 13.2818 -  symbol *oldsym;
 13.2819 -
 13.2820 -  if (opertok==0)
 13.2821 -    return TRUE;
 13.2822 -
 13.2823 -  assert(sym!=NULL && sym->ident==iFUNCTN && sym->dim.arglist!=NULL);
 13.2824 -  /* count arguments and save (first two) tags */
 13.2825 -  while (arg=&sym->dim.arglist[count], arg->ident!=0) {
 13.2826 -    if (count<2) {
 13.2827 -      if (arg->numtags>1)
 13.2828 -        error(65,count+1);  /* function argument may only have a single tag */
 13.2829 -      else if (arg->numtags==1)
 13.2830 -        tags[count]=arg->tags[0];
 13.2831 -    } /* if */
 13.2832 -    if (opertok=='~' && count==0) {
 13.2833 -      if (arg->ident!=iREFARRAY)
 13.2834 -        error(73,arg->name);/* must be an array argument */
 13.2835 -    } else {
 13.2836 -      if (arg->ident!=iVARIABLE)
 13.2837 -        error(66,arg->name);/* must be non-reference argument */
 13.2838 -    } /* if */
 13.2839 -    if (arg->hasdefault)
 13.2840 -      error(59,arg->name);  /* arguments of an operator may not have a default value */
 13.2841 -    count++;
 13.2842 -  } /* while */
 13.2843 -
 13.2844 -  /* for '!', '++' and '--', count must be 1
 13.2845 -   * for '-', count may be 1 or 2
 13.2846 -   * for '=', count must be 1, and the resulttag is also important
 13.2847 -   * for all other (binary) operators and the special '~' operator, count must be 2
 13.2848 -   */
 13.2849 -  switch (opertok) {
 13.2850 -  case '!':
 13.2851 -  case '=':
 13.2852 -  case tINC:
 13.2853 -  case tDEC:
 13.2854 -    if (count!=1)
 13.2855 -      error(62);      /* number or placement of the operands does not fit the operator */
 13.2856 -    break;
 13.2857 -  case '-':
 13.2858 -    if (count!=1 && count!=2)
 13.2859 -      error(62);      /* number or placement of the operands does not fit the operator */
 13.2860 -    break;
 13.2861 -  default:
 13.2862 -    if (count!=2)
 13.2863 -      error(62);      /* number or placement of the operands does not fit the operator */
 13.2864 -  } /* switch */
 13.2865 -
 13.2866 -  if (tags[0]==0 && (opertok!='=' && tags[1]==0 || opertok=='=' && resulttag==0))
 13.2867 -    error(64);        /* cannot change predefined operators */
 13.2868 -
 13.2869 -  /* change the operator name */
 13.2870 -  assert(strlen(opername)>0);
 13.2871 -  operator_symname(tmpname,opername,tags[0],tags[1],count,resulttag);
 13.2872 -  if ((oldsym=findglb(tmpname,sGLOBAL))!=NULL) {
 13.2873 -    int i;
 13.2874 -    if ((oldsym->usage & uDEFINE)!=0) {
 13.2875 -      char errname[2*sNAMEMAX+16];
 13.2876 -      funcdisplayname(errname,tmpname);
 13.2877 -      error(21,errname);        /* symbol already defined */
 13.2878 -    } /* if */
 13.2879 -    sym->usage|=oldsym->usage;  /* copy flags from the previous definition */
 13.2880 -    for (i=0; i<oldsym->numrefers; i++)
 13.2881 -      if (oldsym->refer[i]!=NULL)
 13.2882 -        refer_symbol(sym,oldsym->refer[i]);
 13.2883 -    delete_symbol(&glbtab,oldsym);
 13.2884 -  } /* if */
 13.2885 -  strcpy(sym->name,tmpname);
 13.2886 -  sym->hash=namehash(sym->name);/* calculate new hash */
 13.2887 -
 13.2888 -  /* operators should return a value, except the '~' operator */
 13.2889 -  if (opertok!='~')
 13.2890 -    sym->usage |= uRETVALUE;
 13.2891 -
 13.2892 -  return TRUE;
 13.2893 -}
 13.2894 -
 13.2895 -static int check_operatortag(int opertok,int resulttag,char *opername)
 13.2896 -{
 13.2897 -  assert(opername!=NULL && strlen(opername)>0);
 13.2898 -  switch (opertok) {
 13.2899 -  case '!':
 13.2900 -  case '<':
 13.2901 -  case '>':
 13.2902 -  case tlEQ:
 13.2903 -  case tlNE:
 13.2904 -  case tlLE:
 13.2905 -  case tlGE:
 13.2906 -    if (resulttag!=pc_addtag("bool")) {
 13.2907 -      error(63,opername,"bool:"); /* operator X requires a "bool:" result tag */
 13.2908 -      return FALSE;
 13.2909 -    } /* if */
 13.2910 -    break;
 13.2911 -  case '~':
 13.2912 -    if (resulttag!=0) {
 13.2913 -      error(63,opername,"_:");    /* operator "~" requires a "_:" result tag */
 13.2914 -      return FALSE;
 13.2915 -    } /* if */
 13.2916 -    break;
 13.2917 -  } /* switch */
 13.2918 -  return TRUE;
 13.2919 -}
 13.2920 -
 13.2921 -static char *tag2str(char *dest,int tag)
 13.2922 -{
 13.2923 -  tag &= TAGMASK;
 13.2924 -  assert(tag>=0);
 13.2925 -  sprintf(dest,"0%x",tag);
 13.2926 -  return isdigit(dest[1]) ? &dest[1] : dest;
 13.2927 -}
 13.2928 -
 13.2929 -SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag)
 13.2930 -{
 13.2931 -  char tagstr1[10], tagstr2[10];
 13.2932 -  int opertok;
 13.2933 -
 13.2934 -  assert(numtags>=1 && numtags<=2);
 13.2935 -  opertok= (opername[1]=='\0') ? opername[0] : 0;
 13.2936 -  if (opertok=='=')
 13.2937 -    sprintf(symname,"%s%s%s",tag2str(tagstr1,resulttag),opername,tag2str(tagstr2,tag1));
 13.2938 -  else if (numtags==1 || opertok=='~')
 13.2939 -    sprintf(symname,"%s%s",opername,tag2str(tagstr1,tag1));
 13.2940 -  else
 13.2941 -    sprintf(symname,"%s%s%s",tag2str(tagstr1,tag1),opername,tag2str(tagstr2,tag2));
 13.2942 -  return symname;
 13.2943 -}
 13.2944 -
 13.2945 -static int parse_funcname(char *fname,int *tag1,int *tag2,char *opname)
 13.2946 -{
 13.2947 -  char *ptr,*name;
 13.2948 -  int unary;
 13.2949 -
 13.2950 -  /* tags are only positive, so if the function name starts with a '-',
 13.2951 -   * the operator is an unary '-' or '--' operator.
 13.2952 -   */
 13.2953 -  if (*fname=='-') {
 13.2954 -    *tag1=0;
 13.2955 -    unary=TRUE;
 13.2956 -    ptr=fname;
 13.2957 -  } else {
 13.2958 -    *tag1=(int)strtol(fname,&ptr,16);
 13.2959 -    unary= ptr==fname;  /* unary operator if it doesn't start with a tag name */
 13.2960 -  } /* if */
 13.2961 -  assert(!unary || *tag1==0);
 13.2962 -  assert(*ptr!='\0');
 13.2963 -  for (name=opname; !isdigit(*ptr); )
 13.2964 -    *name++ = *ptr++;
 13.2965 -  *name='\0';
 13.2966 -  *tag2=(int)strtol(ptr,NULL,16);
 13.2967 -  return unary;
 13.2968 -}
 13.2969 -
 13.2970 -static constvalue *find_tag_byval(int tag)
 13.2971 -{
 13.2972 -  constvalue *tagsym;
 13.2973 -  tagsym=find_constval_byval(&tagname_tab,tag & ~PUBLICTAG);
 13.2974 -  if (tagsym==NULL)
 13.2975 -    tagsym=find_constval_byval(&tagname_tab,tag | PUBLICTAG);
 13.2976 -  return tagsym;
 13.2977 -}
 13.2978 -
 13.2979 -SC_FUNC char *funcdisplayname(char *dest,char *funcname)
 13.2980 -{
 13.2981 -  int tags[2];
 13.2982 -  char opname[10];
 13.2983 -  constvalue *tagsym[2];
 13.2984 -  int unary;
 13.2985 -
 13.2986 -  if (isalpha(*funcname) || *funcname=='_' || *funcname==PUBLIC_CHAR || *funcname=='\0') {
 13.2987 -    if (dest!=funcname)
 13.2988 -      strcpy(dest,funcname);
 13.2989 -    return dest;
 13.2990 -  } /* if */
 13.2991 -
 13.2992 -  unary=parse_funcname(funcname,&tags[0],&tags[1],opname);
 13.2993 -  tagsym[1]=find_tag_byval(tags[1]);
 13.2994 -  assert(tagsym[1]!=NULL);
 13.2995 -  if (unary) {
 13.2996 -    sprintf(dest,"operator%s(%s:)",opname,tagsym[1]->name);
 13.2997 -  } else {
 13.2998 -    tagsym[0]=find_tag_byval(tags[0]);
 13.2999 -    assert(tagsym[0]!=NULL);
 13.3000 -    /* special case: the assignment operator has the return value as the 2nd tag */
 13.3001 -    if (opname[0]=='=' && opname[1]=='\0')
 13.3002 -      sprintf(dest,"%s:operator%s(%s:)",tagsym[0]->name,opname,tagsym[1]->name);
 13.3003 -    else
 13.3004 -      sprintf(dest,"operator%s(%s:,%s:)",opname,tagsym[0]->name,tagsym[1]->name);
 13.3005 -  } /* if */
 13.3006 -  return dest;
 13.3007 -}
 13.3008 -
 13.3009 -static void funcstub(int fnative)
 13.3010 -{
 13.3011 -  int tok,tag,fpublic;
 13.3012 -  char *str;
 13.3013 -  cell val,size;
 13.3014 -  char symbolname[sNAMEMAX+1];
 13.3015 -  int idxtag[sDIMEN_MAX];
 13.3016 -  int dim[sDIMEN_MAX];
 13.3017 -  int numdim;
 13.3018 -  symbol *sym,*sub;
 13.3019 -  int opertok;
 13.3020 -
 13.3021 -  opertok=0;
 13.3022 -  lastst=0;
 13.3023 -  litidx=0;                     /* clear the literal pool */
 13.3024 -  assert(loctab.next==NULL);    /* local symbol table should be empty */
 13.3025 -
 13.3026 -  tag=pc_addtag(NULL);			/* get the tag of the return value */
 13.3027 -  numdim=0;
 13.3028 -  while (matchtoken('[')) {
 13.3029 -    /* the function returns an array, get this tag for the index and the array
 13.3030 -     * dimensions
 13.3031 -     */
 13.3032 -    if (numdim == sDIMEN_MAX) {
 13.3033 -      error(53);                /* exceeding maximum number of dimensions */
 13.3034 -      return;
 13.3035 -    } /* if */
 13.3036 -    size=needsub(&idxtag[numdim],NULL); /* get size; size==0 for "var[]" */
 13.3037 -    if (size==0)
 13.3038 -      error(9);                 /* invalid array size */
 13.3039 -    #if INT_MAX < LONG_MAX
 13.3040 -      if (size > INT_MAX)
 13.3041 -        error(105);             /* overflow, exceeding capacity */
 13.3042 -    #endif
 13.3043 -    dim[numdim++]=(int)size;
 13.3044 -  } /* while */
 13.3045 -
 13.3046 -  tok=lex(&val,&str);
 13.3047 -  fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR);
 13.3048 -  if (fnative) {
 13.3049 -    if (fpublic || tok==tSTOCK || tok==tSTATIC || tok==tSYMBOL && *str==PUBLIC_CHAR)
 13.3050 -      error(42);                /* invalid combination of class specifiers */
 13.3051 -  } else {
 13.3052 -    if (tok==tPUBLIC || tok==tSTOCK || tok==tSTATIC)
 13.3053 -      tok=lex(&val,&str);
 13.3054 -  } /* if */
 13.3055 -
 13.3056 -  if (tok==tOPERATOR) {
 13.3057 -    opertok=operatorname(symbolname);
 13.3058 -    if (opertok==0)
 13.3059 -      return;                   /* error message already given */
 13.3060 -    check_operatortag(opertok,tag,symbolname);
 13.3061 -  } else {
 13.3062 -    if (tok!=tSYMBOL && freading) {
 13.3063 -      error(10);                /* illegal function or declaration */
 13.3064 -      return;
 13.3065 -    } /* if */
 13.3066 -    strcpy(symbolname,str);
 13.3067 -  } /* if */
 13.3068 -  needtoken('(');               /* only functions may be native/forward */
 13.3069 -
 13.3070 -  sym=fetchfunc(symbolname,tag);/* get a pointer to the function entry */
 13.3071 -  if (sym==NULL)
 13.3072 -    return;
 13.3073 -  if (fnative) {
 13.3074 -    sym->usage=(char)(uNATIVE | uRETVALUE | uDEFINE | (sym->usage & uPROTOTYPED));
 13.3075 -    sym->x.lib=curlibrary;
 13.3076 -  } else if (fpublic) {
 13.3077 -    sym->usage|=uPUBLIC;
 13.3078 -  } /* if */
 13.3079 -  sym->usage|=uFORWARD;
 13.3080 -
 13.3081 -  declargs(sym,FALSE);
 13.3082 -  /* "declargs()" found the ")" */
 13.3083 -  sc_attachdocumentation(sym);  /* attach any documenation to the function */
 13.3084 -  if (!operatoradjust(opertok,sym,symbolname,tag))
 13.3085 -    sym->usage &= ~uDEFINE;
 13.3086 -
 13.3087 -  if (getstates(symbolname)!=0) {
 13.3088 -    if (fnative || opertok!=0)
 13.3089 -      error(82);                /* native functions and operators may not have states */
 13.3090 -    else
 13.3091 -      error(231);               /* ignoring state specifications on forward declarations */
 13.3092 -  } /* if */
 13.3093 -
 13.3094 -  /* for a native operator, also need to specify an "exported" function name;
 13.3095 -   * for a native function, this is optional
 13.3096 -   */
 13.3097 -  if (fnative) {
 13.3098 -    if (opertok!=0) {
 13.3099 -      needtoken('=');
 13.3100 -      lexpush();        /* push back, for matchtoken() to retrieve again */
 13.3101 -    } /* if */
 13.3102 -    if (matchtoken('=')) {
 13.3103 -      /* allow number or symbol */
 13.3104 -      if (matchtoken(tSYMBOL)) {
 13.3105 -        tokeninfo(&val,&str);
 13.3106 -        insert_alias(sym->name,str);
 13.3107 -      } else {
 13.3108 -        constexpr(&val,NULL,NULL);
 13.3109 -        sym->addr=val;
 13.3110 -        /* At the moment, I have assumed that this syntax is only valid if
 13.3111 -         * val < 0. To properly mix "normal" native functions and indexed
 13.3112 -         * native functions, one should use negative indices anyway.
 13.3113 -         * Special code for a negative index in sym->addr exists in SC4.C
 13.3114 -         * (ffcall()) and in SC6.C (the loops for counting the number of native
 13.3115 -         * variables and for writing them).
 13.3116 -         */
 13.3117 -      } /* if */
 13.3118 -    } /* if */
 13.3119 -  } /* if */
 13.3120 -  needtoken(tTERM);
 13.3121 -
 13.3122 -  /* attach the array to the function symbol */
 13.3123 -  if (numdim>0) {
 13.3124 -    assert(sym!=NULL);
 13.3125 -    sub=addvariable(symbolname,0,iARRAY,sGLOBAL,tag,dim,numdim,idxtag);
 13.3126 -    sub->parent=sym;
 13.3127 -  } /* if */
 13.3128 -
 13.3129 -  litidx=0;                     /* clear the literal pool */
 13.3130 -  delete_symbols(&loctab,0,TRUE,TRUE);/* clear local variables queue */
 13.3131 -}
 13.3132 -
 13.3133 -/*  newfunc    - begin a function
 13.3134 - *
 13.3135 - *  This routine is called from "parse" and tries to make a function
 13.3136 - *  out of the following text
 13.3137 - *
 13.3138 - *  Global references: funcstatus,lastst,litidx
 13.3139 - *                     rettype  (altered)
 13.3140 - *                     curfunc  (altered)
 13.3141 - *                     declared (altered)
 13.3142 - *                     glb_declared (altered)
 13.3143 - *                     sc_alignnext (altered)
 13.3144 - */
 13.3145 -static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stock)
 13.3146 -{
 13.3147 -  symbol *sym;
 13.3148 -  int argcnt,tok,tag,funcline;
 13.3149 -  int opertok,opererror;
 13.3150 -  char symbolname[sNAMEMAX+1];
 13.3151 -  char *str;
 13.3152 -  cell val,cidx,glbdecl;
 13.3153 -  short filenum;
 13.3154 -  int state_id;
 13.3155 -
 13.3156 -  assert(litidx==0);    /* literal queue should be empty */
 13.3157 -  litidx=0;             /* clear the literal pool (should already be empty) */
 13.3158 -  opertok=0;
 13.3159 -  lastst=0;             /* no statement yet */
 13.3160 -  cidx=0;               /* just to avoid compiler warnings */
 13.3161 -  glbdecl=0;
 13.3162 -  assert(loctab.next==NULL);    /* local symbol table should be empty */
 13.3163 -  filenum=fcurrent;     /* save file number at the start of the declaration */
 13.3164 -
 13.3165 -  if (firstname!=NULL) {
 13.3166 -    assert(strlen(firstname)<=sNAMEMAX);
 13.3167 -    strcpy(symbolname,firstname);       /* save symbol name */
 13.3168 -    tag=firsttag;
 13.3169 -  } else {
 13.3170 -    tag= (firsttag>=0) ? firsttag : pc_addtag(NULL);
 13.3171 -    tok=lex(&val,&str);
 13.3172 -    assert(!fpublic);
 13.3173 -    if (tok==tNATIVE || tok==tPUBLIC && stock)
 13.3174 -      error(42);                /* invalid combination of class specifiers */
 13.3175 -    if (tok==tOPERATOR) {
 13.3176 -      opertok=operatorname(symbolname);
 13.3177 -      if (opertok==0)
 13.3178 -        return TRUE;            /* error message already given */
 13.3179 -      check_operatortag(opertok,tag,symbolname);
 13.3180 -    } else {
 13.3181 -      if (tok!=tSYMBOL && freading) {
 13.3182 -        error(20,str);          /* invalid symbol name */
 13.3183 -        return FALSE;
 13.3184 -      } /* if */
 13.3185 -      assert(strlen(str)<=sNAMEMAX);
 13.3186 -      strcpy(symbolname,str);
 13.3187 -    } /* if */
 13.3188 -  } /* if */
 13.3189 -  /* check whether this is a function or a variable declaration */
 13.3190 -  if (!matchtoken('('))
 13.3191 -    return FALSE;
 13.3192 -  /* so it is a function, proceed */
 13.3193 -  funcline=fline;               /* save line at which the function is defined */
 13.3194 -  if (symbolname[0]==PUBLIC_CHAR) {
 13.3195 -    fpublic=TRUE;               /* implicitly public function */
 13.3196 -    if (stock)
 13.3197 -      error(42);                /* invalid combination of class specifiers */
 13.3198 -  } /* if */
 13.3199 -  sym=fetchfunc(symbolname,tag);/* get a pointer to the function entry */
 13.3200 -  if (sym==NULL || (sym->usage & uNATIVE)!=0)
 13.3201 -    return TRUE;                /* it was recognized as a function declaration, but not as a valid one */
 13.3202 -  if (fpublic)
 13.3203 -    sym->usage|=uPUBLIC;
 13.3204 -  if (fstatic)
 13.3205 -    sym->fnumber=filenum;
 13.3206 -  /* if the function was used before being declared, and it has a tag for the
 13.3207 -   * result, add a third pass (as second "skimming" parse) because the function
 13.3208 -   * result may have been used with user-defined operators, which have now
 13.3209 -   * been incorrectly flagged (as the return tag was unknown at the time of
 13.3210 -   * the call)
 13.3211 -   */
 13.3212 -  if ((sym->usage & (uPROTOTYPED | uREAD))==uREAD && sym->tag!=0) {
 13.3213 -    int curstatus=sc_status;
 13.3214 -    sc_status=statWRITE;  /* temporarily set status to WRITE, so the warning isn't blocked */
 13.3215 -    error(208);
 13.3216 -    sc_status=curstatus;
 13.3217 -    sc_reparse=TRUE;      /* must add another pass to "initial scan" phase */
 13.3218 -  } /* if */
 13.3219 -  /* we want public functions to be explicitly prototyped, as they are called
 13.3220 -   * from the outside
 13.3221 -   */
 13.3222 -  if (fpublic && (sym->usage & uFORWARD)==0)
 13.3223 -    error(235,symbolname);
 13.3224 -  /* declare all arguments */
 13.3225 -  argcnt=declargs(sym,TRUE);
 13.3226 -  opererror=!operatoradjust(opertok,sym,symbolname,tag);
 13.3227 -  if (strcmp(symbolname,uMAINFUNC)==0 || strcmp(symbolname,uENTRYFUNC)==0) {
 13.3228 -    if (argcnt>0)
 13.3229 -      error(5);         /* "main()" and "entry()" functions may not have any arguments */
 13.3230 -    sym->usage|=uREAD;  /* "main()" is the program's entry point: always used */
 13.3231 -  } /* if */
 13.3232 -  state_id=getstates(symbolname);
 13.3233 -  if (state_id>0 && (opertok!=0 || strcmp(symbolname,uMAINFUNC)==0))
 13.3234 -    error(82);          /* operators may not have states, main() may neither */
 13.3235 -  attachstatelist(sym,state_id);
 13.3236 -  /* "declargs()" found the ")"; if a ";" appears after this, it was a
 13.3237 -   * prototype */
 13.3238 -  if (matchtoken(';')) {
 13.3239 -    sym->usage|=uFORWARD;
 13.3240 -    if (!sc_needsemicolon)
 13.3241 -      error(218);       /* old style prototypes used with optional semicolumns */
 13.3242 -    delete_symbols(&loctab,0,TRUE,TRUE);  /* prototype is done; forget everything */
 13.3243 -    return TRUE;
 13.3244 -  } /* if */
 13.3245 -  /* so it is not a prototype, proceed */
 13.3246 -  /* if this is a function that is not referred to (this can only be detected
 13.3247 -   * in the second stage), shut code generation off */
 13.3248 -  if (sc_status==statWRITE && (sym->usage & uREAD)==0 && !fpublic) {
 13.3249 -    sc_status=statSKIP;
 13.3250 -    cidx=code_idx;
 13.3251 -    glbdecl=glb_declared;
 13.3252 -  } /* if */
 13.3253 -  if ((sym->flags & flgDEPRICATED)!=0) {
 13.3254 -    char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
 13.3255 -    error(234,symbolname,ptr);  /* depricated (probably a public function) */
 13.3256 -  } /* if */
 13.3257 -  begcseg();
 13.3258 -  sym->usage|=uDEFINE;  /* set the definition flag */
 13.3259 -  if (stock)
 13.3260 -    sym->usage|=uSTOCK;
 13.3261 -  if (opertok!=0 && opererror)
 13.3262 -    sym->usage &= ~uDEFINE;
 13.3263 -  /* if the function has states, dump the label to the start of the function */
 13.3264 -  if (state_id!=0) {
 13.3265 -    constvalue *ptr=sym->states->next;
 13.3266 -    while (ptr!=NULL) {
 13.3267 -      assert(sc_status!=statWRITE || strlen(ptr->name)>0);
 13.3268 -      if (ptr->index==state_id) {
 13.3269 -        setlabel((int)strtol(ptr->name,NULL,16));
 13.3270 -        break;
 13.3271 -      } /* if */
 13.3272 -      ptr=ptr->next;
 13.3273 -    } /* while */
 13.3274 -  } /* if */
 13.3275 -  startfunc(sym->name); /* creates stack frame */
 13.3276 -  insert_dbgline(funcline);
 13.3277 -  setline(FALSE);
 13.3278 -  if (sc_alignnext) {
 13.3279 -    alignframe(sc_dataalign);
 13.3280 -    sc_alignnext=FALSE;
 13.3281 -  } /* if */
 13.3282 -  declared=0;           /* number of local cells */
 13.3283 -  rettype=(sym->usage & uRETVALUE);      /* set "return type" variable */
 13.3284 -  curfunc=sym;
 13.3285 -  define_args();        /* add the symbolic info for the function arguments */
 13.3286 -  #if !defined SC_LIGHT
 13.3287 -    if (matchtoken('{')) {
 13.3288 -      lexpush();
 13.3289 -    } else {
 13.3290 -      /* Insert a separator so that comments following the statement will not
 13.3291 -       * be attached to this function; they should be attached to the next
 13.3292 -       * function. This is not a problem for functions having a compound block,
 13.3293 -       * because the closing brace is an explicit "end token" for the function.
 13.3294 -       * With single statement functions, the preprocessor may overread the
 13.3295 -       * source code before the parser determines an "end of statement".
 13.3296 -       */
 13.3297 -      insert_docstring_separator();
 13.3298 -    } /* if */
 13.3299 -  #endif
 13.3300 -  sc_curstates=state_id;/* set state id, for accessing global state variables */
 13.3301 -  statement(NULL,FALSE);
 13.3302 -  sc_curstates=0;
 13.3303 -  if ((rettype & uRETVALUE)!=0)
 13.3304 -    sym->usage|=uRETVALUE;
 13.3305 -  if (declared!=0) {
 13.3306 -    /* This happens only in a very special (and useless) case, where a function
 13.3307 -     * has only a single statement in its body (no compound block) and that
 13.3308 -     * statement declares a new variable
 13.3309 -     */
 13.3310 -    modstk((int)declared*sizeof(cell)); /* remove all local variables */
 13.3311 -    declared=0;
 13.3312 -  } /* if */
 13.3313 -  if ((lastst!=tRETURN) && (lastst!=tGOTO)){
 13.3314 -    ldconst(0,sPRI);
 13.3315 -    ffret(strcmp(sym->name,uENTRYFUNC)!=0);
 13.3316 -    if ((sym->usage & uRETVALUE)!=0) {
 13.3317 -      char symname[2*sNAMEMAX+16];  /* allow space for user defined operators */
 13.3318 -      funcdisplayname(symname,sym->name);
 13.3319 -      error(209,symname);       /* function should return a value */
 13.3320 -    } /* if */
 13.3321 -  } /* if */
 13.3322 -  endfunc();
 13.3323 -  sym->codeaddr=code_idx;
 13.3324 -  sc_attachdocumentation(sym);  /* attach collected documenation to the function */
 13.3325 -  if (litidx) {                 /* if there are literals defined */
 13.3326 -    glb_declared+=litidx;
 13.3327 -    begdseg();                  /* flip to DATA segment */
 13.3328 -    dumplits();                 /* dump literal strings */
 13.3329 -    litidx=0;
 13.3330 -  } /* if */
 13.3331 -  testsymbols(&loctab,0,TRUE,TRUE);     /* test for unused arguments and labels */
 13.3332 -  delete_symbols(&loctab,0,TRUE,TRUE);  /* clear local variables queue */
 13.3333 -  assert(loctab.next==NULL);
 13.3334 -  curfunc=NULL;
 13.3335 -  if (sc_status==statSKIP) {
 13.3336 -    sc_status=statWRITE;
 13.3337 -    code_idx=cidx;
 13.3338 -    glb_declared=glbdecl;
 13.3339 -  } /* if */
 13.3340 -  return TRUE;
 13.3341 -}
 13.3342 -
 13.3343 -static int argcompare(arginfo *a1,arginfo *a2)
 13.3344 -{
 13.3345 -  int result,level,i;
 13.3346 -
 13.3347 -  result= strcmp(a1->name,a2->name)==0;     /* name */
 13.3348 -  if (result)
 13.3349 -    result= a1->ident==a2->ident;           /* type/class */
 13.3350 -  if (result)
 13.3351 -    result= a1->usage==a2->usage;           /* "const" flag */
 13.3352 -  if (result)
 13.3353 -    result= a1->numtags==a2->numtags;       /* tags (number and names) */
 13.3354 -  for (i=0; result && i<a1->numtags; i++)
 13.3355 -    result= a1->tags[i]==a2->tags[i];
 13.3356 -  if (result)
 13.3357 -    result= a1->numdim==a2->numdim;         /* array dimensions & index tags */
 13.3358 -  for (level=0; result && level<a1->numdim; level++)
 13.3359 -    result= a1->dim[level]==a2->dim[level];
 13.3360 -  for (level=0; result && level<a1->numdim; level++)
 13.3361 -    result= a1->idxtag[level]==a2->idxtag[level];
 13.3362 -  if (result)
 13.3363 -    result= a1->hasdefault==a2->hasdefault; /* availability of default value */
 13.3364 -  if (a1->hasdefault) {
 13.3365 -    if (a1->ident==iREFARRAY) {
 13.3366 -      if (result)
 13.3367 -        result= a1->defvalue.array.size==a2->defvalue.array.size;
 13.3368 -      if (result)
 13.3369 -        result= a1->defvalue.array.arraysize==a2->defvalue.array.arraysize;
 13.3370 -      /* ??? should also check contents of the default array (these troubles
 13.3371 -       * go away in a 2-pass compiler that forbids double declarations, but
 13.3372 -       * Pawn currently does not forbid them) */
 13.3373 -    } else {
 13.3374 -      if (result) {
 13.3375 -        if ((a1->hasdefault & uSIZEOF)!=0 || (a1->hasdefault & uTAGOF)!=0)
 13.3376 -          result= a1->hasdefault==a2->hasdefault
 13.3377 -                  && strcmp(a1->defvalue.size.symname,a2->defvalue.size.symname)==0
 13.3378 -                  && a1->defvalue.size.level==a2->defvalue.size.level;
 13.3379 -        else
 13.3380 -          result= a1->defvalue.val==a2->defvalue.val;
 13.3381 -      } /* if */
 13.3382 -    } /* if */
 13.3383 -    if (result)
 13.3384 -      result= a1->defvalue_tag==a2->defvalue_tag;
 13.3385 -  } /* if */
 13.3386 -  return result;
 13.3387 -}
 13.3388 -
 13.3389 -/*  declargs()
 13.3390 - *
 13.3391 - *  This routine adds an entry in the local symbol table for each argument
 13.3392 - *  found in the argument list. It returns the number of arguments.
 13.3393 - */
 13.3394 -static int declargs(symbol *sym,int chkshadow)
 13.3395 -{
 13.3396 -  #define MAXTAGS 16
 13.3397 -  char *ptr;
 13.3398 -  int argcnt,oldargcnt,tok,tags[MAXTAGS],numtags;
 13.3399 -  cell val;
 13.3400 -  arginfo arg, *arglist;
 13.3401 -  char name[sNAMEMAX+1];
 13.3402 -  int ident,fpublic,fconst;
 13.3403 -  int idx;
 13.3404 -
 13.3405 -  /* if the function is already defined earlier, get the number of arguments
 13.3406 -   * of the existing definition
 13.3407 -   */
 13.3408 -  oldargcnt=0;
 13.3409 -  if ((sym->usage & uPROTOTYPED)!=0)
 13.3410 -    while (sym->dim.arglist[oldargcnt].ident!=0)
 13.3411 -      oldargcnt++;
 13.3412 -  argcnt=0;                             /* zero aruments up to now */
 13.3413 -  ident=iVARIABLE;
 13.3414 -  numtags=0;
 13.3415 -  fconst=FALSE;
 13.3416 -  fpublic= (sym->usage & uPUBLIC)!=0;
 13.3417 -  /* the '(' parantheses has already been parsed */
 13.3418 -  if (!matchtoken(')')){
 13.3419 -    do {                                /* there are arguments; process them */
 13.3420 -      /* any legal name increases argument count (and stack offset) */
 13.3421 -      tok=lex(&val,&ptr);
 13.3422 -      switch (tok) {
 13.3423 -      case 0:
 13.3424 -        /* nothing */
 13.3425 -        break;
 13.3426 -      case '&':
 13.3427 -        if (ident!=iVARIABLE || numtags>0)
 13.3428 -          error(1,"-identifier-","&");
 13.3429 -        ident=iREFERENCE;
 13.3430 -        break;
 13.3431 -      case tCONST:
 13.3432 -        if (ident!=iVARIABLE || numtags>0)
 13.3433 -          error(1,"-identifier-","const");
 13.3434 -        fconst=TRUE;
 13.3435 -        break;
 13.3436 -      case tLABEL:
 13.3437 -        if (numtags>0)
 13.3438 -          error(1,"-identifier-","-tagname-");
 13.3439 -        tags[0]=pc_addtag(ptr);
 13.3440 -        numtags=1;
 13.3441 -        break;
 13.3442 -      case '{':
 13.3443 -        if (numtags>0)
 13.3444 -          error(1,"-identifier-","-tagname-");
 13.3445 -        numtags=0;
 13.3446 -        while (numtags<MAXTAGS) {
 13.3447 -          if (!matchtoken('_') && !needtoken(tSYMBOL))
 13.3448 -            break;
 13.3449 -          tokeninfo(&val,&ptr);
 13.3450 -          tags[numtags++]=pc_addtag(ptr);
 13.3451 -          if (matchtoken('}'))
 13.3452 -            break;
 13.3453 -          needtoken(',');
 13.3454 -        } /* for */
 13.3455 -        needtoken(':');
 13.3456 -        tok=tLABEL;     /* for outer loop: flag that we have seen a tagname */
 13.3457 -        break;
 13.3458 -      case tSYMBOL:
 13.3459 -        if (argcnt>=sMAXARGS)
 13.3460 -          error(45);                    /* too many function arguments */
 13.3461 -        strcpy(name,ptr);               /* save symbol name */
 13.3462 -        if (name[0]==PUBLIC_CHAR)
 13.3463 -          error(56,name);               /* function arguments cannot be public */
 13.3464 -        if (numtags==0)
 13.3465 -          tags[numtags++]=0;            /* default tag */
 13.3466 -        /* Stack layout:
 13.3467 -         *   base + 0*sizeof(cell)  == previous "base"
 13.3468 -         *   base + 1*sizeof(cell)  == function return address
 13.3469 -         *   base + 2*sizeof(cell)  == number of arguments
 13.3470 -         *   base + 3*sizeof(cell)  == first argument of the function
 13.3471 -         * So the offset of each argument is "(argcnt+3) * sizeof(cell)".
 13.3472 -         */
 13.3473 -        doarg(name,ident,(argcnt+3)*sizeof(cell),tags,numtags,fpublic,fconst,chkshadow,&arg);
 13.3474 -        if (fpublic && arg.hasdefault)
 13.3475 -          error(59,name);       /* arguments of a public function may not have a default value */
 13.3476 -        if ((sym->usage & uPROTOTYPED)==0) {
 13.3477 -          /* redimension the argument list, add the entry */
 13.3478 -          sym->dim.arglist=(arginfo*)realloc(sym->dim.arglist,(argcnt+2)*sizeof(arginfo));
 13.3479 -          if (sym->dim.arglist==0)
 13.3480 -            error(103);                 /* insufficient memory */
 13.3481 -          memset(&sym->dim.arglist[argcnt+1],0,sizeof(arginfo));  /* keep the list terminated */
 13.3482 -          sym->dim.arglist[argcnt]=arg;
 13.3483 -        } else {
 13.3484 -          /* check the argument with the earlier definition */
 13.3485 -          if (argcnt>oldargcnt || !argcompare(&sym->dim.arglist[argcnt],&arg))
 13.3486 -            error(25);          /* function definition does not match prototype */
 13.3487 -          /* may need to free default array argument and the tag list */
 13.3488 -          if (arg.ident==iREFARRAY && arg.hasdefault)
 13.3489 -            free(arg.defvalue.array.data);
 13.3490 -          else if (arg.ident==iVARIABLE
 13.3491 -                   && ((arg.hasdefault & uSIZEOF)!=0 || (arg.hasdefault & uTAGOF)!=0))
 13.3492 -            free(arg.defvalue.size.symname);
 13.3493 -          free(arg.tags);
 13.3494 -        } /* if */
 13.3495 -        argcnt++;
 13.3496 -        ident=iVARIABLE;
 13.3497 -        numtags=0;
 13.3498 -        fconst=FALSE;
 13.3499 -        break;
 13.3500 -      case tELLIPS:
 13.3501 -        if (ident!=iVARIABLE)
 13.3502 -          error(10);                    /* illegal function or declaration */
 13.3503 -        if (numtags==0)
 13.3504 -          tags[numtags++]=0;            /* default tag */
 13.3505 -        if ((sym->usage & uPROTOTYPED)==0) {
 13.3506 -          /* redimension the argument list, add the entry iVARARGS */
 13.3507 -          sym->dim.arglist=(arginfo*)realloc(sym->dim.arglist,(argcnt+2)*sizeof(arginfo));
 13.3508 -          if (sym->dim.arglist==0)
 13.3509 -            error(103);                 /* insufficient memory */
 13.3510 -          memset(&sym->dim.arglist[argcnt+1],0,sizeof(arginfo));  /* keep the list terminated */
 13.3511 -          sym->dim.arglist[argcnt].ident=iVARARGS;
 13.3512 -          sym->dim.arglist[argcnt].hasdefault=FALSE;
 13.3513 -          sym->dim.arglist[argcnt].defvalue.val=0;
 13.3514 -          sym->dim.arglist[argcnt].defvalue_tag=0;
 13.3515 -          sym->dim.arglist[argcnt].numtags=numtags;
 13.3516 -          sym->dim.arglist[argcnt].tags=(int*)malloc(numtags*sizeof tags[0]);
 13.3517 -          if (sym->dim.arglist[argcnt].tags==NULL)
 13.3518 -            error(103);                 /* insufficient memory */
 13.3519 -          memcpy(sym->dim.arglist[argcnt].tags,tags,numtags*sizeof tags[0]);
 13.3520 -        } else {
 13.3521 -          if (argcnt>oldargcnt || sym->dim.arglist[argcnt].ident!=iVARARGS)
 13.3522 -            error(25);          /* function definition does not match prototype */
 13.3523 -        } /* if */
 13.3524 -        argcnt++;
 13.3525 -        break;
 13.3526 -      default:
 13.3527 -        error(10);                      /* illegal function or declaration */
 13.3528 -      } /* switch */
 13.3529 -    } while (tok=='&' || tok==tLABEL || tok==tCONST
 13.3530 -             || tok!=tELLIPS && matchtoken(',')); /* more? */
 13.3531 -    /* if the next token is not ",", it should be ")" */
 13.3532 -    needtoken(')');
 13.3533 -  } /* if */
 13.3534 -  /* resolve any "sizeof" arguments (now that all arguments are known) */
 13.3535 -  assert(sym->dim.arglist!=NULL);
 13.3536 -  arglist=sym->dim.arglist;
 13.3537 -  for (idx=0; idx<argcnt && arglist[idx].ident!=0; idx++) {
 13.3538 -    if ((arglist[idx].hasdefault & uSIZEOF)!=0 || (arglist[idx].hasdefault & uTAGOF)!=0) {
 13.3539 -      int altidx;
 13.3540 -      /* Find the argument with the name mentioned after the "sizeof". Note
 13.3541 -       * that we cannot use findloc here because we need the arginfo struct,
 13.3542 -       * not the symbol.
 13.3543 -       */
 13.3544 -      ptr=arglist[idx].defvalue.size.symname;
 13.3545 -      assert(ptr!=NULL);
 13.3546 -      for (altidx=0; altidx<argcnt && strcmp(ptr,arglist[altidx].name)!=0; altidx++)
 13.3547 -        /* nothing */;
 13.3548 -      if (altidx>=argcnt) {
 13.3549 -        error(17,ptr);                  /* undefined symbol */
 13.3550 -      } else {
 13.3551 -        assert(arglist[idx].defvalue.size.symname!=NULL);
 13.3552 -        /* check the level against the number of dimensions */
 13.3553 -        if (arglist[idx].defvalue.size.level>0
 13.3554 -            && arglist[idx].defvalue.size.level>=arglist[altidx].numdim)
 13.3555 -          error(28,arglist[idx].name);  /* invalid subscript */
 13.3556 -        /* check the type of the argument whose size to take; for a iVARIABLE
 13.3557 -         * or a iREFERENCE, this is always 1 (so the code is redundant)
 13.3558 -         */
 13.3559 -        assert(arglist[altidx].ident!=iVARARGS);
 13.3560 -        if (arglist[altidx].ident!=iREFARRAY && (arglist[idx].hasdefault & uSIZEOF)!=0) {
 13.3561 -          if ((arglist[idx].hasdefault & uTAGOF)!=0) {
 13.3562 -            error(81,arglist[idx].name);  /* cannot take "tagof" an indexed array */
 13.3563 -          } else {
 13.3564 -            assert(arglist[altidx].ident==iVARIABLE || arglist[altidx].ident==iREFERENCE);
 13.3565 -            error(223,ptr);             /* redundant sizeof */
 13.3566 -          } /* if */
 13.3567 -        } /* if */
 13.3568 -      } /* if */
 13.3569 -    } /* if */
 13.3570 -  } /* for */
 13.3571 -
 13.3572 -  sym->usage|=uPROTOTYPED;
 13.3573 -  errorset(sRESET,0);           /* reset error flag (clear the "panic mode")*/
 13.3574 -  return argcnt;
 13.3575 -}
 13.3576 -
 13.3577 -/*  doarg       - declare one argument type
 13.3578 - *
 13.3579 - *  this routine is called from "declargs()" and adds an entry in the local
 13.3580 - *  symbol table for one argument.
 13.3581 - *
 13.3582 - *  "fpublic" indicates whether the function for this argument list is public.
 13.3583 - *  The arguments themselves are never public.
 13.3584 - */
 13.3585 -static void doarg(char *name,int ident,int offset,int tags[],int numtags,
 13.3586 -                  int fpublic,int fconst,int chkshadow,arginfo *arg)
 13.3587 -{
 13.3588 -  symbol *argsym;
 13.3589 -  constvalue *enumroot;
 13.3590 -  cell size;
 13.3591 -
 13.3592 -  strcpy(arg->name,name);
 13.3593 -  arg->hasdefault=FALSE;        /* preset (most common case) */
 13.3594 -  arg->defvalue.val=0;          /* clear */
 13.3595 -  arg->defvalue_tag=0;
 13.3596 -  arg->numdim=0;
 13.3597 -  if (matchtoken('[')) {
 13.3598 -    if (ident==iREFERENCE)
 13.3599 -      error(67,name);           /* illegal declaration ("&name[]" is unsupported) */
 13.3600 -    do {
 13.3601 -      if (arg->numdim == sDIMEN_MAX) {
 13.3602 -        error(53);              /* exceeding maximum number of dimensions */
 13.3603 -        return;
 13.3604 -      } /* if */
 13.3605 -      size=needsub(&arg->idxtag[arg->numdim],&enumroot);/* may be zero here, it is a pointer anyway */
 13.3606 -      #if INT_MAX < LONG_MAX
 13.3607 -        if (size > INT_MAX)
 13.3608 -          error(105);           /* overflow, exceeding capacity */
 13.3609 -      #endif
 13.3610 -      arg->dim[arg->numdim]=(int)size;
 13.3611 -      arg->numdim+=1;
 13.3612 -    } while (matchtoken('['));
 13.3613 -    ident=iREFARRAY;            /* "reference to array" (is a pointer) */
 13.3614 -    if (matchtoken('=')) {
 13.3615 -      lexpush();                /* initials() needs the "=" token again */
 13.3616 -      assert(litidx==0);        /* at the start of a function, this is reset */
 13.3617 -      assert(numtags>0);
 13.3618 -      initials(ident,tags[0],&size,arg->dim,arg->numdim,enumroot);
 13.3619 -      assert(size>=litidx);
 13.3620 -      /* allocate memory to hold the initial values */
 13.3621 -      arg->defvalue.array.data=(cell *)malloc(litidx*sizeof(cell));
 13.3622 -      if (arg->defvalue.array.data!=NULL) {
 13.3623 -        int i;
 13.3624 -        memcpy(arg->defvalue.array.data,litq,litidx*sizeof(cell));
 13.3625 -        arg->hasdefault=TRUE;   /* argument has default value */
 13.3626 -        arg->defvalue.array.size=litidx;
 13.3627 -        arg->defvalue.array.addr=-1;
 13.3628 -        /* calulate size to reserve on the heap */
 13.3629 -        arg->defvalue.array.arraysize=1;
 13.3630 -        for (i=0; i<arg->numdim; i++)
 13.3631 -          arg->defvalue.array.arraysize*=arg->dim[i];
 13.3632 -        if (arg->defvalue.array.arraysize < arg->defvalue.array.size)
 13.3633 -          arg->defvalue.array.arraysize = arg->defvalue.array.size;
 13.3634 -      } /* if */
 13.3635 -      litidx=0;                 /* reset */
 13.3636 -    } /* if */
 13.3637 -  } else {
 13.3638 -    if (matchtoken('=')) {
 13.3639 -      unsigned char size_tag_token;
 13.3640 -      assert(ident==iVARIABLE || ident==iREFERENCE);
 13.3641 -      arg->hasdefault=TRUE;     /* argument has a default value */
 13.3642 -      size_tag_token=(unsigned char)(matchtoken(tSIZEOF) ? uSIZEOF : 0);
 13.3643 -      if (size_tag_token==0)
 13.3644 -        size_tag_token=(unsigned char)(matchtoken(tTAGOF) ? uTAGOF : 0);
 13.3645 -      if (size_tag_token!=0) {
 13.3646 -        int paranthese;
 13.3647 -        if (ident==iREFERENCE)
 13.3648 -          error(66,name);       /* argument may not be a reference */
 13.3649 -        paranthese=0;
 13.3650 -        while (matchtoken('('))
 13.3651 -          paranthese++;
 13.3652 -        if (needtoken(tSYMBOL)) {
 13.3653 -          /* save the name of the argument whose size id to take */
 13.3654 -          char *name;
 13.3655 -          cell val;
 13.3656 -          tokeninfo(&val,&name);
 13.3657 -          if ((arg->defvalue.size.symname=duplicatestring(name)) == NULL)
 13.3658 -            error(103);         /* insufficient memory */
 13.3659 -          arg->defvalue.size.level=0;
 13.3660 -          if (size_tag_token==uSIZEOF) {
 13.3661 -            while (matchtoken('[')) {
 13.3662 -              arg->defvalue.size.level+=(short)1;
 13.3663 -              needtoken(']');
 13.3664 -            } /* while */
 13.3665 -          } /* if */
 13.3666 -          if (ident==iVARIABLE) /* make sure we set this only if not a reference */
 13.3667 -            arg->hasdefault |= size_tag_token;  /* uSIZEOF or uTAGOF */
 13.3668 -        } /* if */
 13.3669 -        while (paranthese--)
 13.3670 -          needtoken(')');
 13.3671 -      } else {
 13.3672 -        constexpr(&arg->defvalue.val,&arg->defvalue_tag,NULL);
 13.3673 -        assert(numtags>0);
 13.3674 -        if (!matchtag(tags[0],arg->defvalue_tag,TRUE))
 13.3675 -          error(213);           /* tagname mismatch */
 13.3676 -      } /* if */
 13.3677 -    } /* if */
 13.3678 -  } /* if */
 13.3679 -  arg->ident=(char)ident;
 13.3680 -  arg->usage=(char)(fconst ? uCONST : 0);
 13.3681 -  arg->numtags=numtags;
 13.3682 -  arg->tags=(int*)malloc(numtags*sizeof tags[0]);
 13.3683 -  if (arg->tags==NULL)
 13.3684 -    error(103);                 /* insufficient memory */
 13.3685 -  memcpy(arg->tags,tags,numtags*sizeof tags[0]);
 13.3686 -  argsym=findloc(name);
 13.3687 -  if (argsym!=NULL) {
 13.3688 -    error(21,name);             /* symbol already defined */
 13.3689 -  } else {
 13.3690 -    if (chkshadow && (argsym=findglb(name,sSTATEVAR))!=NULL && argsym->ident!=iFUNCTN)
 13.3691 -      error(219,name);          /* variable shadows another symbol */
 13.3692 -    /* add details of type and address */
 13.3693 -    assert(numtags>0);
 13.3694 -    argsym=addvariable(name,offset,ident,sLOCAL,tags[0],
 13.3695 -                       arg->dim,arg->numdim,arg->idxtag);
 13.3696 -    argsym->compound=0;
 13.3697 -    if (ident==iREFERENCE)
 13.3698 -      argsym->usage|=uREAD;     /* because references are passed back */
 13.3699 -    if (fpublic)
 13.3700 -      argsym->usage|=uREAD;     /* arguments of public functions are always "used" */
 13.3701 -    if (fconst)
 13.3702 -      argsym->usage|=uCONST;
 13.3703 -  } /* if */
 13.3704 -}
 13.3705 -
 13.3706 -static int count_referrers(symbol *entry)
 13.3707 -{
 13.3708 -  int i,count;
 13.3709 -
 13.3710 -  count=0;
 13.3711 -  for (i=0; i<entry->numrefers; i++)
 13.3712 -    if (entry->refer[i]!=NULL)
 13.3713 -      count++;
 13.3714 -  return count;
 13.3715 -}
 13.3716 -
 13.3717 -#if !defined SC_LIGHT
 13.3718 -static int find_xmltag(char *source,char *xmltag,char *xmlparam,char *xmlvalue,
 13.3719 -                       char **outer_start,int *outer_length,
 13.3720 -                       char **inner_start,int *inner_length)
 13.3721 -{
 13.3722 -  char *ptr,*inner_end;
 13.3723 -  int xmltag_len,xmlparam_len,xmlvalue_len;
 13.3724 -  int match;
 13.3725 -
 13.3726 -  assert(source!=NULL);
 13.3727 -  assert(xmltag!=NULL);
 13.3728 -  assert(outer_start!=NULL);
 13.3729 -  assert(outer_length!=NULL);
 13.3730 -  assert(inner_start!=NULL);
 13.3731 -  assert(inner_length!=NULL);
 13.3732 -
 13.3733 -  /* both NULL or both non-NULL */
 13.3734 -  assert(xmlvalue!=NULL && xmlparam!=NULL || xmlvalue==NULL && xmlparam==NULL);
 13.3735 -
 13.3736 -  xmltag_len=strlen(xmltag);
 13.3737 -  xmlparam_len= (xmlparam!=NULL) ? strlen(xmlparam) : 0;
 13.3738 -  xmlvalue_len= (xmlvalue!=NULL) ? strlen(xmlvalue) : 0;
 13.3739 -  ptr=source;
 13.3740 -  /* find an opening '<' */
 13.3741 -  while ((ptr=strchr(ptr,'<'))!=NULL) {
 13.3742 -    *outer_start=ptr;           /* be optimistic... */
 13.3743 -    match=FALSE;                /* ...and pessimistic at the same time */
 13.3744 -    ptr++;                      /* skip '<' */
 13.3745 -    while (*ptr!='\0' && *ptr<=' ')
 13.3746 -      ptr++;                    /* skip white space */
 13.3747 -    if (strncmp(ptr,xmltag,xmltag_len)==0 && (*(ptr+xmltag_len)<=' ' || *(ptr+xmltag_len)=='>')) {
 13.3748 -      /* xml tag found, optionally check the parameter */
 13.3749 -      ptr+=xmltag_len;
 13.3750 -      while (*ptr!='\0' && *ptr<=' ')
 13.3751 -        ptr++;                  /* skip white space */
 13.3752 -      if (xmlparam!=NULL) {
 13.3753 -        if (strncmp(ptr,xmlparam,xmlparam_len)==0 && (*(ptr+xmlparam_len)<=' ' || *(ptr+xmlparam_len)=='=')) {
 13.3754 -          ptr+=xmlparam_len;
 13.3755 -          while (*ptr!='\0' && *ptr<=' ')
 13.3756 -            ptr++;              /* skip white space */
 13.3757 -          if (*ptr=='=') {
 13.3758 -            ptr++;              /* skip '=' */
 13.3759 -            while (*ptr!='\0' && *ptr<=' ')
 13.3760 -              ptr++;            /* skip white space */
 13.3761 -            if (*ptr=='"' || *ptr=='\'')
 13.3762 -              ptr++;            /* skip " or ' */
 13.3763 -            assert(xmlvalue!=NULL);
 13.3764 -            if (strncmp(ptr,xmlvalue,xmlvalue_len)==0
 13.3765 -                && (*(ptr+xmlvalue_len)<=' '
 13.3766 -                    || *(ptr+xmlvalue_len)=='>'
 13.3767 -                    || *(ptr+xmlvalue_len)=='"'
 13.3768 -                    || *(ptr+xmlvalue_len)=='\''))
 13.3769 -              match=TRUE;       /* found it */
 13.3770 -          } /* if */
 13.3771 -        } /* if */
 13.3772 -      } else {
 13.3773 -        match=TRUE;             /* don't check the parameter */
 13.3774 -      } /* if */
 13.3775 -    } /* if */
 13.3776 -    if (match) {
 13.3777 -      /* now find the end of the opening tag */
 13.3778 -      while (*ptr!='\0' && *ptr!='>')
 13.3779 -        ptr++;
 13.3780 -      if (*ptr=='>')
 13.3781 -        ptr++;
 13.3782 -      while (*ptr!='\0' && *ptr<=' ')
 13.3783 -        ptr++;                  /* skip white space */
 13.3784 -      *inner_start=ptr;
 13.3785 -      /* find the start of the closing tag (assume no nesting) */
 13.3786 -      while ((ptr=strchr(ptr,'<'))!=NULL) {
 13.3787 -        inner_end=ptr;
 13.3788 -        ptr++;                  /* skip '<' */
 13.3789 -        while (*ptr!='\0' && *ptr<=' ')
 13.3790 -          ptr++;                /* skip white space */
 13.3791 -        if (*ptr=='/') {
 13.3792 -          ptr++;                /* skip / */
 13.3793 -          while (*ptr!='\0' && *ptr<=' ')
 13.3794 -            ptr++;              /* skip white space */
 13.3795 -          if (strncmp(ptr,xmltag,xmltag_len)==0 && (*(ptr+xmltag_len)<=' ' || *(ptr+xmltag_len)=='>')) {
 13.3796 -            /* find the end of the closing tag */
 13.3797 -            while (*ptr!='\0' && *ptr!='>')
 13.3798 -              ptr++;
 13.3799 -            if (*ptr=='>')
 13.3800 -              ptr++;
 13.3801 -            /* set the lengths of the inner and outer segment */
 13.3802 -            assert(*inner_start!=NULL);
 13.3803 -            *inner_length=(int)(inner_end-*inner_start);
 13.3804 -            assert(*outer_start!=NULL);
 13.3805 -            *outer_length=(int)(ptr-*outer_start);
 13.3806 -            break;              /* break out of the loop */
 13.3807 -          } /* if */
 13.3808 -        } /* if */
 13.3809 -      } /* while */
 13.3810 -      return TRUE;
 13.3811 -    } /* if */
 13.3812 -  } /* while */
 13.3813 -  return FALSE; /* not found */
 13.3814 -}
 13.3815 -
 13.3816 -static char *xmlencode(char *dest,char *source)
 13.3817 -{
 13.3818 -  char temp[2*sNAMEMAX+20],*ptr;
 13.3819 -
 13.3820 -  /* replace < by &lt; and such; normally, such a symbol occurs at most once in
 13.3821 -   * a symbol name (e.g. "operator<")
 13.3822 -   */
 13.3823 -  ptr=temp;
 13.3824 -  while (*source!='\0') {
 13.3825 -    switch (*source) {
 13.3826 -    case '<':
 13.3827 -      strcpy(ptr,"&lt;");
 13.3828 -      ptr+=4;
 13.3829 -      break;
 13.3830 -    case '>':
 13.3831 -      strcpy(ptr,"&gt;");
 13.3832 -      ptr+=4;
 13.3833 -      break;
 13.3834 -    case '&':
 13.3835 -      strcpy(ptr,"&amp;");
 13.3836 -      ptr+=5;
 13.3837 -      break;
 13.3838 -    default:
 13.3839 -      *ptr++=*source;
 13.3840 -    } /* switch */
 13.3841 -    source++;
 13.3842 -  } /* while */
 13.3843 -  *ptr='\0';
 13.3844 -  strcpy(dest,temp);
 13.3845 -  return dest;
 13.3846 -}
 13.3847 -
 13.3848 -static void make_report(symbol *root,FILE *log,char *sourcefile)
 13.3849 -{
 13.3850 -  char symname[_MAX_PATH];
 13.3851 -  int i,arg;
 13.3852 -  symbol *sym,*ref;
 13.3853 -  constvalue *tagsym;
 13.3854 -  constvalue *enumroot;
 13.3855 -  char *ptr;
 13.3856 -
 13.3857 -  /* adapt the installation directory */
 13.3858 -  strcpy(symname,sc_rootpath);
 13.3859 -  #if DIRSEP_CHAR=='\\'
 13.3860 -    while ((ptr=strchr(symname,':'))!=NULL)
 13.3861 -      *ptr='|';
 13.3862 -    while ((ptr=strchr(symname,DIRSEP_CHAR))!=NULL)
 13.3863 -      *ptr='/';
 13.3864 -  #endif
 13.3865 -
 13.3866 -  /* the XML header */
 13.3867 -  fprintf(log,"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
 13.3868 -  fprintf(log,"<?xml-stylesheet href=\"file:///%s/xml/pawndoc.xsl\" type=\"text/xsl\"?>\n",symname);
 13.3869 -  fprintf(log,"<doc source=\"%s\">\n",sourcefile);
 13.3870 -  ptr=strrchr(sourcefile,DIRSEP_CHAR);
 13.3871 -  if (ptr!=NULL)
 13.3872 -    ptr++;
 13.3873 -  else
 13.3874 -    ptr=sourcefile;
 13.3875 -  fprintf(log,"\t<assembly>\n\t\t<name>%s</name>\n\t</assembly>\n",ptr);
 13.3876 -
 13.3877 -  /* attach the global documentation, if any */
 13.3878 -  if (sc_documentation!=NULL) {
 13.3879 -    fprintf(log,"\n\t<!-- general -->\n");
 13.3880 -    fprintf(log,"\t<general>\n\t\t");
 13.3881 -    fputs(sc_documentation,log);
 13.3882 -    fprintf(log,"\n\t</general>\n\n");
 13.3883 -  } /* if */
 13.3884 -
 13.3885 -  /* use multiple passes to print constants variables and functions in
 13.3886 -   * separate sections
 13.3887 -   */
 13.3888 -  fprintf(log,"\t<members>\n");
 13.3889 -
 13.3890 -  fprintf(log,"\n\t\t<!-- enumerations -->\n");
 13.3891 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.3892 -    if (sym->parent!=NULL)
 13.3893 -      continue;                 /* hierarchical data type */
 13.3894 -    assert(sym->ident==iCONSTEXPR || sym->ident==iVARIABLE
 13.3895 -           || sym->ident==iARRAY || sym->ident==iFUNCTN);
 13.3896 -    if (sym->ident!=iCONSTEXPR || (sym->usage & uENUMROOT)==0)
 13.3897 -      continue;
 13.3898 -    if ((sym->usage & uREAD)==0)
 13.3899 -      continue;
 13.3900 -    fprintf(log,"\t\t<member name=\"T:%s\" value=\"%ld\">\n",funcdisplayname(symname,sym->name),sym->addr);
 13.3901 -    if (sym->tag!=0) {
 13.3902 -      tagsym=find_tag_byval(sym->tag);
 13.3903 -      assert(tagsym!=NULL);
 13.3904 -      fprintf(log,"\t\t\t<tagname value=\"%s\"/>\n",tagsym->name);
 13.3905 -    } /* if */
 13.3906 -    /* browse through all fields */
 13.3907 -    if ((enumroot=sym->dim.enumlist)!=NULL) {
 13.3908 -      enumroot=enumroot->next;  /* skip root */
 13.3909 -      while (enumroot!=NULL) {
 13.3910 -        fprintf(log,"\t\t\t<member name=\"C:%s\" value=\"%ld\">\n",funcdisplayname(symname,enumroot->name),enumroot->value);
 13.3911 -        /* find the constant with this name and get the tag */
 13.3912 -        ref=findglb(enumroot->name,sGLOBAL);
 13.3913 -        if (ref!=NULL) {
 13.3914 -          if (ref->x.tags.index!=0) {
 13.3915 -            tagsym=find_tag_byval(ref->x.tags.index);
 13.3916 -            assert(tagsym!=NULL);
 13.3917 -            fprintf(log,"\t\t\t\t<tagname value=\"%s\"/>\n",tagsym->name);
 13.3918 -          } /* if */
 13.3919 -          if (ref->dim.array.length!=1)
 13.3920 -            fprintf(log,"\t\t\t\t<size value=\"%ld\"/>\n",(long)ref->dim.array.length);
 13.3921 -        } /* if */
 13.3922 -        fprintf(log,"\t\t\t</member>\n");
 13.3923 -        enumroot=enumroot->next;
 13.3924 -      } /* while */
 13.3925 -    } /* if */
 13.3926 -    assert(sym->refer!=NULL);
 13.3927 -    for (i=0; i<sym->numrefers; i++) {
 13.3928 -      if ((ref=sym->refer[i])!=NULL)
 13.3929 -        fprintf(log,"\t\t\t<referrer name=\"%s\"/>\n",xmlencode(symname,funcdisplayname(symname,ref->name)));
 13.3930 -    } /* for */
 13.3931 -    if (sym->documentation!=NULL)
 13.3932 -      fprintf(log,"\t\t\t%s\n",sym->documentation);
 13.3933 -    fprintf(log,"\t\t</member>\n");
 13.3934 -  } /* for */
 13.3935 -
 13.3936 -  fprintf(log,"\n\t\t<!-- constants -->\n");
 13.3937 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.3938 -    if (sym->parent!=NULL)
 13.3939 -      continue;                 /* hierarchical data type */
 13.3940 -    assert(sym->ident==iCONSTEXPR || sym->ident==iVARIABLE
 13.3941 -           || sym->ident==iARRAY || sym->ident==iFUNCTN);
 13.3942 -    if (sym->ident!=iCONSTEXPR)
 13.3943 -      continue;
 13.3944 -    if ((sym->usage & uREAD)==0 || (sym->usage & (uENUMFIELD | uENUMROOT))!=0)
 13.3945 -      continue;
 13.3946 -    fprintf(log,"\t\t<member name=\"C:%s\" value=\"%ld\">\n",funcdisplayname(symname,sym->name),sym->addr);
 13.3947 -    if (sym->tag!=0) {
 13.3948 -      tagsym=find_tag_byval(sym->tag);
 13.3949 -      assert(tagsym!=NULL);
 13.3950 -      fprintf(log,"\t\t\t<tagname value=\"%s\"/>\n",tagsym->name);
 13.3951 -    } /* if */
 13.3952 -    assert(sym->refer!=NULL);
 13.3953 -    for (i=0; i<sym->numrefers; i++) {
 13.3954 -      if ((ref=sym->refer[i])!=NULL)
 13.3955 -        fprintf(log,"\t\t\t<referrer name=\"%s\"/>\n",xmlencode(symname,funcdisplayname(symname,ref->name)));
 13.3956 -    } /* for */
 13.3957 -    if (sym->documentation!=NULL)
 13.3958 -      fprintf(log,"\t\t\t%s\n",sym->documentation);
 13.3959 -    fprintf(log,"\t\t</member>\n");
 13.3960 -  } /* for */
 13.3961 -
 13.3962 -  fprintf(log,"\n\t\t<!-- variables -->\n");
 13.3963 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.3964 -    if (sym->parent!=NULL)
 13.3965 -      continue;                 /* hierarchical data type */
 13.3966 -    if (sym->ident!=iVARIABLE && sym->ident!=iARRAY)
 13.3967 -      continue;
 13.3968 -    fprintf(log,"\t\t<member name=\"F:%s\">\n",funcdisplayname(symname,sym->name));
 13.3969 -    if (sym->tag!=0) {
 13.3970 -      tagsym=find_tag_byval(sym->tag);
 13.3971 -      assert(tagsym!=NULL);
 13.3972 -      fprintf(log,"\t\t\t<tagname value=\"%s\"/>\n",tagsym->name);
 13.3973 -    } /* if */
 13.3974 -    assert(sym->refer!=NULL);
 13.3975 -    if ((sym->usage & uPUBLIC)!=0)
 13.3976 -      fprintf(log,"\t\t\t<attribute name=\"public\"/>\n");
 13.3977 -    for (i=0; i<sym->numrefers; i++) {
 13.3978 -      if ((ref=sym->refer[i])!=NULL)
 13.3979 -        fprintf(log,"\t\t\t<referrer name=\"%s\"/>\n",xmlencode(symname,funcdisplayname(symname,ref->name)));
 13.3980 -    } /* for */
 13.3981 -    if (sym->documentation!=NULL)
 13.3982 -      fprintf(log,"\t\t\t%s\n",sym->documentation);
 13.3983 -    fprintf(log,"\t\t</member>\n");
 13.3984 -  } /* for */
 13.3985 -
 13.3986 -  fprintf(log,"\n\t\t<!-- functions -->\n");
 13.3987 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.3988 -    if (sym->parent!=NULL)
 13.3989 -      continue;                 /* hierarchical data type */
 13.3990 -    if (sym->ident!=iFUNCTN)
 13.3991 -      continue;
 13.3992 -    if ((sym->usage & (uREAD | uNATIVE))==uNATIVE)
 13.3993 -      continue;                 /* unused native function */
 13.3994 -    funcdisplayname(symname,sym->name);
 13.3995 -    xmlencode(symname,symname);
 13.3996 -    fprintf(log,"\t\t<member name=\"M:%s\" syntax=\"%s(",symname,symname);
 13.3997 -    /* print only the names of the parameters between the parentheses */
 13.3998 -    assert(sym->dim.arglist!=NULL);
 13.3999 -    for (arg=0; sym->dim.arglist[arg].ident!=0; arg++) {
 13.4000 -      int dim;
 13.4001 -      if (arg>0)
 13.4002 -        fprintf(log,", ");
 13.4003 -      switch (sym->dim.arglist[arg].ident) {
 13.4004 -      case iVARIABLE:
 13.4005 -        fprintf(log,"%s",sym->dim.arglist[arg].name);
 13.4006 -        break;
 13.4007 -      case iREFERENCE:
 13.4008 -        fprintf(log,"&amp;%s",sym->dim.arglist[arg].name);
 13.4009 -        break;
 13.4010 -      case iREFARRAY:
 13.4011 -        fprintf(log,"%s",sym->dim.arglist[arg].name);
 13.4012 -        for (dim=0; dim<sym->dim.arglist[arg].numdim;dim++)
 13.4013 -          fprintf(log,"[]");
 13.4014 -        break;
 13.4015 -      case iVARARGS:
 13.4016 -        fprintf(log,"...");
 13.4017 -        break;
 13.4018 -      } /* switch */
 13.4019 -    } /* for */
 13.4020 -    /* ??? should also print an "array return" size */
 13.4021 -    fprintf(log,")\">\n");
 13.4022 -    if (sym->tag!=0) {
 13.4023 -      tagsym=find_tag_byval(sym->tag);
 13.4024 -      assert(tagsym!=NULL);
 13.4025 -      fprintf(log,"\t\t\t<tagname value=\"%s\"/>\n",tagsym->name);
 13.4026 -    } /* if */
 13.4027 -    /* check whether this function is called from the outside */
 13.4028 -    if ((sym->usage & uNATIVE)!=0)
 13.4029 -      fprintf(log,"\t\t\t<attribute name=\"native\"/>\n");
 13.4030 -    if ((sym->usage & uPUBLIC)!=0)
 13.4031 -      fprintf(log,"\t\t\t<attribute name=\"public\"/>\n");
 13.4032 -    if (strcmp(sym->name,uMAINFUNC)==0 || strcmp(sym->name,uENTRYFUNC)==0)
 13.4033 -      fprintf(log,"\t\t\t<attribute name=\"entry\"/>\n");
 13.4034 -    if ((sym->usage & uNATIVE)==0)
 13.4035 -      fprintf(log,"\t\t\t<stacksize value=\"%ld\"/>\n",(long)sym->x.stacksize);
 13.4036 -    if (sym->states!=NULL) {
 13.4037 -      constvalue *stlist=sym->states->next;
 13.4038 -      assert(stlist!=NULL);     /* there should be at least one state item */
 13.4039 -      while (stlist!=NULL && stlist->index==-1)
 13.4040 -        stlist=stlist->next;
 13.4041 -      assert(stlist!=NULL);     /* state id should be found */
 13.4042 -      i=state_getfsa(stlist->index);
 13.4043 -      assert(i>=0);             /* automaton 0 exists */
 13.4044 -      stlist=automaton_findid(i);
 13.4045 -      assert(stlist!=NULL);     /* automaton should be found */
 13.4046 -      fprintf(log,"\t\t\t<automaton name=\"%s\"/>\n", strlen(stlist->name)>0 ? stlist->name : "(anonymous)");
 13.4047 -      //??? dump state decision table
 13.4048 -    } /* if */
 13.4049 -    assert(sym->refer!=NULL);
 13.4050 -    for (i=0; i<sym->numrefers; i++)
 13.4051 -      if ((ref=sym->refer[i])!=NULL)
 13.4052 -        fprintf(log,"\t\t\t<referrer name=\"%s\"/>\n",xmlencode(symname,funcdisplayname(symname,ref->name)));
 13.4053 -    /* print all symbols that are required for this function to compile */
 13.4054 -    for (ref=root->next; ref!=NULL; ref=ref->next) {
 13.4055 -      if (ref==sym)
 13.4056 -        continue;
 13.4057 -      for (i=0; i<ref->numrefers; i++)
 13.4058 -        if (ref->refer[i]==sym)
 13.4059 -          fprintf(log,"\t\t\t<dependency name=\"%s\"/>\n",xmlencode(symname,funcdisplayname(symname,ref->name)));
 13.4060 -    } /* for */
 13.4061 -    /* print parameter list, with tag & const information, plus descriptions */
 13.4062 -    assert(sym->dim.arglist!=NULL);
 13.4063 -    for (arg=0; sym->dim.arglist[arg].ident!=0; arg++) {
 13.4064 -      int dim,paraminfo;
 13.4065 -      char *outer_start,*inner_start;
 13.4066 -      int outer_length,inner_length;
 13.4067 -      if (sym->dim.arglist[arg].ident==iVARARGS)
 13.4068 -        fprintf(log,"\t\t\t<param name=\"...\">\n");
 13.4069 -      else
 13.4070 -        fprintf(log,"\t\t\t<param name=\"%s\">\n",sym->dim.arglist[arg].name);
 13.4071 -      /* print the tag name(s) for each parameter */
 13.4072 -      assert(sym->dim.arglist[arg].numtags>0);
 13.4073 -      assert(sym->dim.arglist[arg].tags!=NULL);
 13.4074 -      paraminfo=(sym->dim.arglist[arg].numtags>1 || sym->dim.arglist[arg].tags[0]!=0)
 13.4075 -                || sym->dim.arglist[arg].ident==iREFERENCE
 13.4076 -                || sym->dim.arglist[arg].ident==iREFARRAY;
 13.4077 -      if (paraminfo)
 13.4078 -        fprintf(log,"\t\t\t\t<paraminfo>");
 13.4079 -      if (sym->dim.arglist[arg].numtags>1 || sym->dim.arglist[arg].tags[0]!=0) {
 13.4080 -        assert(paraminfo);
 13.4081 -        if (sym->dim.arglist[arg].numtags>1)
 13.4082 -          fprintf(log," {");
 13.4083 -        for (i=0; i<sym->dim.arglist[arg].numtags; i++) {
 13.4084 -          if (i>0)
 13.4085 -            fprintf(log,",");
 13.4086 -          tagsym=find_tag_byval(sym->dim.arglist[arg].tags[i]);
 13.4087 -          assert(tagsym!=NULL);
 13.4088 -          fprintf(log,"%s",tagsym->name);
 13.4089 -        } /* for */
 13.4090 -        if (sym->dim.arglist[arg].numtags>1)
 13.4091 -          fprintf(log,"}");
 13.4092 -      } /* if */
 13.4093 -      switch (sym->dim.arglist[arg].ident) {
 13.4094 -      case iREFERENCE:
 13.4095 -        fprintf(log," &amp;");
 13.4096 -        break;
 13.4097 -      case iREFARRAY:
 13.4098 -        fprintf(log," ");
 13.4099 -        for (dim=0; dim<sym->dim.arglist[arg].numdim; dim++) {
 13.4100 -          if (sym->dim.arglist[arg].dim[dim]==0) {
 13.4101 -            fprintf(log,"[]");
 13.4102 -          } else {
 13.4103 -            //??? find index tag
 13.4104 -            fprintf(log,"[%d]",sym->dim.arglist[arg].dim[dim]);
 13.4105 -          } /* if */
 13.4106 -        } /* for */
 13.4107 -        break;
 13.4108 -      } /* switch */
 13.4109 -      if (paraminfo)
 13.4110 -        fprintf(log," </paraminfo>\n");
 13.4111 -      /* print the user description of the parameter (parse through
 13.4112 -       * sym->documentation)
 13.4113 -       */
 13.4114 -      if (sym->documentation!=NULL
 13.4115 -          && find_xmltag(sym->documentation, "param", "name", sym->dim.arglist[arg].name,
 13.4116 -                         &outer_start, &outer_length, &inner_start, &inner_length))
 13.4117 -      {
 13.4118 -        char *tail;
 13.4119 -        fprintf(log,"\t\t\t\t%.*s\n",inner_length,inner_start);
 13.4120 -        /* delete from documentation string */
 13.4121 -        tail=outer_start+outer_length;
 13.4122 -        memmove(outer_start,tail,strlen(tail)+1);
 13.4123 -      } /* if */
 13.4124 -      fprintf(log,"\t\t\t</param>\n");
 13.4125 -    } /* for */
 13.4126 -    if (sym->documentation!=NULL)
 13.4127 -      fprintf(log,"\t\t\t%s\n",sym->documentation);
 13.4128 -    fprintf(log,"\t\t</member>\n");
 13.4129 -  } /* for */
 13.4130 -
 13.4131 -  fprintf(log,"\n\t</members>\n");
 13.4132 -  fprintf(log,"</doc>\n");
 13.4133 -}
 13.4134 -#endif
 13.4135 -
 13.4136 -/* Every symbol has a referrer list, that contains the functions that use
 13.4137 - * the symbol. Now, if function "apple" is accessed by functions "banana" and
 13.4138 - * "citron", but neither function "banana" nor "citron" are used by anyone
 13.4139 - * else, then, by inference, function "apple" is not used either.
 13.4140 - */
 13.4141 -static void reduce_referrers(symbol *root)
 13.4142 -{
 13.4143 -  int i,restart;
 13.4144 -  symbol *sym,*ref;
 13.4145 -
 13.4146 -  do {
 13.4147 -    restart=0;
 13.4148 -    for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.4149 -      if (sym->parent!=NULL)
 13.4150 -        continue;                 /* hierarchical data type */
 13.4151 -      if (sym->ident==iFUNCTN
 13.4152 -          && (sym->usage & uNATIVE)==0
 13.4153 -          && (sym->usage & uPUBLIC)==0 && strcmp(sym->name,uMAINFUNC)!=0 && strcmp(sym->name,uENTRYFUNC)!=0
 13.4154 -          && count_referrers(sym)==0)
 13.4155 -      {
 13.4156 -        sym->usage&=~(uREAD | uWRITTEN);  /* erase usage bits if there is no referrer */
 13.4157 -        /* find all symbols that are referred by this symbol */
 13.4158 -        for (ref=root->next; ref!=NULL; ref=ref->next) {
 13.4159 -          if (ref->parent!=NULL)
 13.4160 -            continue;             /* hierarchical data type */
 13.4161 -          assert(ref->refer!=NULL);
 13.4162 -          for (i=0; i<ref->numrefers && ref->refer[i]!=sym; i++)
 13.4163 -            /* nothing */;
 13.4164 -          if (i<ref->numrefers) {
 13.4165 -            assert(ref->refer[i]==sym);
 13.4166 -            ref->refer[i]=NULL;
 13.4167 -            restart++;
 13.4168 -          } /* if */
 13.4169 -        } /* for */
 13.4170 -      } else if ((sym->ident==iVARIABLE || sym->ident==iARRAY)
 13.4171 -                 && (sym->usage & uPUBLIC)==0
 13.4172 -                 && sym->parent==NULL
 13.4173 -                 && count_referrers(sym)==0)
 13.4174 -      {
 13.4175 -        sym->usage&=~(uREAD | uWRITTEN);  /* erase usage bits if there is no referrer */
 13.4176 -      } /* if */
 13.4177 -    } /* for */
 13.4178 -    /* after removing a symbol, check whether more can be removed */
 13.4179 -  } while (restart>0);
 13.4180 -}
 13.4181 -
 13.4182 -#if !defined SC_LIGHT
 13.4183 -static long max_stacksize_recurse(symbol *sourcesym,symbol *sym,long basesize,int *pubfuncparams,int *recursion)
 13.4184 -{
 13.4185 -  long size,maxsize;
 13.4186 -  int i;
 13.4187 -
 13.4188 -  assert(sym!=NULL);
 13.4189 -  assert(sym->ident==iFUNCTN);
 13.4190 -  assert((sym->usage & uNATIVE)==0);
 13.4191 -  assert(recursion!=NULL);
 13.4192 -
 13.4193 -  maxsize=sym->x.stacksize;
 13.4194 -  for (i=0; i<sym->numrefers; i++) {
 13.4195 -    if (sym->refer[i]!=NULL) {
 13.4196 -      assert(sym->refer[i]->ident==iFUNCTN);
 13.4197 -      assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */
 13.4198 -      if (sym->refer[i]==sourcesym) {   /* recursion detection */
 13.4199 -        *recursion=1;
 13.4200 -        break;                          /* recursion was detected, quit loop */
 13.4201 -      } /* if */
 13.4202 -      size=max_stacksize_recurse(sourcesym,sym->refer[i],sym->x.stacksize,pubfuncparams,recursion);
 13.4203 -      if (maxsize<size)
 13.4204 -        maxsize=size;
 13.4205 -    } /* if */
 13.4206 -  } /* for */
 13.4207 -
 13.4208 -  if ((sym->usage & uPUBLIC)!=0) {
 13.4209 -    /* Find out how many parameters a public function has, then see if this
 13.4210 -     * is bigger than some maximum
 13.4211 -     */
 13.4212 -    arginfo *arg=sym->dim.arglist;
 13.4213 -    int count=0;
 13.4214 -    assert(arg!=0);
 13.4215 -    while (arg->ident!=0) {
 13.4216 -      count++;
 13.4217 -      arg++;
 13.4218 -    } /* while */
 13.4219 -    assert(pubfuncparams!=0);
 13.4220 -    if (count>*pubfuncparams)
 13.4221 -      *pubfuncparams=count;
 13.4222 -  } /* if */
 13.4223 -
 13.4224 -  return maxsize+basesize;
 13.4225 -}
 13.4226 -
 13.4227 -static long max_stacksize(symbol *root,int *recursion)
 13.4228 -{
 13.4229 -  /* Loop over all non-native functions. For each function, loop
 13.4230 -   * over all of its referrers, accumulating the stack requirements.
 13.4231 -   * Detect (indirect) recursion with a "mark-and-sweep" algorithm.
 13.4232 -   * I (mis-)use the "compound" field of the symbol structure for
 13.4233 -   * the marker, as this field is unused for functions.
 13.4234 -   *
 13.4235 -   * Note that the stack is shared with the heap. A host application
 13.4236 -   * may "eat" cells from the heap as well, through amx_Allot(). The
 13.4237 -   * stack requirements are thus only an estimate.
 13.4238 -   */
 13.4239 -  long size,maxsize;
 13.4240 -  int maxparams;
 13.4241 -  symbol *sym;
 13.4242 -
 13.4243 -  assert(root!=NULL);
 13.4244 -  assert(recursion!=NULL);
 13.4245 -  #if !defined NDEBUG
 13.4246 -    for (sym=root->next; sym!=NULL; sym=sym->next)
 13.4247 -      if (sym->ident==iFUNCTN)
 13.4248 -        assert(sym->compound==0);
 13.4249 -  #endif
 13.4250 -
 13.4251 -  maxsize=0;
 13.4252 -  maxparams=0;
 13.4253 -  *recursion=0;         /* assume no recursion */
 13.4254 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
 13.4255 -    /* drop out if this is not a user-implemented function */
 13.4256 -    if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0)
 13.4257 -      continue;
 13.4258 -    /* accumulate stack size for this symbol */
 13.4259 -    size=max_stacksize_recurse(sym,sym,0L,&maxparams,recursion);
 13.4260 -    assert(size>=0);
 13.4261 -    if (maxsize<size)
 13.4262 -      maxsize=size;
 13.4263 -  } /* for */
 13.4264 -
 13.4265 -  maxsize++;                  /* +1 because a zero cell is always pushed on top
 13.4266 -                               * of the stack to catch stack overwrites */
 13.4267 -  return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */
 13.4268 -}
 13.4269 -#endif
 13.4270 -
 13.4271 -/*  testsymbols - test for unused local or global variables
 13.4272 - *
 13.4273 - *  "Public" functions are excluded from the check, since these
 13.4274 - *  may be exported to other object modules.
 13.4275 - *  Labels are excluded from the check if the argument 'testlabs'
 13.4276 - *  is 0. Thus, labels are not tested until the end of the function.
 13.4277 - *  Constants may also be excluded (convenient for global constants).
 13.4278 - *
 13.4279 - *  When the nesting level drops below "level", the check stops.
 13.4280 - *
 13.4281 - *  The function returns whether there is an "entry" point for the file.
 13.4282 - *  This flag will only be 1 when browsing the global symbol table.
 13.4283 - */
 13.4284 -static int testsymbols(symbol *root,int level,int testlabs,int testconst)
 13.4285 -{
 13.4286 -  char symname[2*sNAMEMAX+16];
 13.4287 -  int entry=FALSE;
 13.4288 -
 13.4289 -  symbol *sym=root->next;
 13.4290 -  while (sym!=NULL && sym->compound>=level) {
 13.4291 -    switch (sym->ident) {
 13.4292 -    case iLABEL:
 13.4293 -      if (testlabs) {
 13.4294 -        if ((sym->usage & uDEFINE)==0) {
 13.4295 -          error(19,sym->name);      /* not a label: ... */
 13.4296 -        } else if ((sym->usage & uREAD)==0) {
 13.4297 -          errorset(sSETPOS,sym->lnumber);
 13.4298 -          error(203,sym->name);     /* symbol isn't used: ... */
 13.4299 -        } /* if */
 13.4300 -      } /* if */
 13.4301 -      break;
 13.4302 -    case iFUNCTN:
 13.4303 -      if ((sym->usage & (uDEFINE | uREAD | uNATIVE | uSTOCK | uPUBLIC))==uDEFINE) {
 13.4304 -        funcdisplayname(symname,sym->name);
 13.4305 -        if (strlen(symname)>0)
 13.4306 -          error(203,symname);       /* symbol isn't used ... (and not public/native/stock) */
 13.4307 -      } /* if */
 13.4308 -      if ((sym->usage & uPUBLIC)!=0 || strcmp(sym->name,uMAINFUNC)==0)
 13.4309 -        entry=TRUE;                 /* there is an entry point */
 13.4310 -      /* also mark the function to the debug information */
 13.4311 -      if (((sym->usage & uREAD)!=0 || (sym->usage & uPUBLIC)!=0) && (sym->usage & uNATIVE)==0)
 13.4312 -        insert_dbgsymbol(sym);
 13.4313 -      break;
 13.4314 -    case iCONSTEXPR:
 13.4315 -      if (testconst && (sym->usage & uREAD)==0) {
 13.4316 -        errorset(sSETPOS,sym->lnumber);
 13.4317 -        error(203,sym->name);       /* symbol isn't used: ... */
 13.4318 -      } /* if */
 13.4319 -      break;
 13.4320 -    default:
 13.4321 -      /* a variable */
 13.4322 -      if (sym->parent!=NULL)
 13.4323 -        break;                      /* hierarchical data type */
 13.4324 -      if ((sym->usage & (uWRITTEN | uREAD | uSTOCK))==0) {
 13.4325 -        if (testconst)
 13.4326 -          errorset(sSETPOS,sym->lnumber);
 13.4327 -        error(203,sym->name,sym->lnumber);  /* symbol isn't used (and not stock) */
 13.4328 -      } else if ((sym->usage & (uREAD | uSTOCK | uPUBLIC))==0) {
 13.4329 -        errorset(sSETPOS,sym->lnumber);
 13.4330 -        error(204,sym->name);       /* value assigned to symbol is never used */
 13.4331 -#if 0 // ??? not sure whether it is a good idea to force people use "const"
 13.4332 -      } else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) {
 13.4333 -        errorset(sSETPOS,sym->lnumber);
 13.4334 -        error(214,sym->name);       /* make array argument "const" */
 13.4335 -#endif
 13.4336 -      } /* if */
 13.4337 -      /* also mark the variable (local or global) to the debug information */
 13.4338 -      if ((sym->usage & (uWRITTEN | uREAD))!=0 && (sym->usage & uNATIVE)==0)
 13.4339 -        insert_dbgsymbol(sym);
 13.4340 -    } /* if */
 13.4341 -    sym=sym->next;
 13.4342 -  } /* while */
 13.4343 -
 13.4344 -  return entry;
 13.4345 -}
 13.4346 -
 13.4347 -static cell calc_array_datasize(symbol *sym, cell *offset)
 13.4348 -{
 13.4349 -  cell length;
 13.4350 -
 13.4351 -  assert(sym!=NULL);
 13.4352 -  assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
 13.4353 -  length=sym->dim.array.length;
 13.4354 -  if (sym->dim.array.level > 0) {
 13.4355 -    cell sublength=calc_array_datasize(finddepend(sym),offset);
 13.4356 -    if (offset!=NULL)
 13.4357 -      *offset=length*(*offset+sizeof(cell));
 13.4358 -    if (sublength>0)
 13.4359 -      length*=length*sublength;
 13.4360 -    else
 13.4361 -      length=0;
 13.4362 -  } else {
 13.4363 -    if (offset!=NULL)
 13.4364 -      *offset=0;
 13.4365 -  } /* if */
 13.4366 -  return length;
 13.4367 -}
 13.4368 -
 13.4369 -static void destructsymbols(symbol *root,int level)
 13.4370 -{
 13.4371 -  cell offset=0;
 13.4372 -  int savepri=FALSE;
 13.4373 -  symbol *sym=root->next;
 13.4374 -  while (sym!=NULL && sym->compound>=level) {
 13.4375 -    if (sym->ident==iVARIABLE || sym->ident==iARRAY) {
 13.4376 -      char symbolname[16];
 13.4377 -      symbol *opsym;
 13.4378 -      cell elements;
 13.4379 -      /* check that the '~' operator is defined for this tag */
 13.4380 -      operator_symname(symbolname,"~",sym->tag,0,1,0);
 13.4381 -      if ((opsym=findglb(symbolname,sGLOBAL))!=NULL) {
 13.4382 -        /* save PRI, in case of a return statment */
 13.4383 -        if (!savepri) {
 13.4384 -          pushreg(sPRI);        /* right-hand operand is in PRI */
 13.4385 -          savepri=TRUE;
 13.4386 -        } /* if */
 13.4387 -        /* if the variable is an array, get the number of elements */
 13.4388 -        if (sym->ident==iARRAY) {
 13.4389 -          elements=calc_array_datasize(sym,&offset);
 13.4390 -          /* "elements" can be zero when the variable is declared like
 13.4391 -           *    new mytag: myvar[2][] = { {1, 2}, {3, 4} }
 13.4392 -           * one should declare all dimensions!
 13.4393 -           */
 13.4394 -          if (elements==0)
 13.4395 -            error(46,sym->name);        /* array size is unknown */
 13.4396 -        } else {
 13.4397 -          elements=1;
 13.4398 -          offset=0;
 13.4399 -        } /* if */
 13.4400 -        pushval(elements);
 13.4401 -        /* call the '~' operator */
 13.4402 -        address(sym,sPRI);
 13.4403 -        addconst(offset);       /* add offset to array data to the address */
 13.4404 -        pushreg(sPRI);
 13.4405 -        pushval(2*sizeof(cell));/* 2 parameters */
 13.4406 -        assert(opsym->ident==iFUNCTN);
 13.4407 -        ffcall(opsym,NULL,1);
 13.4408 -        if (sc_status!=statSKIP)
 13.4409 -          markusage(opsym,uREAD);   /* do not mark as "used" when this call itself is skipped */
 13.4410 -        if ((opsym->usage & uNATIVE)!=0 && opsym->x.lib!=NULL)
 13.4411 -          opsym->x.lib->value += 1; /* increment "usage count" of the library */
 13.4412 -      } /* if */
 13.4413 -    } /* if */
 13.4414 -    sym=sym->next;
 13.4415 -  } /* while */
 13.4416 -  /* restore PRI, if it was saved */
 13.4417 -  if (savepri)
 13.4418 -    popreg(sPRI);
 13.4419 -}
 13.4420 -
 13.4421 -static constvalue *insert_constval(constvalue *prev,constvalue *next,const char *name,cell val,
 13.4422 -                                   int index)
 13.4423 -{
 13.4424 -  constvalue *cur;
 13.4425 -
 13.4426 -  if ((cur=(constvalue*)malloc(sizeof(constvalue)))==NULL)
 13.4427 -    error(103);       /* insufficient memory (fatal error) */
 13.4428 -  memset(cur,0,sizeof(constvalue));
 13.4429 -  if (name!=NULL) {
 13.4430 -    assert(strlen(name)<sNAMEMAX);
 13.4431 -    strcpy(cur->name,name);
 13.4432 -  } /* if */
 13.4433 -  cur->value=val;
 13.4434 -  cur->index=index;
 13.4435 -  cur->next=next;
 13.4436 -  prev->next=cur;
 13.4437 -  return cur;
 13.4438 -}
 13.4439 -
 13.4440 -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index)
 13.4441 -{
 13.4442 -  constvalue *cur,*prev;
 13.4443 -
 13.4444 -  /* find the end of the constant table */
 13.4445 -  for (prev=table, cur=table->next; cur!=NULL; prev=cur, cur=cur->next)
 13.4446 -    /* nothing */;
 13.4447 -  return insert_constval(prev,NULL,name,val,index);
 13.4448 -}
 13.4449 -
 13.4450 -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index)
 13.4451 -{
 13.4452 -  constvalue *ptr = table->next;
 13.4453 -
 13.4454 -  while (ptr!=NULL) {
 13.4455 -    if (strcmp(name,ptr->name)==0 && ptr->index==index)
 13.4456 -      return ptr;
 13.4457 -    ptr=ptr->next;
 13.4458 -  } /* while */
 13.4459 -  return NULL;
 13.4460 -}
 13.4461 -
 13.4462 -static constvalue *find_constval_byval(constvalue *table,cell val)
 13.4463 -{
 13.4464 -  constvalue *ptr = table->next;
 13.4465 -
 13.4466 -  while (ptr!=NULL) {
 13.4467 -    if (ptr->value==val)
 13.4468 -      return ptr;
 13.4469 -    ptr=ptr->next;
 13.4470 -  } /* while */
 13.4471 -  return NULL;
 13.4472 -}
 13.4473 -
 13.4474 -#if 0   /* never used */
 13.4475 -static int delete_constval(constvalue *table,char *name)
 13.4476 -{
 13.4477 -  constvalue *prev = table;
 13.4478 -  constvalue *cur = prev->next;
 13.4479 -
 13.4480 -  while (cur!=NULL) {
 13.4481 -    if (strcmp(name,cur->name)==0) {
 13.4482 -      prev->next=cur->next;
 13.4483 -      free(cur);
 13.4484 -      return TRUE;
 13.4485 -    } /* if */
 13.4486 -    prev=cur;
 13.4487 -    cur=cur->next;
 13.4488 -  } /* while */
 13.4489 -  return FALSE;
 13.4490 -}
 13.4491 -#endif
 13.4492 -
 13.4493 -SC_FUNC void delete_consttable(constvalue *table)
 13.4494 -{
 13.4495 -  constvalue *cur=table->next, *next;
 13.4496 -
 13.4497 -  while (cur!=NULL) {
 13.4498 -    next=cur->next;
 13.4499 -    free(cur);
 13.4500 -    cur=next;
 13.4501 -  } /* while */
 13.4502 -  memset(table,0,sizeof(constvalue));
 13.4503 -}
 13.4504 -
 13.4505 -/*  add_constant
 13.4506 - *
 13.4507 - *  Adds a symbol to the symbol table. Returns NULL on failure.
 13.4508 - */
 13.4509 -SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag)
 13.4510 -{
 13.4511 -  symbol *sym;
 13.4512 -
 13.4513 -  /* Test whether a global or local symbol with the same name exists. Since
 13.4514 -   * constants are stored in the symbols table, this also finds previously
 13.4515 -   * defind constants. */
 13.4516 -  sym=findglb(name,sSTATEVAR);
 13.4517 -  if (!sym)
 13.4518 -    sym=findloc(name);
 13.4519 -  if (sym) {
 13.4520 -    int redef=0;
 13.4521 -    if (sym->ident!=iCONSTEXPR)
 13.4522 -      redef=1;                  /* redefinition a function/variable to a constant is not allowed */
 13.4523 -    if ((sym->usage & uENUMFIELD)!=0) {
 13.4524 -      /* enum field, special case if it has a different tag and the new symbol is also an enum field */
 13.4525 -      constvalue *tagid;
 13.4526 -      symbol *tagsym;
 13.4527 -      if (sym->tag==tag)
 13.4528 -        redef=1;                /* enumeration field is redefined (same tag) */
 13.4529 -      tagid=find_tag_byval(tag);
 13.4530 -      if (tagid==NULL) {
 13.4531 -        redef=1;                /* new constant does not have a tag */
 13.4532 -      } else {
 13.4533 -        tagsym=findconst(tagid->name,NULL);
 13.4534 -        if (tagsym==NULL || (tagsym->usage & uENUMROOT)==0)
 13.4535 -          redef=1;              /* new constant is not an enumeration field */
 13.4536 -      } /* if */
 13.4537 -      /* in this particular case (enumeration field that is part of a different
 13.4538 -       * enum, and non-conflicting with plain constants) we want to be able to
 13.4539 -       * redefine it
 13.4540 -       */
 13.4541 -      if (!redef)
 13.4542 -        goto redef_enumfield;
 13.4543 -    } else if (sym->tag!=tag) {
 13.4544 -      redef=1;                  /* redefinition of a constant (non-enum) to a different tag is not allowed */
 13.4545 -    } /* if */
 13.4546 -    if (redef) {
 13.4547 -      error(21,name);           /* symbol already defined */
 13.4548 -      return NULL;
 13.4549 -    } else if (sym->addr!=val) {
 13.4550 -      error(201,name);          /* redefinition of constant (different value) */
 13.4551 -      sym->addr=val;            /* set new value */
 13.4552 -    } /* if */
 13.4553 -    /* silently ignore redefinitions of constants with the same value & tag */
 13.4554 -    return sym;
 13.4555 -  } /* if */
 13.4556 -
 13.4557 -  /* constant doesn't exist yet (or is allowed to be redefined) */
 13.4558 -redef_enumfield:
 13.4559 -  sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE);
 13.4560 -  assert(sym!=NULL);            /* fatal error 103 must be given on error */
 13.4561 -  if (sc_status == statIDLE)
 13.4562 -    sym->usage |= uPREDEF;
 13.4563 -  return sym;
 13.4564 -}
 13.4565 -
 13.4566 -/*  statement           - The Statement Parser
 13.4567 - *
 13.4568 - *  This routine is called whenever the parser needs to know what statement
 13.4569 - *  it encounters (i.e. whenever program syntax requires a statement).
 13.4570 - */
 13.4571 -static void statement(int *lastindent,int allow_decl)
 13.4572 -{
 13.4573 -  int tok;
 13.4574 -  cell val;
 13.4575 -  char *st;
 13.4576 -
 13.4577 -  if (!freading) {
 13.4578 -    error(36);                  /* empty statement */
 13.4579 -    return;
 13.4580 -  } /* if */
 13.4581 -  errorset(sRESET,0);
 13.4582 -
 13.4583 -  tok=lex(&val,&st);
 13.4584 -  if (tok!='{') {
 13.4585 -    insert_dbgline(fline);
 13.4586 -    setline(TRUE);
 13.4587 -  } /* if */
 13.4588 -  /* lex() has set stmtindent */
 13.4589 -  if (lastindent!=NULL && tok!=tLABEL) {
 13.4590 -    if (*lastindent>=0 && *lastindent!=stmtindent && !indent_nowarn && sc_tabsize>0)
 13.4591 -      error(217);               /* loose indentation */
 13.4592 -    *lastindent=stmtindent;
 13.4593 -    indent_nowarn=FALSE;        /* if warning was blocked, re-enable it */
 13.4594 -  } /* if */
 13.4595 -  switch (tok) {
 13.4596 -  case 0:
 13.4597 -    /* nothing */
 13.4598 -    break;
 13.4599 -  case tNEW:
 13.4600 -    if (allow_decl) {
 13.4601 -      autozero=1;
 13.4602 -      declloc(FALSE);
 13.4603 -      lastst=tNEW;
 13.4604 -    } else {
 13.4605 -      error(3);                 /* declaration only valid in a block */
 13.4606 -    } /* if */
 13.4607 -    break;
 13.4608 -  case tDECL:
 13.4609 -    if (allow_decl) {
 13.4610 -      autozero=0;
 13.4611 -      declloc(FALSE);
 13.4612 -      lastst=tDECL;
 13.4613 -    } else {
 13.4614 -      error(3);                 /* declaration only valid in a block */
 13.4615 -    } /* if */
 13.4616 -    break;
 13.4617 -  case tSTATIC:
 13.4618 -    if (allow_decl) {
 13.4619 -      declloc(TRUE);
 13.4620 -      lastst=tNEW;
 13.4621 -    } else {
 13.4622 -      error(3);                 /* declaration only valid in a block */
 13.4623 -    } /* if */
 13.4624 -    break;
 13.4625 -  case '{':
 13.4626 -    tok=fline;
 13.4627 -    if (!matchtoken('}'))       /* {} is the empty statement */
 13.4628 -      compound(tok==fline);
 13.4629 -    /* lastst (for "last statement") does not change */
 13.4630 -    break;
 13.4631 -  case ';':
 13.4632 -    error(36);                  /* empty statement */
 13.4633 -    break;
 13.4634 -  case tIF:
 13.4635 -    doif();
 13.4636 -    lastst=tIF;
 13.4637 -    break;
 13.4638 -  case tWHILE:
 13.4639 -    dowhile();
 13.4640 -    lastst=tWHILE;
 13.4641 -    break;
 13.4642 -  case tDO:
 13.4643 -    dodo();
 13.4644 -    lastst=tDO;
 13.4645 -    break;
 13.4646 -  case tFOR:
 13.4647 -    dofor();
 13.4648 -    lastst=tFOR;
 13.4649 -    break;
 13.4650 -  case tSWITCH:
 13.4651 -    doswitch();
 13.4652 -    lastst=tSWITCH;
 13.4653 -    break;
 13.4654 -  case tCASE:
 13.4655 -  case tDEFAULT:
 13.4656 -    error(14);     /* not in switch */
 13.4657 -    break;
 13.4658 -  case tGOTO:
 13.4659 -    dogoto();
 13.4660 -    lastst=tGOTO;
 13.4661 -    break;
 13.4662 -  case tLABEL:
 13.4663 -    dolabel();
 13.4664 -    lastst=tLABEL;
 13.4665 -    break;
 13.4666 -  case tRETURN:
 13.4667 -    doreturn();
 13.4668 -    lastst=tRETURN;
 13.4669 -    break;
 13.4670 -  case tBREAK:
 13.4671 -    dobreak();
 13.4672 -    lastst=tBREAK;
 13.4673 -    break;
 13.4674 -  case tCONTINUE:
 13.4675 -    docont();
 13.4676 -    lastst=tCONTINUE;
 13.4677 -    break;
 13.4678 -  case tEXIT:
 13.4679 -    doexit();
 13.4680 -    lastst=tEXIT;
 13.4681 -    break;
 13.4682 -  case tASSERT:
 13.4683 -    doassert();
 13.4684 -    lastst=tASSERT;
 13.4685 -    break;
 13.4686 -  case tSLEEP:
 13.4687 -    dosleep();
 13.4688 -    lastst=tSLEEP;
 13.4689 -    break;
 13.4690 -  case tSTATE:
 13.4691 -    dostate();
 13.4692 -    lastst=tSTATE;
 13.4693 -    break;
 13.4694 -  case tCONST:
 13.4695 -    decl_const(sLOCAL);
 13.4696 -    break;
 13.4697 -  case tENUM:
 13.4698 -    decl_enum(sLOCAL);
 13.4699 -    break;
 13.4700 -  default:          /* non-empty expression */
 13.4701 -    sc_allowproccall=optproccall;
 13.4702 -    lexpush();      /* analyze token later */
 13.4703 -    doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE);
 13.4704 -    needtoken(tTERM);
 13.4705 -    lastst=tEXPR;
 13.4706 -    sc_allowproccall=FALSE;
 13.4707 -  } /* switch */
 13.4708 -}
 13.4709 -
 13.4710 -static void compound(int stmt_sameline)
 13.4711 -{
 13.4712 -  int indent=-1;
 13.4713 -  cell save_decl=declared;
 13.4714 -  int count_stmt=0;
 13.4715 -  int block_start=fline;  /* save line where the compound block started */
 13.4716 -
 13.4717 -  /* if there is more text on this line, we should adjust the statement indent */
 13.4718 -  if (stmt_sameline) {
 13.4719 -    int i;
 13.4720 -    const unsigned char *p=lptr;
 13.4721 -    /* go back to the opening brace */
 13.4722 -    while (*p!='{') {
 13.4723 -      assert(p>pline);
 13.4724 -      p--;
 13.4725 -    } /* while */
 13.4726 -    assert(*p=='{');  /* it should be found */
 13.4727 -    /* go forward, skipping white-space */
 13.4728 -    p++;
 13.4729 -    while (*p<=' ' && *p!='\0')
 13.4730 -      p++;
 13.4731 -    assert(*p!='\0'); /* a token should be found */
 13.4732 -    stmtindent=0;
 13.4733 -    for (i=0; i<(int)(p-pline); i++)
 13.4734 -      if (pline[i]=='\t' && sc_tabsize>0)
 13.4735 -        stmtindent += (int)(sc_tabsize - (stmtindent+sc_tabsize) % sc_tabsize);
 13.4736 -      else
 13.4737 -        stmtindent++;
 13.4738 -  } /* if */
 13.4739 -
 13.4740 -  nestlevel+=1;                 /* increase compound statement level */
 13.4741 -  while (matchtoken('}')==0){   /* repeat until compound statement is closed */
 13.4742 -    if (!freading){
 13.4743 -      error(30,block_start);    /* compound block not closed at end of file */
 13.4744 -      break;
 13.4745 -    } else {
 13.4746 -      if (count_stmt>0 && (lastst==tRETURN || lastst==tBREAK || lastst==tCONTINUE))
 13.4747 -        error(225);             /* unreachable code */
 13.4748 -      statement(&indent,TRUE);  /* do a statement */
 13.4749 -      count_stmt++;
 13.4750 -    } /* if */
 13.4751 -  } /* while */
 13.4752 -  if (lastst!=tRETURN)
 13.4753 -    destructsymbols(&loctab,nestlevel);
 13.4754 -  if (lastst!=tRETURN && lastst!=tGOTO)
 13.4755 -    modstk((int)(declared-save_decl)*sizeof(cell)); /* delete local variable space */
 13.4756 -  testsymbols(&loctab,nestlevel,FALSE,TRUE);        /* look for unused block locals */
 13.4757 -  declared=save_decl;
 13.4758 -  delete_symbols(&loctab,nestlevel,FALSE,TRUE);     /* erase local symbols, but
 13.4759 -                                                     * retain block local labels
 13.4760 -                                                     * (within the function) */
 13.4761 -  nestlevel-=1;                 /* decrease compound statement level */
 13.4762 -}
 13.4763 -
 13.4764 -/*  doexpr
 13.4765 - *
 13.4766 - *  Global references: stgidx   (referred to only)
 13.4767 - */
 13.4768 -static int doexpr(int comma,int chkeffect,int allowarray,int mark_endexpr,
 13.4769 -                  int *tag,symbol **symptr,int chkfuncresult)
 13.4770 -{
 13.4771 -  int index,ident;
 13.4772 -  int localstaging=FALSE;
 13.4773 -  cell val;
 13.4774 -
 13.4775 -  if (!staging) {
 13.4776 -    stgset(TRUE);               /* start stage-buffering */
 13.4777 -    localstaging=TRUE;
 13.4778 -    assert(stgidx==0);
 13.4779 -  } /* if */
 13.4780 -  index=stgidx;
 13.4781 -  errorset(sEXPRMARK,0);
 13.4782 -  do {
 13.4783 -    /* on second round through, mark the end of the previous expression */
 13.4784 -    if (index!=stgidx)
 13.4785 -      markexpr(sEXPR,NULL,0);
 13.4786 -    sideeffect=FALSE;
 13.4787 -    ident=expression(&val,tag,symptr,chkfuncresult);
 13.4788 -    if (!allowarray && (ident==iARRAY || ident==iREFARRAY))
 13.4789 -      error(33,"-unknown-");    /* array must be indexed */
 13.4790 -    if (chkeffect && !sideeffect)
 13.4791 -      error(215);               /* expression has no effect */
 13.4792 -    sc_allowproccall=FALSE;     /* cannot use "procedure call" syntax anymore */
 13.4793 -  } while (comma && matchtoken(',')); /* more? */
 13.4794 -  if (mark_endexpr)
 13.4795 -    markexpr(sEXPR,NULL,0);     /* optionally, mark the end of the expression */
 13.4796 -  errorset(sEXPRRELEASE,0);
 13.4797 -  if (localstaging) {
 13.4798 -    stgout(index);
 13.4799 -    stgset(FALSE);              /* stop staging */
 13.4800 -  } /* if */
 13.4801 -  return ident;
 13.4802 -}
 13.4803 -
 13.4804 -/*  constexpr
 13.4805 - */
 13.4806 -SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr)
 13.4807 -{
 13.4808 -  int ident,index;
 13.4809 -  cell cidx;
 13.4810 -
 13.4811 -  stgset(TRUE);         /* start stage-buffering */
 13.4812 -  stgget(&index,&cidx); /* mark position in code generator */
 13.4813 -  errorset(sEXPRMARK,0);
 13.4814 -  ident=expression(val,tag,symptr,FALSE);
 13.4815 -  stgdel(index,cidx);   /* scratch generated code */
 13.4816 -  stgset(FALSE);        /* stop stage-buffering */
 13.4817 -  if (ident!=iCONSTEXPR) {
 13.4818 -    error(8);           /* must be constant expression */
 13.4819 -    if (val!=NULL)
 13.4820 -      *val=0;
 13.4821 -    if (tag!=NULL)
 13.4822 -      *tag=0;
 13.4823 -    if (symptr!=NULL)
 13.4824 -      *symptr=NULL;
 13.4825 -  } /* if */
 13.4826 -  errorset(sEXPRRELEASE,0);
 13.4827 -  return (ident==iCONSTEXPR);
 13.4828 -}
 13.4829 -
 13.4830 -/*  test
 13.4831 - *
 13.4832 - *  In the case a "simple assignment" operator ("=") is used within a test,
 13.4833 - *  the warning "possibly unintended assignment" is displayed. This routine
 13.4834 - *  sets the global variable "sc_intest" to true, it is restored upon termination.
 13.4835 - *  In the case the assignment was intended, use parantheses around the
 13.4836 - *  expression to avoid the warning; primary() sets "sc_intest" to 0.
 13.4837 - *
 13.4838 - *  Global references: sc_intest (altered, but restored upon termination)
 13.4839 - */
 13.4840 -static void test(int label,int parens,int invert)
 13.4841 -{
 13.4842 -  int index,tok;
 13.4843 -  cell cidx;
 13.4844 -  int ident,tag;
 13.4845 -  cell constval;
 13.4846 -  symbol *sym;
 13.4847 -  int localstaging=FALSE;
 13.4848 -
 13.4849 -  if (!staging) {
 13.4850 -    stgset(TRUE);               /* start staging */
 13.4851 -    localstaging=TRUE;
 13.4852 -    #if !defined NDEBUG
 13.4853 -      stgget(&index,&cidx);     /* should start at zero if started locally */
 13.4854 -      assert(index==0);
 13.4855 -    #endif
 13.4856 -  } /* if */
 13.4857 -
 13.4858 -  PUSHSTK_I(sc_intest);
 13.4859 -  sc_intest=TRUE;
 13.4860 -  if (parens)
 13.4861 -    needtoken('(');
 13.4862 -  do {
 13.4863 -    stgget(&index,&cidx);       /* mark position (of last expression) in
 13.4864 -                                 * code generator */
 13.4865 -    ident=expression(&constval,&tag,&sym,TRUE);
 13.4866 -    tok=matchtoken(',');
 13.4867 -    if (tok)
 13.4868 -      markexpr(sEXPR,NULL,0);
 13.4869 -  } while (tok); /* do */
 13.4870 -  if (parens)
 13.4871 -    needtoken(')');
 13.4872 -  if (ident==iARRAY || ident==iREFARRAY) {
 13.4873 -    char *ptr=(sym->name!=NULL) ? sym->name : "-unknown-";
 13.4874 -    error(33,ptr);              /* array must be indexed */
 13.4875 -  } /* if */
 13.4876 -  if (ident==iCONSTEXPR) {      /* constant expression */
 13.4877 -    sc_intest=(short)POPSTK_I();/* restore stack */
 13.4878 -    stgdel(index,cidx);
 13.4879 -    if (constval) {             /* code always executed */
 13.4880 -      error(206);               /* redundant test: always non-zero */
 13.4881 -    } else {
 13.4882 -      error(205);               /* redundant code: never executed */
 13.4883 -      jumplabel(label);
 13.4884 -    } /* if */
 13.4885 -    if (localstaging) {
 13.4886 -      stgout(0);                /* write "jumplabel" code */
 13.4887 -      stgset(FALSE);            /* stop staging */
 13.4888 -    } /* if */
 13.4889 -    return;
 13.4890 -  } /* if */
 13.4891 -  if (tag!=0 && tag!=pc_addtag("bool"))
 13.4892 -    if (check_userop(lneg,tag,0,1,NULL,&tag))
 13.4893 -      invert= !invert;          /* user-defined ! operator inverted result */
 13.4894 -  if (invert)
 13.4895 -    jmp_ne0(label);             /* jump to label if true (different from 0) */
 13.4896 -  else
 13.4897 -    jmp_eq0(label);             /* jump to label if false (equal to 0) */
 13.4898 -  markexpr(sEXPR,NULL,0);       /* end expression (give optimizer a chance) */
 13.4899 -  sc_intest=(short)POPSTK_I();  /* double typecast to avoid warning with Microsoft C */
 13.4900 -  if (localstaging) {
 13.4901 -    stgout(0);                  /* output queue from the very beginning (see
 13.4902 -                                 * assert() when localstaging is set to TRUE) */
 13.4903 -    stgset(FALSE);              /* stop staging */
 13.4904 -  } /* if */
 13.4905 -}
 13.4906 -
 13.4907 -static void doif(void)
 13.4908 -{
 13.4909 -  int flab1,flab2;
 13.4910 -  int ifindent;
 13.4911 -
 13.4912 -  ifindent=stmtindent;          /* save the indent of the "if" instruction */
 13.4913 -  flab1=getlabel();             /* get label number for false branch */
 13.4914 -  test(flab1,TRUE,FALSE);       /* get expression, branch to flab1 if false */
 13.4915 -  statement(NULL,FALSE);        /* if true, do a statement */
 13.4916 -  if (matchtoken(tELSE)==0){    /* if...else ? */
 13.4917 -    setlabel(flab1);            /* no, simple if..., print false label */
 13.4918 -  } else {
 13.4919 -    /* to avoid the "dangling else" error, we want a warning if the "else"
 13.4920 -     * has a lower indent than the matching "if" */
 13.4921 -    if (stmtindent<ifindent && sc_tabsize>0)
 13.4922 -      error(217);               /* loose indentation */
 13.4923 -    flab2=getlabel();
 13.4924 -    if ((lastst!=tRETURN) && (lastst!=tGOTO))
 13.4925 -      jumplabel(flab2);
 13.4926 -    setlabel(flab1);            /* print false label */
 13.4927 -    statement(NULL,FALSE);      /* do "else" clause */
 13.4928 -    setlabel(flab2);            /* print true label */
 13.4929 -  } /* endif */
 13.4930 -}
 13.4931 -
 13.4932 -static void dowhile(void)
 13.4933 -{
 13.4934 -  int wq[wqSIZE];               /* allocate local queue */
 13.4935 -
 13.4936 -  addwhile(wq);                 /* add entry to queue for "break" */
 13.4937 -  setlabel(wq[wqLOOP]);         /* loop label */
 13.4938 -  /* The debugger uses the "break" opcode to be able to "break" out of
 13.4939 -   * a loop. To make sure that each loop has a break opcode, even for the
 13.4940 -   * tiniest loop, set it below the top of the loop
 13.4941 -   */
 13.4942 -  setline(TRUE);
 13.4943 -  test(wq[wqEXIT],TRUE,FALSE);  /* branch to wq[wqEXIT] if false */
 13.4944 -  statement(NULL,FALSE);        /* if so, do a statement */
 13.4945 -  jumplabel(wq[wqLOOP]);        /* and loop to "while" start */
 13.4946 -  setlabel(wq[wqEXIT]);         /* exit label */
 13.4947 -  delwhile();                   /* delete queue entry */
 13.4948 -}
 13.4949 -
 13.4950 -/*
 13.4951 - *  Note that "continue" will in this case not jump to the top of the loop, but
 13.4952 - *  to the end: just before the TRUE-or-FALSE testing code.
 13.4953 - */
 13.4954 -static void dodo(void)
 13.4955 -{
 13.4956 -  int wq[wqSIZE],top;
 13.4957 -
 13.4958 -  addwhile(wq);           /* see "dowhile" for more info */
 13.4959 -  top=getlabel();         /* make a label first */
 13.4960 -  setlabel(top);          /* loop label */
 13.4961 -  statement(NULL,FALSE);
 13.4962 -  needtoken(tWHILE);
 13.4963 -  setlabel(wq[wqLOOP]);   /* "continue" always jumps to WQLOOP. */
 13.4964 -  setline(TRUE);
 13.4965 -  test(wq[wqEXIT],TRUE,FALSE);
 13.4966 -  jumplabel(top);
 13.4967 -  setlabel(wq[wqEXIT]);
 13.4968 -  delwhile();
 13.4969 -  needtoken(tTERM);
 13.4970 -}
 13.4971 -
 13.4972 -static void dofor(void)
 13.4973 -{
 13.4974 -  int wq[wqSIZE],skiplab;
 13.4975 -  cell save_decl;
 13.4976 -  int save_nestlevel,index;
 13.4977 -  int *ptr;
 13.4978 -
 13.4979 -  save_decl=declared;
 13.4980 -  save_nestlevel=nestlevel;
 13.4981 -
 13.4982 -  addwhile(wq);
 13.4983 -  skiplab=getlabel();
 13.4984 -  needtoken('(');
 13.4985 -  if (matchtoken(';')==0) {
 13.4986 -    /* new variable declarations are allowed here */
 13.4987 -    if (matchtoken(tNEW)) {
 13.4988 -      /* The variable in expr1 of the for loop is at a
 13.4989 -       * 'compound statement' level of it own.
 13.4990 -       */
 13.4991 -      nestlevel++;
 13.4992 -      autozero=1;
 13.4993 -      declloc(FALSE); /* declare local variable */
 13.4994 -    } else {
 13.4995 -      doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE);  /* expression 1 */
 13.4996 -      needtoken(';');
 13.4997 -    } /* if */
 13.4998 -  } /* if */
 13.4999 -  /* Adjust the "declared" field in the "while queue", in case that
 13.5000 -   * local variables were declared in the first expression of the
 13.5001 -   * "for" loop. These are deleted in separately, so a "break" or a "continue"
 13.5002 -   * must ignore these fields.
 13.5003 -   */
 13.5004 -  ptr=readwhile();
 13.5005 -  assert(ptr!=NULL);
 13.5006 -  ptr[wqBRK]=(int)declared;
 13.5007 -  ptr[wqCONT]=(int)declared;
 13.5008 -  jumplabel(skiplab);               /* skip expression 3 1st time */
 13.5009 -  setlabel(wq[wqLOOP]);             /* "continue" goes to this label: expr3 */
 13.5010 -  setline(TRUE);
 13.5011 -  /* Expressions 2 and 3 are reversed in the generated code: expression 3
 13.5012 -   * precedes expression 2. When parsing, the code is buffered and marks for
 13.5013 -   * the start of each expression are insterted in the buffer.
 13.5014 -   */
 13.5015 -  assert(!staging);
 13.5016 -  stgset(TRUE);                     /* start staging */
 13.5017 -  assert(stgidx==0);
 13.5018 -  index=stgidx;
 13.5019 -  stgmark(sSTARTREORDER);
 13.5020 -  stgmark((char)(sEXPRSTART+0));    /* mark start of 2nd expression in stage */
 13.5021 -  setlabel(skiplab);                /* jump to this point after 1st expression */
 13.5022 -  if (matchtoken(';')==0) {
 13.5023 -    test(wq[wqEXIT],FALSE,FALSE);   /* expression 2 (jump to wq[wqEXIT] if false) */
 13.5024 -    needtoken(';');
 13.5025 -  } /* if */
 13.5026 -  stgmark((char)(sEXPRSTART+1));    /* mark start of 3th expression in stage */
 13.5027 -  if (matchtoken(')')==0) {
 13.5028 -    doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE);    /* expression 3 */
 13.5029 -    needtoken(')');
 13.5030 -  } /* if */
 13.5031 -  stgmark(sENDREORDER);             /* mark end of reversed evaluation */
 13.5032 -  stgout(index);
 13.5033 -  stgset(FALSE);                    /* stop staging */
 13.5034 -  statement(NULL,FALSE);
 13.5035 -  jumplabel(wq[wqLOOP]);
 13.5036 -  setlabel(wq[wqEXIT]);
 13.5037 -  delwhile();
 13.5038 -
 13.5039 -  assert(nestlevel>=save_nestlevel);
 13.5040 -  if (nestlevel>save_nestlevel) {
 13.5041 -    /* Clean up the space and the symbol table for the local
 13.5042 -     * variable in "expr1".
 13.5043 -     */
 13.5044 -    destructsymbols(&loctab,nestlevel);
 13.5045 -    modstk((int)(declared-save_decl)*sizeof(cell));
 13.5046 -    testsymbols(&loctab,nestlevel,FALSE,TRUE);  /* look for unused block locals */
 13.5047 -    declared=save_decl;
 13.5048 -    delete_symbols(&loctab,nestlevel,FALSE,TRUE);
 13.5049 -    nestlevel=save_nestlevel;     /* reset 'compound statement' nesting level */
 13.5050 -  } /* if */
 13.5051 -}
 13.5052 -
 13.5053 -/* The switch statement is incompatible with its C sibling:
 13.5054 - * 1. the cases are not drop through
 13.5055 - * 2. only one instruction may appear below each case, use a compound
 13.5056 - *    instruction to execute multiple instructions
 13.5057 - * 3. the "case" keyword accepts a comma separated list of values to
 13.5058 - *    match, it also accepts a range using the syntax "1 .. 4"
 13.5059 - *
 13.5060 - * SWITCH param
 13.5061 - *   PRI = expression result
 13.5062 - *   param = table offset (code segment)
 13.5063 - *
 13.5064 - */
 13.5065 -static void doswitch(void)
 13.5066 -{
 13.5067 -  int lbl_table,lbl_exit,lbl_case;
 13.5068 -  int tok,swdefault,casecount;
 13.5069 -  cell val;
 13.5070 -  char *str;
 13.5071 -  constvalue caselist = { NULL, "", 0, 0};   /* case list starts empty */
 13.5072 -  constvalue *cse,*csp;
 13.5073 -  char labelname[sNAMEMAX+1];
 13.5074 -
 13.5075 -  needtoken('(');
 13.5076 -  doexpr(TRUE,FALSE,FALSE,FALSE,NULL,NULL,TRUE);/* evaluate switch expression */
 13.5077 -  needtoken(')');
 13.5078 -  /* generate the code for the switch statement, the label is the address
 13.5079 -   * of the case table (to be generated later).
 13.5080 -   */
 13.5081 -  lbl_table=getlabel();
 13.5082 -  lbl_case=0;                   /* just to avoid a compiler warning */
 13.5083 -  ffswitch(lbl_table);
 13.5084 -
 13.5085 -  needtoken('{');
 13.5086 -  lbl_exit=getlabel();          /* get label number for jumping out of switch */
 13.5087 -  swdefault=FALSE;
 13.5088 -  casecount=0;
 13.5089 -  do {
 13.5090 -    tok=lex(&val,&str);         /* read in (new) token */
 13.5091 -    switch (tok) {
 13.5092 -    case tCASE:
 13.5093 -      if (swdefault!=FALSE)
 13.5094 -        error(15);        /* "default" case must be last in switch statement */
 13.5095 -      lbl_case=getlabel();
 13.5096 -      PUSHSTK_I(sc_allowtags);
 13.5097 -      sc_allowtags=FALSE; /* do not allow tagnames here */
 13.5098 -      do {
 13.5099 -        casecount++;
 13.5100 -
 13.5101 -        /* ??? enforce/document that, in a switch, a statement cannot start
 13.5102 -         *     with a label. Then, you can search for:
 13.5103 -         *     * the first semicolon (marks the end of a statement)
 13.5104 -         *     * an opening brace (marks the start of a compound statement)
 13.5105 -         *     and search for the right-most colon before that statement
 13.5106 -         *     Now, by replacing the ':' by a special COLON token, you can
 13.5107 -         *     parse all expressions until that special token.
 13.5108 -         */
 13.5109 -
 13.5110 -        constexpr(&val,NULL,NULL);
 13.5111 -        /* Search the insertion point (the table is kept in sorted order, so
 13.5112 -         * that advanced abstract machines can sift the case table with a
 13.5113 -         * binary search). Check for duplicate case values at the same time.
 13.5114 -         */
 13.5115 -        for (csp=&caselist, cse=caselist.next;
 13.5116 -             cse!=NULL && cse->value<val;
 13.5117 -             csp=cse, cse=cse->next)
 13.5118 -          /* nothing */;
 13.5119 -        if (cse!=NULL && cse->value==val)
 13.5120 -          error(40,val);                /* duplicate "case" label */
 13.5121 -        /* Since the label is stored as a string in the "constvalue", the
 13.5122 -         * size of an identifier must be at least 8, as there are 8
 13.5123 -         * hexadecimal digits in a 32-bit number.
 13.5124 -         */
 13.5125 -        #if sNAMEMAX < 8
 13.5126 -          #error Length of identifier (sNAMEMAX) too small.
 13.5127 -        #endif
 13.5128 -        assert(csp!=NULL);
 13.5129 -        assert(csp->next==cse);
 13.5130 -        insert_constval(csp,cse,itoh(lbl_case),val,0);
 13.5131 -        if (matchtoken(tDBLDOT)) {
 13.5132 -          cell end;
 13.5133 -          constexpr(&end,NULL,NULL);
 13.5134 -          if (end<=val)
 13.5135 -            error(50);                  /* invalid range */
 13.5136 -          while (++val<=end) {
 13.5137 -            casecount++;
 13.5138 -            /* find the new insertion point */
 13.5139 -            for (csp=&caselist, cse=caselist.next;
 13.5140 -                 cse!=NULL && cse->value<val;
 13.5141 -                 csp=cse, cse=cse->next)
 13.5142 -              /* nothing */;
 13.5143 -            if (cse!=NULL && cse->value==val)
 13.5144 -              error(40,val);            /* duplicate "case" label */
 13.5145 -            assert(csp!=NULL);
 13.5146 -            assert(csp->next==cse);
 13.5147 -            insert_constval(csp,cse,itoh(lbl_case),val,0);
 13.5148 -          } /* if */
 13.5149 -        } /* if */
 13.5150 -      } while (matchtoken(','));
 13.5151 -      needtoken(':');                   /* ':' ends the case */
 13.5152 -      sc_allowtags=(short)POPSTK_I();   /* reset */
 13.5153 -      setlabel(lbl_case);
 13.5154 -      statement(NULL,FALSE);
 13.5155 -      jumplabel(lbl_exit);
 13.5156 -      break;
 13.5157 -    case tDEFAULT:
 13.5158 -      if (swdefault!=FALSE)
 13.5159 -        error(16);         /* multiple defaults in switch */
 13.5160 -      lbl_case=getlabel();
 13.5161 -      setlabel(lbl_case);
 13.5162 -      needtoken(':');
 13.5163 -      swdefault=TRUE;
 13.5164 -      statement(NULL,FALSE);
 13.5165 -      /* Jump to lbl_exit, even thouh this is the last clause in the
 13.5166 -       * switch, because the jump table is generated between the last
 13.5167 -       * clause of the switch and the exit label.
 13.5168 -       */
 13.5169 -      jumplabel(lbl_exit);
 13.5170 -      break;
 13.5171 -    case '}':
 13.5172 -      /* nothing, but avoid dropping into "default" */
 13.5173 -      break;
 13.5174 -    default:
 13.5175 -      error(2);
 13.5176 -      indent_nowarn=TRUE; /* disable this check */
 13.5177 -      tok='}';          /* break out of the loop after an error */
 13.5178 -    } /* switch */
 13.5179 -  } while (tok!='}');
 13.5180 -
 13.5181 -  #if !defined NDEBUG
 13.5182 -    /* verify that the case table is sorted (unfortunatly, duplicates can
 13.5183 -     * occur; there really shouldn't be duplicate cases, but the compiler
 13.5184 -     * may not crash or drop into an assertion for a user error). */
 13.5185 -    for (cse=caselist.next; cse!=NULL && cse->next!=NULL; cse=cse->next)
 13.5186 -      assert(cse->value <= cse->next->value);
 13.5187 -  #endif
 13.5188 -  /* generate the table here, before lbl_exit (general jump target) */
 13.5189 -  setlabel(lbl_table);
 13.5190 -  assert(swdefault==FALSE || swdefault==TRUE);
 13.5191 -  if (swdefault==FALSE) {
 13.5192 -    /* store lbl_exit as the "none-matched" label in the switch table */
 13.5193 -    strcpy(labelname,itoh(lbl_exit));
 13.5194 -  } else {
 13.5195 -    /* lbl_case holds the label of the "default" clause */
 13.5196 -    strcpy(labelname,itoh(lbl_case));
 13.5197 -  } /* if */
 13.5198 -  ffcase(casecount,labelname,TRUE);
 13.5199 -  /* generate the rest of the table */
 13.5200 -  for (cse=caselist.next; cse!=NULL; cse=cse->next)
 13.5201 -    ffcase(cse->value,cse->name,FALSE);
 13.5202 -
 13.5203 -  setlabel(lbl_exit);
 13.5204 -  delete_consttable(&caselist); /* clear list of case labels */
 13.5205 -}
 13.5206 -
 13.5207 -static void doassert(void)
 13.5208 -{
 13.5209 -  int flab1,index;
 13.5210 -  cell cidx;
 13.5211 -
 13.5212 -  if ((sc_debug & sCHKBOUNDS)!=0) {
 13.5213 -    flab1=getlabel();           /* get label number for "OK" branch */
 13.5214 -    test(flab1,FALSE,TRUE);     /* get expression and branch to flab1 if true */
 13.5215 -    insert_dbgline(fline);      /* make sure we can find the correct line number */
 13.5216 -    ffabort(xASSERTION);
 13.5217 -    setlabel(flab1);
 13.5218 -  } else {
 13.5219 -    stgset(TRUE);               /* start staging */
 13.5220 -    stgget(&index,&cidx);       /* mark position in code generator */
 13.5221 -    do {
 13.5222 -      expression(NULL,NULL,NULL,FALSE);
 13.5223 -      stgdel(index,cidx);       /* just scrap the code */
 13.5224 -    } while (matchtoken(','));
 13.5225 -    stgset(FALSE);              /* stop staging */
 13.5226 -  } /* if */
 13.5227 -  needtoken(tTERM);
 13.5228 -}
 13.5229 -
 13.5230 -static void dogoto(void)
 13.5231 -{
 13.5232 -  char *st;
 13.5233 -  cell val;
 13.5234 -  symbol *sym;
 13.5235 -
 13.5236 -  if (lex(&val,&st)==tSYMBOL) {
 13.5237 -    sym=fetchlab(st);
 13.5238 -    jumplabel((int)sym->addr);
 13.5239 -    sym->usage|=uREAD;  /* set "uREAD" bit */
 13.5240 -    // ??? if the label is defined (check sym->usage & uDEFINE), check
 13.5241 -    //     sym->compound (nesting level of the label) against nestlevel;
 13.5242 -    //     if sym->compound < nestlevel, call the destructor operator
 13.5243 -  } else {
 13.5244 -    error(20,st);       /* illegal symbol name */
 13.5245 -  } /* if */
 13.5246 -  needtoken(tTERM);
 13.5247 -}
 13.5248 -
 13.5249 -static void dolabel(void)
 13.5250 -{
 13.5251 -  char *st;
 13.5252 -  cell val;
 13.5253 -  symbol *sym;
 13.5254 -
 13.5255 -  tokeninfo(&val,&st);  /* retrieve label name again */
 13.5256 -  if (find_constval(&tagname_tab,st,0)!=NULL)
 13.5257 -    error(221,st);      /* label name shadows tagname */
 13.5258 -  sym=fetchlab(st);
 13.5259 -  setlabel((int)sym->addr);
 13.5260 -  /* since one can jump around variable declarations or out of compound
 13.5261 -   * blocks, the stack must be manually adjusted
 13.5262 -   */
 13.5263 -  setstk(-declared*sizeof(cell));
 13.5264 -  sym->usage|=uDEFINE;  /* label is now defined */
 13.5265 -}
 13.5266 -
 13.5267 -/*  fetchlab
 13.5268 - *
 13.5269 - *  Finds a label from the (local) symbol table or adds one to it.
 13.5270 - *  Labels are local in scope.
 13.5271 - *
 13.5272 - *  Note: The "_usage" bit is set to zero. The routines that call "fetchlab()"
 13.5273 - *        must set this bit accordingly.
 13.5274 - */
 13.5275 -static symbol *fetchlab(char *name)
 13.5276 -{
 13.5277 -  symbol *sym;
 13.5278 -
 13.5279 -  sym=findloc(name);            /* labels are local in scope */
 13.5280 -  if (sym){
 13.5281 -    if (sym->ident!=iLABEL)
 13.5282 -      error(19,sym->name);      /* not a label: ... */
 13.5283 -  } else {
 13.5284 -    sym=addsym(name,getlabel(),iLABEL,sLOCAL,0,0);
 13.5285 -    assert(sym!=NULL);          /* fatal error 103 must be given on error */
 13.5286 -    sym->x.declared=(int)declared;
 13.5287 -    sym->compound=nestlevel;
 13.5288 -  } /* if */
 13.5289 -  return sym;
 13.5290 -}
 13.5291 -
 13.5292 -/*  doreturn
 13.5293 - *
 13.5294 - *  Global references: rettype  (altered)
 13.5295 - */
 13.5296 -static void doreturn(void)
 13.5297 -{
 13.5298 -  int tag,ident;
 13.5299 -  int level;
 13.5300 -  symbol *sym,*sub;
 13.5301 -
 13.5302 -  if (!matchtoken(tTERM)) {
 13.5303 -    /* "return <value>" */
 13.5304 -    if ((rettype & uRETNONE)!=0)
 13.5305 -      error(78);                        /* mix "return;" and "return value;" */
 13.5306 -    ident=doexpr(TRUE,FALSE,TRUE,TRUE,&tag,&sym,TRUE);
 13.5307 -    needtoken(tTERM);
 13.5308 -    /* see if this function already has a sub type (an array attached) */
 13.5309 -    sub=finddepend(curfunc);
 13.5310 -    assert(sub==NULL || sub->ident==iREFARRAY);
 13.5311 -    if ((rettype & uRETVALUE)!=0) {
 13.5312 -      int retarray=(ident==iARRAY || ident==iREFARRAY);
 13.5313 -      /* there was an earlier "return" statement in this function */
 13.5314 -      if (sub==NULL && retarray || sub!=NULL && !retarray)
 13.5315 -        error(79);                      /* mixing "return array;" and "return value;" */
 13.5316 -      if (retarray && (curfunc->usage & uPUBLIC)!=0)
 13.5317 -        error(90,curfunc->name);        /* public function may not return array */
 13.5318 -    } /* if */
 13.5319 -    rettype|=uRETVALUE;                 /* function returns a value */
 13.5320 -    /* check tagname with function tagname */
 13.5321 -    assert(curfunc!=NULL);
 13.5322 -    if (!matchtag(curfunc->tag,tag,TRUE))
 13.5323 -      error(213);                       /* tagname mismatch */
 13.5324 -    if (ident==iARRAY || ident==iREFARRAY) {
 13.5325 -      int dim[sDIMEN_MAX],numdim;
 13.5326 -      cell arraysize;
 13.5327 -      assert(sym!=NULL);
 13.5328 -      if (sub!=NULL) {
 13.5329 -        assert(sub->ident==iREFARRAY);
 13.5330 -        /* this function has an array attached already; check that the current
 13.5331 -         * "return" statement returns exactly the same array
 13.5332 -         */
 13.5333 -        level=sym->dim.array.level;
 13.5334 -        if (sub->dim.array.level!=level) {
 13.5335 -          error(48);                    /* array dimensions must match */
 13.5336 -        } else {
 13.5337 -          for (numdim=0; numdim<=level; numdim++) {
 13.5338 -            dim[numdim]=(int)sub->dim.array.length;
 13.5339 -            if (sym->dim.array.length!=dim[numdim])
 13.5340 -              error(47);    /* array sizes must match */
 13.5341 -            if (numdim<level) {
 13.5342 -              sym=finddepend(sym);
 13.5343 -              sub=finddepend(sub);
 13.5344 -              assert(sym!=NULL && sub!=NULL);
 13.5345 -              /* ^^^ both arrays have the same dimensions (this was checked
 13.5346 -               *     earlier) so the dependend should always be found
 13.5347 -               */
 13.5348 -            } /* if */
 13.5349 -          } /* for */
 13.5350 -        } /* if */
 13.5351 -      } else {
 13.5352 -        int idxtag[sDIMEN_MAX];
 13.5353 -        int argcount;
 13.5354 -        /* this function does not yet have an array attached; clone the
 13.5355 -         * returned symbol beneath the current function
 13.5356 -         */
 13.5357 -        sub=sym;
 13.5358 -        assert(sub!=NULL);
 13.5359 -        level=sub->dim.array.level;
 13.5360 -        for (numdim=0; numdim<=level; numdim++) {
 13.5361 -          dim[numdim]=(int)sub->dim.array.length;
 13.5362 -          idxtag[numdim]=sub->x.tags.index;
 13.5363 -          if (numdim<level) {
 13.5364 -            sub=finddepend(sub);
 13.5365 -            assert(sub!=NULL);
 13.5366 -          } /* if */
 13.5367 -          /* check that all dimensions are known */
 13.5368 -          if (dim[numdim]<=0)
 13.5369 -            error(46,sym->name);
 13.5370 -        } /* for */
 13.5371 -        /* the address of the array is stored in a hidden parameter; the address
 13.5372 -         * of this parameter is 1 + the number of parameters (times the size of
 13.5373 -         * a cell) + the size of the stack frame and the return address
 13.5374 -         *   base + 0*sizeof(cell)         == previous "base"
 13.5375 -         *   base + 1*sizeof(cell)         == function return address
 13.5376 -         *   base + 2*sizeof(cell)         == number of arguments
 13.5377 -         *   base + 3*sizeof(cell)         == first argument of the function
 13.5378 -         *   ...
 13.5379 -         *   base + ((n-1)+3)*sizeof(cell) == last argument of the function
 13.5380 -         *   base + (n+3)*sizeof(cell)     == hidden parameter with array address
 13.5381 -         */
 13.5382 -        assert(curfunc!=NULL);
 13.5383 -        assert(curfunc->dim.arglist!=NULL);
 13.5384 -        for (argcount=0; curfunc->dim.arglist[argcount].ident!=0; argcount++)
 13.5385 -          /* nothing */;
 13.5386 -        sub=addvariable(curfunc->name,(argcount+3)*sizeof(cell),iREFARRAY,sGLOBAL,curfunc->tag,dim,numdim,idxtag);
 13.5387 -        sub->parent=curfunc;
 13.5388 -      } /* if */
 13.5389 -      /* get the hidden parameter, copy the array (the array is on the heap;
 13.5390 -       * it stays on the heap for the moment, and it is removed -usually- at
 13.5391 -       * the end of the expression/statement, see expression() in SC3.C)
 13.5392 -       */
 13.5393 -      address(sub,sALT);                /* ALT = destination */
 13.5394 -      arraysize=calc_arraysize(dim,numdim,0);
 13.5395 -      memcopy(arraysize*sizeof(cell));  /* source already in PRI */
 13.5396 -      /* moveto1(); is not necessary, callfunction() does a popreg() */
 13.5397 -    } /* if */
 13.5398 -  } else {
 13.5399 -    /* this return statement contains no expression */
 13.5400 -    ldconst(0,sPRI);
 13.5401 -    if ((rettype & uRETVALUE)!=0) {
 13.5402 -      char symname[2*sNAMEMAX+16];      /* allow space for user defined operators */
 13.5403 -      assert(curfunc!=NULL);
 13.5404 -      funcdisplayname(symname,curfunc->name);
 13.5405 -      error(209,symname);               /* function should return a value */
 13.5406 -    } /* if */
 13.5407 -    rettype|=uRETNONE;                  /* function does not return anything */
 13.5408 -  } /* if */
 13.5409 -  destructsymbols(&loctab,0);           /* call destructor for *all* locals */
 13.5410 -  modstk((int)declared*sizeof(cell));   /* end of function, remove *all*
 13.5411 -                                         * local variables */
 13.5412 -  ffret(strcmp(curfunc->name,uENTRYFUNC)!=0);
 13.5413 -}
 13.5414 -
 13.5415 -static void dobreak(void)
 13.5416 -{
 13.5417 -  int *ptr;
 13.5418 -
 13.5419 -  ptr=readwhile();      /* readwhile() gives an error if not in loop */
 13.5420 -  needtoken(tTERM);
 13.5421 -  if (ptr==NULL)
 13.5422 -    return;
 13.5423 -  destructsymbols(&loctab,nestlevel);
 13.5424 -  modstk(((int)declared-ptr[wqBRK])*sizeof(cell));
 13.5425 -  jumplabel(ptr[wqEXIT]);
 13.5426 -}
 13.5427 -
 13.5428 -static void docont(void)
 13.5429 -{
 13.5430 -  int *ptr;
 13.5431 -
 13.5432 -  ptr=readwhile();      /* readwhile() gives an error if not in loop */
 13.5433 -  needtoken(tTERM);
 13.5434 -  if (ptr==NULL)
 13.5435 -    return;
 13.5436 -  destructsymbols(&loctab,nestlevel);
 13.5437 -  modstk(((int)declared-ptr[wqCONT])*sizeof(cell));
 13.5438 -  jumplabel(ptr[wqLOOP]);
 13.5439 -}
 13.5440 -
 13.5441 -SC_FUNC void exporttag(int tag)
 13.5442 -{
 13.5443 -  /* find the tag by value in the table, then set the top bit to mark it
 13.5444 -   * "public"
 13.5445 -   */
 13.5446 -  if (tag!=0 && (tag & PUBLICTAG)==0) {
 13.5447 -    constvalue *ptr;
 13.5448 -    for (ptr=tagname_tab.next; ptr!=NULL && tag!=(int)(ptr->value & TAGMASK); ptr=ptr->next)
 13.5449 -      /* nothing */;
 13.5450 -    if (ptr!=NULL)
 13.5451 -      ptr->value |= PUBLICTAG;
 13.5452 -  } /* if */
 13.5453 -}
 13.5454 -
 13.5455 -static void doexit(void)
 13.5456 -{
 13.5457 -  int tag=0;
 13.5458 -
 13.5459 -  if (matchtoken(tTERM)==0){
 13.5460 -    doexpr(TRUE,FALSE,FALSE,TRUE,&tag,NULL,TRUE);
 13.5461 -    needtoken(tTERM);
 13.5462 -  } else {
 13.5463 -    ldconst(0,sPRI);
 13.5464 -  } /* if */
 13.5465 -  ldconst(tag,sALT);
 13.5466 -  exporttag(tag);
 13.5467 -  destructsymbols(&loctab,0);           /* call destructor for *all* locals */
 13.5468 -  ffabort(xEXIT);
 13.5469 -}
 13.5470 -
 13.5471 -static void dosleep(void)
 13.5472 -{
 13.5473 -  int tag=0;
 13.5474 -
 13.5475 -  if (matchtoken(tTERM)==0){
 13.5476 -    doexpr(TRUE,FALSE,FALSE,TRUE,&tag,NULL,TRUE);
 13.5477 -    needtoken(tTERM);
 13.5478 -  } else {
 13.5479 -    ldconst(0,sPRI);
 13.5480 -  } /* if */
 13.5481 -  ldconst(tag,sALT);
 13.5482 -  exporttag(tag);
 13.5483 -  ffabort(xSLEEP);
 13.5484 -
 13.5485 -  /* for stack usage checking, mark the use of the sleep instruction */
 13.5486 -  pc_memflags |= suSLEEP_INSTR;
 13.5487 -}
 13.5488 -
 13.5489 -static void dostate(void)
 13.5490 -{
 13.5491 -  char name[sNAMEMAX+1];
 13.5492 -  constvalue *automaton;
 13.5493 -  constvalue *state;
 13.5494 -  constvalue *stlist;
 13.5495 -  int flabel;
 13.5496 -  symbol *sym;
 13.5497 -  #if !defined SC_LIGHT
 13.5498 -    int length,index,listid,listindex,stateindex;
 13.5499 -    char *doc;
 13.5500 -  #endif
 13.5501 -
 13.5502 -  /* check for an optional condition */
 13.5503 -  if (matchtoken('(')) {
 13.5504 -    flabel=getlabel();          /* get label number for "false" branch */
 13.5505 -    pc_docexpr=TRUE;            /* attach expression as a documentation string */
 13.5506 -    test(flabel,FALSE,FALSE);   /* get expression, branch to flabel if false */
 13.5507 -    pc_docexpr=FALSE;
 13.5508 -    needtoken(')');
 13.5509 -  } else {
 13.5510 -    flabel=-1;
 13.5511 -  } /* if */
 13.5512 -
 13.5513 -  if (!sc_getstateid(&automaton,&state)) {
 13.5514 -    delete_autolisttable();
 13.5515 -    return;
 13.5516 -  } /* if */
 13.5517 -  needtoken(tTERM);
 13.5518 -
 13.5519 -  /* store the new state id */
 13.5520 -  assert(state!=NULL);
 13.5521 -  ldconst(state->value,sPRI);
 13.5522 -  assert(automaton!=NULL);
 13.5523 -  assert(automaton->index==0 && automaton->name[0]=='\0' || automaton->index>0);
 13.5524 -  storereg(automaton->value,sPRI);
 13.5525 -
 13.5526 -  /* find the optional entry() function for the state */
 13.5527 -  sym=findglb(uENTRYFUNC,sGLOBAL);
 13.5528 -  if (sc_status==statWRITE && sym!=NULL && sym->ident==iFUNCTN && sym->states!=NULL) {
 13.5529 -    for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) {
 13.5530 -      assert(strlen(stlist->name)!=0);
 13.5531 -      if (state_getfsa(stlist->index)==automaton->index && state_inlist(stlist->index,(int)state->value))
 13.5532 -        break;      /* found! */
 13.5533 -    } /* for */
 13.5534 -    assert(stlist==NULL || state_inlist(stlist->index,state->value));
 13.5535 -    if (stlist!=NULL) {
 13.5536 -      /* the label to jump to is in stlist->name */
 13.5537 -      ffcall(sym,stlist->name,0);
 13.5538 -    } /* if */
 13.5539 -  } /* if */
 13.5540 -
 13.5541 -  if (flabel>=0)
 13.5542 -    setlabel(flabel);           /* condition was false, jump around the state switch */
 13.5543 -
 13.5544 -  #if !defined SC_LIGHT
 13.5545 -    /* mark for documentation */
 13.5546 -    if (sc_status==statFIRST) {
 13.5547 -      char *str;
 13.5548 -      /* get the last list id attached to the function, this contains the source states */
 13.5549 -      assert(curfunc!=NULL);
 13.5550 -      if (curfunc->states!=NULL) {
 13.5551 -        stlist=curfunc->states->next;
 13.5552 -        assert(stlist!=NULL);
 13.5553 -        while (stlist->next!=NULL)
 13.5554 -          stlist=stlist->next;
 13.5555 -        listid=stlist->index;
 13.5556 -      } else {
 13.5557 -        listid=-1;
 13.5558 -      } /* if */
 13.5559 -      listindex=0;
 13.5560 -      length=strlen(name)+70; /* +70 for the fixed part "<transition ... />\n" */
 13.5561 -      /* see if there are any condition strings to attach */
 13.5562 -      for (index=0; (str=get_autolist(index))!=NULL; index++)
 13.5563 -        length+=strlen(str);
 13.5564 -      if ((doc=(char*)malloc(length*sizeof(char)))!=NULL) {
 13.5565 -        do {
 13.5566 -          sprintf(doc,"<transition target=\"%s\"",name);
 13.5567 -          if (listid>=0) {
 13.5568 -            /* get the source state */
 13.5569 -            stateindex=state_listitem(listid,listindex);
 13.5570 -            state=state_findid(stateindex);
 13.5571 -            assert(state!=NULL);
 13.5572 -            sprintf(doc+strlen(doc)," source=\"%s\"",state->name);
 13.5573 -          } /* if */
 13.5574 -          if (get_autolist(0)!=NULL) {
 13.5575 -            /* add the condition */
 13.5576 -            strcat(doc," condition=\"");
 13.5577 -            for (index=0; (str=get_autolist(index))!=NULL; index++) {
 13.5578 -              /* remove the ')' token that may be appended before detecting that the expression has ended */
 13.5579 -              if (*str!=')' || *(str+1)!='\0' || get_autolist(index+1)!=NULL)
 13.5580 -                strcat(doc,str);
 13.5581 -            } /* for */
 13.5582 -            strcat(doc,"\"");
 13.5583 -          } /* if */
 13.5584 -          strcat(doc,"/>\n");
 13.5585 -          insert_docstring(doc);
 13.5586 -        } while (listid>=0 && ++listindex<state_count(listid));
 13.5587 -        free(doc);
 13.5588 -      } /* if */
 13.5589 -    } /* if */
 13.5590 -  #endif
 13.5591 -  delete_autolisttable();
 13.5592 -}
 13.5593 -
 13.5594 -
 13.5595 -static void addwhile(int *ptr)
 13.5596 -{
 13.5597 -  int k;
 13.5598 -
 13.5599 -  ptr[wqBRK]=(int)declared;     /* stack pointer (for "break") */
 13.5600 -  ptr[wqCONT]=(int)declared;    /* for "continue", possibly adjusted later */
 13.5601 -  ptr[wqLOOP]=getlabel();
 13.5602 -  ptr[wqEXIT]=getlabel();
 13.5603 -  if (wqptr>=(wq+wqTABSZ-wqSIZE))
 13.5604 -    error(102,"loop table");    /* loop table overflow (too many active loops)*/
 13.5605 -  k=0;
 13.5606 -  while (k<wqSIZE){     /* copy "ptr" to while queue table */
 13.5607 -    *wqptr=*ptr;
 13.5608 -    wqptr+=1;
 13.5609 -    ptr+=1;
 13.5610 -    k+=1;
 13.5611 -  } /* while */
 13.5612 -}
 13.5613 -
 13.5614 -static void delwhile(void)
 13.5615 -{
 13.5616 -  if (wqptr>wq)
 13.5617 -    wqptr-=wqSIZE;
 13.5618 -}
 13.5619 -
 13.5620 -static int *readwhile(void)
 13.5621 -{
 13.5622 -  if (wqptr<=wq){
 13.5623 -    error(24);          /* out of context */
 13.5624 -    return NULL;
 13.5625 -  } else {
 13.5626 -    return (wqptr-wqSIZE);
 13.5627 -  } /* if */
 13.5628 -}
 13.5629 -
    14.1 --- a/compiler-init/sc2.c	Sat Jul 15 01:36:48 2006 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,2801 +0,0 @@
    14.4 -/*  Pawn compiler - File input, preprocessing and lexical analysis functions
    14.5 - *
    14.6 - *  Copyright (c) ITB CompuPhase, 1997-2006
    14.7 - *
    14.8 - *  This software is provided "as-is", without any express or implied warranty.
    14.9 - *  In no event will the authors be held liable for any damages arising from
   14.10 - *  the use of this software.
   14.11 - *
   14.12 - *  Permission is granted to anyone to use this software for any purpose,
   14.13 - *  including commercial applications, and to alter it and redistribute it
   14.14 - *  freely, subject to the following restrictions:
   14.15 - *
   14.16 - *  1.  The origin of this software must not be misrepresented; you must not
   14.17 - *      claim that you wrote the original software. If you use this software in
   14.18 - *      a product, an acknowledgment in the product documentation would be
   14.19 - *      appreciated but is not required.
   14.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
   14.21 - *      misrepresented as being the original software.
   14.22 - *  3.  This notice may not be removed or altered from any source distribution.
   14.23 - *
   14.24 - *  Version: $Id: sc2.c 3590 2006-06-24 14:16:39Z thiadmer $
   14.25 - */
   14.26 -#include <assert.h>
   14.27 -#include <stdio.h>
   14.28 -#include <stdlib.h>
   14.29 -#include <string.h>
   14.30 -#include <ctype.h>
   14.31 -#include <math.h>
   14.32 -#include "lstring.h"
   14.33 -#include "sc.h"
   14.34 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
   14.35 -  #include <sclinux.h>
   14.36 -#endif
   14.37 -
   14.38 -#if defined FORTIFY
   14.39 -  #include <alloc/fortify.h>
   14.40 -#endif
   14.41 -
   14.42 -/* flags for litchar() */
   14.43 -#define RAWMODE         1
   14.44 -#define UTF8MODE        2
   14.45 -static cell litchar(const unsigned char **lptr,int flags);
   14.46 -static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int automaton,int *cmptag);
   14.47 -
   14.48 -static void substallpatterns(unsigned char *line,int buffersize);
   14.49 -static int match(char *st,int end);
   14.50 -static int alpha(char c);
   14.51 -
   14.52 -#define SKIPMODE      1 /* bit field in "#if" stack */
   14.53 -#define PARSEMODE     2 /* bit field in "#if" stack */
   14.54 -#define HANDLED_ELSE  4 /* bit field in "#if" stack */
   14.55 -#define SKIPPING      (skiplevel>0 && (ifstack[skiplevel-1] & SKIPMODE)==SKIPMODE)
   14.56 -
   14.57 -static short icomment;  /* currently in multiline comment? */
   14.58 -static char ifstack[sCOMP_STACK]; /* "#if" stack */
   14.59 -static short iflevel;   /* nesting level if #if/#else/#endif */
   14.60 -static short skiplevel; /* level at which we started skipping (including nested #if .. #endif) */
   14.61 -static unsigned char term_expr[] = "";
   14.62 -static int listline=-1; /* "current line" for the list file */
   14.63 -
   14.64 -
   14.65 -/*  pushstk & popstk
   14.66 - *
   14.67 - *  Uses a LIFO stack to store information. The stack is used by doinclude(),
   14.68 - *  doswitch() (to hold the state of "swactive") and some other routines.
   14.69 - *
   14.70 - *  Porting note: I made the bold assumption that an integer will not be
   14.71 - *  larger than a pointer (it may be smaller). That is, the stack element
   14.72 - *  is typedef'ed as a pointer type, but I also store integers on it. See
   14.73 - *  SC.H for "stkitem"
   14.74 - *
   14.75 - *  Global references: stack,stkidx,stktop (private to pushstk(), popstk()
   14.76 - *                     and clearstk())
   14.77 - */
   14.78 -static stkitem *stack=NULL;
   14.79 -static int stkidx=0,stktop=0;
   14.80 -
   14.81 -SC_FUNC void pushstk(stkitem val)
   14.82 -{
   14.83 -  assert(stkidx<=stktop);
   14.84 -  if (stkidx==stktop) {
   14.85 -    stkitem *newstack;
   14.86 -    int newsize= (stktop==0) ? 16 : 2*stktop;
   14.87 -    /* try to resize the stack */
   14.88 -    assert(newsize>stktop);
   14.89 -    newstack=(stkitem*)malloc(newsize*sizeof(stkitem));
   14.90 -    if (newstack==NULL)
   14.91 -      error(102,"parser stack");  /* stack overflow (recursive include?) */
   14.92 -    /* swap the stacks */
   14.93 -    memcpy(newstack,stack,stkidx*sizeof(stkitem));
   14.94 -    if (stack!=NULL)
   14.95 -      free(stack);
   14.96 -    stack=newstack;
   14.97 -    stktop=newsize;
   14.98 -  } /* if */
   14.99 -  assert(stkidx<stktop);
  14.100 -  stack[stkidx]=val;
  14.101 -  stkidx+=1;
  14.102 -}
  14.103 -
  14.104 -SC_FUNC stkitem popstk(void)
  14.105 -{
  14.106 -  if (stkidx==0) {
  14.107 -    stkitem s;
  14.108 -    s.i=-1;             /* stack is empty */
  14.109 -    return s;
  14.110 -  } /* if */
  14.111 -  stkidx--;
  14.112 -  assert(stack!=NULL);
  14.113 -  return stack[stkidx];
  14.114 -}
  14.115 -
  14.116 -SC_FUNC void clearstk(void)
  14.117 -{
  14.118 -  assert(stack!=NULL || stktop==0);
  14.119 -  if (stack!=NULL) {
  14.120 -    free(stack);
  14.121 -    stack=NULL;
  14.122 -    stktop=0;
  14.123 -  } /* if */
  14.124 -  assert(stktop==0);
  14.125 -}
  14.126 -
  14.127 -SC_FUNC int plungequalifiedfile(char *name)
  14.128 -{
  14.129 -static char *extensions[] = { ".inc", ".p", ".pawn" };
  14.130 -  FILE *fp;
  14.131 -  char *ext;
  14.132 -  int ext_idx;
  14.133 -
  14.134 -  ext_idx=0;
  14.135 -  do {
  14.136 -    fp=(FILE*)pc_opensrc(name);
  14.137 -    ext=strchr(name,'\0');      /* save position */
  14.138 -    if (fp==NULL) {
  14.139 -      /* try to append an extension */
  14.140 -      strcpy(ext,extensions[ext_idx]);
  14.141 -      fp=(FILE*)pc_opensrc(name);
  14.142 -      if (fp==NULL)
  14.143 -        *ext='\0';              /* on failure, restore filename */
  14.144 -    } /* if */
  14.145 -    ext_idx++;
  14.146 -  } while (fp==NULL && ext_idx<(sizeof extensions / sizeof extensions[0]));
  14.147 -  if (fp==NULL) {
  14.148 -    *ext='\0';                  /* restore filename */
  14.149 -    return FALSE;
  14.150 -  } /* if */
  14.151 -  PUSHSTK_P(inpf);
  14.152 -  PUSHSTK_P(inpfname);          /* pointer to current file name */
  14.153 -  PUSHSTK_P(curlibrary);
  14.154 -  PUSHSTK_I(iflevel);
  14.155 -  assert(!SKIPPING);
  14.156 -  assert(skiplevel==iflevel);   /* these two are always the same when "parsing" */
  14.157 -  PUSHSTK_I(sc_is_utf8);
  14.158 -  PUSHSTK_I(icomment);
  14.159 -  PUSHSTK_I(fcurrent);
  14.160 -  PUSHSTK_I(fline);
  14.161 -  inpfname=duplicatestring(name);/* set name of include file */
  14.162 -  if (inpfname==NULL)
  14.163 -    error(103);             /* insufficient memory */
  14.164 -  inpf=fp;                  /* set input file pointer to include file */
  14.165 -  fnumber++;
  14.166 -  fline=0;                  /* set current line number to 0 */
  14.167 -  fcurrent=fnumber;
  14.168 -  icomment=0;               /* not in a comment */
  14.169 -  insert_dbgfile(inpfname);
  14.170 -  setfiledirect(inpfname);
  14.171 -  listline=-1;              /* force a #line directive when changing the file */
  14.172 -  sc_is_utf8=(short)scan_utf8(inpf,name);
  14.173 -  return TRUE;
  14.174 -}
  14.175 -
  14.176 -SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths)
  14.177 -{
  14.178 -  int result=FALSE;
  14.179 -
  14.180 -  if (try_currentpath) {
  14.181 -    result=plungequalifiedfile(name);
  14.182 -    if (!result) {
  14.183 -      /* failed to open the file in the active directory, try to open the file
  14.184 -       * in the same directory as the current file --but first check whether
  14.185 -       * there is a (relative) path for the current file
  14.186 -       */
  14.187 -      char *ptr;
  14.188 -      if ((ptr=strrchr(inpfname,DIRSEP_CHAR))!=0) {
  14.189 -        int len=(int)(ptr-inpfname)+1;
  14.190 -        if (len+strlen(name)<_MAX_PATH) {
  14.191 -          char path[_MAX_PATH];
  14.192 -          strlcpy(path,inpfname,len+1);
  14.193 -          strlcat(path,name,sizeof path);
  14.194 -          result=plungequalifiedfile(path);
  14.195 -        } /* if */
  14.196 -      } /* if */
  14.197 -    } /* if */
  14.198 -  } /* if */
  14.199 -
  14.200 -  if (try_includepaths && name[0]!=DIRSEP_CHAR) {
  14.201 -    int i;
  14.202 -    char *ptr;
  14.203 -    for (i=0; !result && (ptr=get_path(i))!=NULL; i++) {
  14.204 -      char path[_MAX_PATH];
  14.205 -      strlcpy(path,ptr,sizeof path);
  14.206 -      strlcat(path,name,sizeof path);
  14.207 -      result=plungequalifiedfile(path);
  14.208 -    } /* while */
  14.209 -  } /* if */
  14.210 -  return result;
  14.211 -}
  14.212 -
  14.213 -static void check_empty(const unsigned char *lptr)
  14.214 -{
  14.215 -  /* verifies that the string contains only whitespace */
  14.216 -  while (*lptr<=' ' && *lptr!='\0')
  14.217 -    lptr++;
  14.218 -  if (*lptr!='\0')
  14.219 -    error(38);          /* extra characters on line */
  14.220 -}
  14.221 -
  14.222 -/*  doinclude
  14.223 - *
  14.224 - *  Gets the name of an include file, pushes the old file on the stack and
  14.225 - *  sets some options. This routine doesn't use lex(), since lex() doesn't
  14.226 - *  recognize file names (and directories).
  14.227 - *
  14.228 - *  Global references: inpf     (altered)
  14.229 - *                     inpfname (altered)
  14.230 - *                     fline    (altered)
  14.231 - *                     lptr     (altered)
  14.232 - */
  14.233 -static void doinclude(int silent)
  14.234 -{
  14.235 -  char name[_MAX_PATH];
  14.236 -  char symname[sNAMEMAX];
  14.237 -  char *ptr;
  14.238 -  char c;
  14.239 -  int i, result;
  14.240 -
  14.241 -  while (*lptr<=' ' && *lptr!='\0')         /* skip leading whitespace */
  14.242 -    lptr++;
  14.243 -  if (*lptr=='<' || *lptr=='\"'){
  14.244 -    c=(char)((*lptr=='\"') ? '\"' : '>');   /* termination character */
  14.245 -    lptr++;
  14.246 -    while (*lptr<=' ' && *lptr!='\0')       /* skip whitespace after quote */
  14.247 -      lptr++;
  14.248 -  } else {
  14.249 -    c='\0';
  14.250 -  } /* if */
  14.251 -
  14.252 -  i=0;
  14.253 -  while (*lptr!=c && *lptr!='\0' && i<sizeof name - 1)  /* find the end of the string */
  14.254 -    name[i++]=*lptr++;
  14.255 -  while (i>0 && name[i-1]<=' ')
  14.256 -    i--;                        /* strip trailing whitespace */
  14.257 -  assert(i>=0 && i<sizeof name);
  14.258 -  name[i]='\0';                 /* zero-terminate the string */
  14.259 -
  14.260 -  if (*lptr!=c) {               /* verify correct string termination */
  14.261 -    error(37);                  /* invalid string */
  14.262 -    return;
  14.263 -  } /* if */
  14.264 -  if (c!='\0')
  14.265 -    check_empty(lptr+1);        /* verify that the rest of the line is whitespace */
  14.266 -
  14.267 -  /* create a symbol from the name of the include file; this allows the system
  14.268 -   * to test for multiple inclusions
  14.269 -   */
  14.270 -  strcpy(symname,"_inc_");
  14.271 -  if ((ptr=strrchr(name,DIRSEP_CHAR))!=NULL)
  14.272 -    strlcat(symname,ptr+1,sizeof symname);
  14.273 -  else
  14.274 -    strlcat(symname,name,sizeof symname);
  14.275 -  if (find_symbol(&glbtab,symname,fcurrent,-1,NULL)==NULL) {
  14.276 -    /* constant is not present, so this file has not been included yet */
  14.277 -
  14.278 -    /* Include files between "..." or without quotes are read from the current
  14.279 -     * directory, or from a list of "include directories". Include files
  14.280 -     * between <...> are only read from the list of include directories.
  14.281 -     */
  14.282 -    result=plungefile(name,(c!='>'),TRUE);
  14.283 -    if (result)
  14.284 -      add_constant(symname,1,sGLOBAL,0);
  14.285 -    else if (!silent)
  14.286 -      error(100,name);            /* cannot read from ... (fatal error) */
  14.287 -  } /* if */
  14.288 -}
  14.289 -
  14.290 -/*  readline
  14.291 - *
  14.292 - *  Reads in a new line from the input file pointed to by "inpf". readline()
  14.293 - *  concatenates lines that end with a \ with the next line. If no more data
  14.294 - *  can be read from the file, readline() attempts to pop off the previous file
  14.295 - *  from the stack. If that fails too, it sets "freading" to 0.
  14.296 - *
  14.297 - *  Global references: inpf,fline,inpfname,freading,icomment (altered)
  14.298 - */
  14.299 -static void readline(unsigned char *line)
  14.300 -{
  14.301 -  int i,num,cont;
  14.302 -  unsigned char *ptr;
  14.303 -
  14.304 -  if (lptr==term_expr)
  14.305 -    return;
  14.306 -  num=sLINEMAX;
  14.307 -  cont=FALSE;
  14.308 -  do {
  14.309 -    if (inpf==NULL || pc_eofsrc(inpf)) {
  14.310 -      if (cont)
  14.311 -        error(49);        /* invalid line continuation */
  14.312 -      if (inpf!=NULL && inpf!=inpf_org)
  14.313 -        pc_closesrc(inpf);
  14.314 -      i=POPSTK_I();
  14.315 -      if (i==-1) {        /* All's done; popstk() returns "stack is empty" */
  14.316 -        freading=FALSE;
  14.317 -        *line='\0';
  14.318 -        /* when there is nothing more to read, the #if/#else stack should
  14.319 -         * be empty and we should not be in a comment
  14.320 -         */
  14.321 -        assert(iflevel>=0);
  14.322 -        if (iflevel>0)
  14.323 -          error(1,"#endif","-end of file-");
  14.324 -        else if (icomment!=0)
  14.325 -          error(1,"*/","-end of file-");
  14.326 -        return;
  14.327 -      } /* if */
  14.328 -      fline=i;
  14.329 -      fcurrent=(short)POPSTK_I();
  14.330 -      icomment=(short)POPSTK_I();
  14.331 -      sc_is_utf8=(short)POPSTK_I();
  14.332 -      iflevel=(short)POPSTK_I();
  14.333 -      skiplevel=iflevel;        /* this condition held before including the file */
  14.334 -      assert(!SKIPPING);        /* idem ditto */
  14.335 -      curlibrary=(constvalue *)POPSTK_P();
  14.336 -      free(inpfname);           /* return memory allocated for the include file name */
  14.337 -      inpfname=(char *)POPSTK_P();
  14.338 -      inpf=(FILE *)POPSTK_P();
  14.339 -      insert_dbgfile(inpfname);
  14.340 -      setfiledirect(inpfname);
  14.341 -      listline=-1;              /* force a #line directive when changing the file */
  14.342 -    } /* if */
  14.343 -
  14.344 -    if (pc_readsrc(inpf,line,num)==NULL) {
  14.345 -      *line='\0';     /* delete line */
  14.346 -      cont=FALSE;
  14.347 -    } else {
  14.348 -      /* check whether to erase leading spaces */
  14.349 -      if (cont) {
  14.350 -        unsigned char *ptr=line;
  14.351 -        while (*ptr<=' ' && *ptr!='\0')
  14.352 -          ptr++;
  14.353 -        if (ptr!=line)
  14.354 -          memmove(line,ptr,strlen((char*)ptr)+1);
  14.355 -      } /* if */
  14.356 -      cont=FALSE;
  14.357 -      /* check whether a full line was read */
  14.358 -      if (strchr((char*)line,'\n')==NULL && !pc_eofsrc(inpf))
  14.359 -        error(75);      /* line too long */
  14.360 -      /* check if the next line must be concatenated to this line */
  14.361 -      if ((ptr=(unsigned char*)strchr((char*)line,'\n'))==NULL)
  14.362 -        ptr=(unsigned char*)strchr((char*)line,'\r');
  14.363 -      if (ptr!=NULL && ptr>line) {
  14.364 -        assert(*(ptr+1)=='\0'); /* '\n' or '\r' should be last in the string */
  14.365 -        while (ptr>line && *ptr<=' ')
  14.366 -          ptr--;        /* skip trailing whitespace */
  14.367 -        if (*ptr=='\\') {
  14.368 -          cont=TRUE;
  14.369 -          /* set '\a' at the position of '\\' to make it possible to check
  14.370 -           * for a line continuation in a single line comment (error 49)
  14.371 -           */
  14.372 -          *ptr++='\a';
  14.373 -          *ptr='\0';    /* erase '\n' (and any trailing whitespace) */
  14.374 -        } /* if */
  14.375 -      } /* if */
  14.376 -      num-=strlen((char*)line);
  14.377 -      line+=strlen((char*)line);
  14.378 -    } /* if */
  14.379 -    fline+=1;
  14.380 -  } while (num>=0 && cont);
  14.381 -}
  14.382 -
  14.383 -/*  stripcom
  14.384 - *
  14.385 - *  Replaces all comments from the line by space characters. It updates
  14.386 - *  a global variable ("icomment") for multiline comments.
  14.387 - *
  14.388 - *  This routine also supports the C++ extension for single line comments.
  14.389 - *  These comments are started with "//" and end at the end of the line.
  14.390 - *
  14.391 - *  The function also detects (and manages) "documentation comments". The
  14.392 - *  global variable "icomment" is set to 2 for documentation comments.
  14.393 - *
  14.394 - *  Global references: icomment  (private to "stripcom")
  14.395 - */
  14.396 -static void stripcom(unsigned char *line)
  14.397 -{
  14.398 -  char c;
  14.399 -  #if !defined SC_LIGHT
  14.400 -    #define COMMENT_LIMIT 100
  14.401 -    #define COMMENT_MARGIN 40   /* length of the longest word */
  14.402 -    char comment[COMMENT_LIMIT+COMMENT_MARGIN];
  14.403 -    int commentidx=0;
  14.404 -    int skipstar=TRUE;
  14.405 -    static int prev_singleline=FALSE;
  14.406 -    int singleline=prev_singleline;
  14.407 -
  14.408 -    prev_singleline=FALSE;  /* preset */
  14.409 -  #endif
  14.410 -
  14.411 -  while (*line){
  14.412 -    if (icomment!=0) {
  14.413 -      if (*line=='*' && *(line+1)=='/') {
  14.414 -        #if !defined SC_LIGHT
  14.415 -          if (icomment==2) {
  14.416 -            assert(commentidx<COMMENT_LIMIT+COMMENT_MARGIN);
  14.417 -            comment[commentidx]='\0';
  14.418 -            if (strlen(comment)>0)
  14.419 -              insert_docstring(comment);
  14.420 -          } /* if */
  14.421 -        #endif
  14.422 -        icomment=0;     /* comment has ended */
  14.423 -        *line=' ';      /* replace '*' and '/' characters by spaces */
  14.424 -        *(line+1)=' ';
  14.425 -        line+=2;
  14.426 -      } else {
  14.427 -        if (*line=='/' && *(line+1)=='*')
  14.428 -          error(216);   /* nested comment */
  14.429 -        #if !defined SC_LIGHT
  14.430 -          /* collect the comment characters in a string */
  14.431 -          if (icomment==2) {
  14.432 -            if (skipstar && (*line!='\0' && *line<=' ' || *line=='*')) {
  14.433 -              /* ignore leading whitespace and '*' characters */
  14.434 -            } else if (commentidx<COMMENT_LIMIT+COMMENT_MARGIN-1) {
  14.435 -              comment[commentidx++]=(char)((*line!='\n') ? *line : ' ');
  14.436 -              if (commentidx>COMMENT_LIMIT && *line!='\0' && *line<=' ') {
  14.437 -                comment[commentidx]='\0';
  14.438 -                insert_docstring(comment);
  14.439 -                commentidx=0;
  14.440 -              } /* if */
  14.441 -              skipstar=FALSE;
  14.442 -            } /* if */
  14.443 -          } /* if */
  14.444 -        #endif
  14.445 -        *line=' ';      /* replace comments by spaces */
  14.446 -        line+=1;
  14.447 -      } /* if */
  14.448 -    } else {
  14.449 -      if (*line=='/' && *(line+1)=='*'){
  14.450 -        icomment=1;     /* start comment */
  14.451 -        #if !defined SC_LIGHT
  14.452 -          /* there must be two "*" behind the slash and then white space */
  14.453 -          if (*(line+2)=='*' && *(line+3)<=' ') {
  14.454 -            /* if we are not in a function, we must attach the previous block
  14.455 -             * to the global documentation
  14.456 -             */
  14.457 -            if (curfunc==NULL && get_docstring(0)!=NULL)
  14.458 -              sc_attachdocumentation(NULL);
  14.459 -            icomment=2; /* documentation comment */
  14.460 -          } /* if */
  14.461 -          commentidx=0;
  14.462 -          skipstar=TRUE;
  14.463 -        #endif
  14.464 -        *line=' ';      /* replace '/' and '*' characters by spaces */
  14.465 -        *(line+1)=' ';
  14.466 -        line+=2;
  14.467 -        if (icomment==2)
  14.468 -          *line++=' ';
  14.469 -      } else if (*line=='/' && *(line+1)=='/'){  /* comment to end of line */
  14.470 -        if (strchr((char*)line,'\a')!=NULL)
  14.471 -          error(49);    /* invalid line continuation */
  14.472 -        #if !defined SC_LIGHT
  14.473 -          if (*(line+2)=='/' && *(line+3)<=' ') {
  14.474 -            /* documentation comment */
  14.475 -            char *str=(char*)line+3;
  14.476 -            char *end;
  14.477 -            while (*str<=' ' && *str!='\0')
  14.478 -              str++;    /* skip leading whitespace */
  14.479 -            if ((end=strrchr(str,'\n'))!=NULL)
  14.480 -              *end='\0';/* erase trailing '\n' */
  14.481 -            /* if there is a disjunct block, we may need to attach the previous
  14.482 -             * block to the global documentation
  14.483 -             */
  14.484 -            if (!singleline && curfunc==NULL && get_docstring(0)!=NULL)
  14.485 -              sc_attachdocumentation(NULL);
  14.486 -            insert_docstring(str);
  14.487 -            prev_singleline=TRUE;
  14.488 -          } /* if */
  14.489 -        #endif
  14.490 -        *line++='\n';   /* put "newline" at first slash */
  14.491 -        *line='\0';     /* put "zero-terminator" at second slash */
  14.492 -      } else {
  14.493 -        if (*line=='\"' || *line=='\''){        /* leave literals unaltered */
  14.494 -          c=*line;      /* ending quote, single or double */
  14.495 -          line+=1;
  14.496 -          while ((*line!=c || *(line-1)==sc_ctrlchar) && *line!='\0')
  14.497 -            line+=1;
  14.498 -          line+=1;      /* skip final quote */
  14.499 -        } else {
  14.500 -          line+=1;
  14.501 -        } /* if */
  14.502 -      } /* if */
  14.503 -    } /* if */
  14.504 -  } /* while */
  14.505 -  #if !defined SC_LIGHT
  14.506 -    if (icomment==2) {
  14.507 -      assert(commentidx<COMMENT_LIMIT+COMMENT_MARGIN);
  14.508 -      comment[commentidx]='\0';
  14.509 -      if (strlen(comment)>0)
  14.510 -        insert_docstring(comment);
  14.511 -    } /* if */
  14.512 -  #endif
  14.513 -}
  14.514 -
  14.515 -/*  btoi
  14.516 - *
  14.517 - *  Attempts to interpret a numeric symbol as a boolean value. On success
  14.518 - *  it returns the number of characters processed (so the line pointer can be
  14.519 - *  adjusted) and the value is stored in "val". Otherwise it returns 0 and
  14.520 - *  "val" is garbage.
  14.521 - *
  14.522 - *  A boolean value must start with "0b"
  14.523 - */
  14.524 -static int btoi(cell *val,const unsigned char *curptr)
  14.525 -{
  14.526 -  const unsigned char *ptr;
  14.527 -
  14.528 -  *val=0;
  14.529 -  ptr=curptr;
  14.530 -  if (*ptr=='0' && *(ptr+1)=='b') {
  14.531 -    ptr+=2;
  14.532 -    while (*ptr=='0' || *ptr=='1' || *ptr=='_') {
  14.533 -      if (*ptr!='_')
  14.534 -        *val=(*val<<1) | (*ptr-'0');
  14.535 -      ptr++;
  14.536 -    } /* while */
  14.537 -  } else {
  14.538 -    return 0;
  14.539 -  } /* if */
  14.540 -  if (alphanum(*ptr))   /* number must be delimited by non-alphanumeric char */
  14.541 -    return 0;
  14.542 -  else
  14.543 -    return (int)(ptr-curptr);
  14.544 -}
  14.545 -
  14.546 -/*  dtoi
  14.547 - *
  14.548 - *  Attempts to interpret a numeric symbol as a decimal value. On success
  14.549 - *  it returns the number of characters processed and the value is stored in
  14.550 - *  "val". Otherwise it returns 0 and "val" is garbage.
  14.551 - */
  14.552 -static int dtoi(cell *val,const unsigned char *curptr)
  14.553 -{
  14.554 -  const unsigned char *ptr;
  14.555 -
  14.556 -  *val=0;
  14.557 -  ptr=curptr;
  14.558 -  if (!isdigit(*ptr))   /* should start with digit */
  14.559 -    return 0;
  14.560 -  while (isdigit(*ptr) || *ptr=='_') {
  14.561 -    if (*ptr!='_')
  14.562 -      *val=(*val*10)+(*ptr-'0');
  14.563 -    ptr++;
  14.564 -  } /* while */
  14.565 -  if (alphanum(*ptr))   /* number must be delimited by non-alphanumerical */
  14.566 -    return 0;
  14.567 -  if (*ptr=='.' && isdigit(*(ptr+1)))
  14.568 -    return 0;           /* but a fractional part must not be present */
  14.569 -  return (int)(ptr-curptr);
  14.570 -}
  14.571 -
  14.572 -/*  htoi
  14.573 - *
  14.574 - *  Attempts to interpret a numeric symbol as a hexadecimal value. On
  14.575 - *  success it returns the number of characters processed and the value is
  14.576 - *  stored in "val". Otherwise it return 0 and "val" is garbage.
  14.577 - */
  14.578 -static int htoi(cell *val,const unsigned char *curptr)
  14.579 -{
  14.580 -  const unsigned char *ptr;
  14.581 -
  14.582 -  *val=0;
  14.583 -  ptr=curptr;
  14.584 -  if (!isdigit(*ptr))   /* should start with digit */
  14.585 -    return 0;
  14.586 -  if (*ptr=='0' && *(ptr+1)=='x') {     /* C style hexadecimal notation */
  14.587 -    ptr+=2;
  14.588 -    while (ishex(*ptr) || *ptr=='_') {
  14.589 -      if (*ptr!='_') {
  14.590 -        assert(ishex(*ptr));
  14.591 -        *val= *val<<4;
  14.592 -        if (isdigit(*ptr))
  14.593 -          *val+= (*ptr-'0');
  14.594 -        else
  14.595 -          *val+= (tolower(*ptr)-'a'+10);
  14.596 -      } /* if */
  14.597 -      ptr++;
  14.598 -    } /* while */
  14.599 -  } else {
  14.600 -    return 0;
  14.601 -  } /* if */
  14.602 -  if (alphanum(*ptr))
  14.603 -    return 0;
  14.604 -  else
  14.605 -    return (int)(ptr-curptr);
  14.606 -}
  14.607 -
  14.608 -#if defined __GNUC__
  14.609 -static double pow10(int value)
  14.610 -{
  14.611 -  double res=1.0;
  14.612 -  while (value>=4) {
  14.613 -    res*=10000.0;
  14.614 -    value-=5;
  14.615 -  } /* while */
  14.616 -  while (value>=2) {
  14.617 -    res*=100.0;
  14.618 -    value-=2;
  14.619 -  } /* while */
  14.620 -  while (value>=1) {
  14.621 -    res*=10.0;
  14.622 -    value-=1;
  14.623 -  } /* while */
  14.624 -  return res;
  14.625 -}
  14.626 -#endif
  14.627 -
  14.628 -/*  ftoi
  14.629 - *
  14.630 - *  Attempts to interpret a numeric symbol as a rational number, either as
  14.631 - *  IEEE 754 single/double precision floating point or as a fixed point integer.
  14.632 - *  On success it returns the number of characters processed and the value is
  14.633 - *  stored in "val". Otherwise it returns 0 and "val" is unchanged.
  14.634 - *
  14.635 - *  Pawn has stricter definition for rational numbers than most:
  14.636 - *  o  the value must start with a digit; ".5" is not a valid number, you
  14.637 - *     should write "0.5"
  14.638 - *  o  a period must appear in the value, even if an exponent is given; "2e3"
  14.639 - *     is not a valid number, you should write "2.0e3"
  14.640 - *  o  at least one digit must follow the period; "6." is not a valid number,
  14.641 - *     you should write "6.0"
  14.642 - */
  14.643 -static int ftoi(cell *val,const unsigned char *curptr)
  14.644 -{
  14.645 -  const unsigned char *ptr;
  14.646 -  double fnum,ffrac,fmult;
  14.647 -  unsigned long dnum,dbase;
  14.648 -  int i, ignore;
  14.649 -
  14.650 -  assert(rational_digits>=0 && rational_digits<9);
  14.651 -  for (i=0,dbase=1; i<rational_digits; i++)
  14.652 -    dbase*=10;
  14.653 -  fnum=0.0;
  14.654 -  dnum=0L;
  14.655 -  ptr=curptr;
  14.656 -  if (!isdigit(*ptr))   /* should start with digit */
  14.657 -    return 0;
  14.658 -  while (isdigit(*ptr) || *ptr=='_') {
  14.659 -    if (*ptr!='_') {
  14.660 -      fnum=(fnum*10.0)+(*ptr-'0');
  14.661 -      dnum=(dnum*10L)+(*ptr-'0')*dbase;
  14.662 -    } /* if */
  14.663 -    ptr++;
  14.664 -  } /* while */
  14.665 -  if (*ptr!='.')
  14.666 -    return 0;           /* there must be a period */
  14.667 -  ptr++;
  14.668 -  if (!isdigit(*ptr))   /* there must be at least one digit after the dot */
  14.669 -    return 0;
  14.670 -  ffrac=0.0;
  14.671 -  fmult=1.0;
  14.672 -  ignore=FALSE;
  14.673 -  while (isdigit(*ptr) || *ptr=='_') {
  14.674 -    if (*ptr!='_') {
  14.675 -      ffrac=(ffrac*10.0)+(*ptr-'0');
  14.676 -      fmult=fmult/10.0;
  14.677 -      dbase /= 10L;
  14.678 -      dnum += (*ptr-'0')*dbase;
  14.679 -      if (dbase==0L && sc_rationaltag && rational_digits>0 && !ignore) {
  14.680 -        error(222);     /* number of digits exceeds rational number precision */
  14.681 -        ignore=TRUE;
  14.682 -      } /* if */
  14.683 -    } /* if */
  14.684 -    ptr++;
  14.685 -  } /* while */
  14.686 -  fnum += ffrac*fmult;  /* form the number so far */
  14.687 -  if (*ptr=='e') {      /* optional fractional part */
  14.688 -    int exp,sign;
  14.689 -    ptr++;
  14.690 -    if (*ptr=='-') {
  14.691 -      sign=-1;
  14.692 -      ptr++;
  14.693 -    } else {
  14.694 -      sign=1;
  14.695 -    } /* if */
  14.696 -    if (!isdigit(*ptr)) /* 'e' should be followed by a digit */
  14.697 -      return 0;
  14.698 -    exp=0;
  14.699 -    while (isdigit(*ptr)) {
  14.700 -      exp=(exp*10)+(*ptr-'0');
  14.701 -      ptr++;
  14.702 -    } /* while */
  14.703 -    #if defined __GNUC__
  14.704 -      fmult=pow10(exp*sign);
  14.705 -    #else
  14.706 -      fmult=pow(10,exp*sign);
  14.707 -    #endif
  14.708 -    fnum *= fmult;
  14.709 -    dnum *= (unsigned long)(fmult+0.5);
  14.710 -  } /* if */
  14.711 -
  14.712 -  /* decide how to store the number */
  14.713 -  if (sc_rationaltag==0) {
  14.714 -    error(70);          /* rational number support was not enabled */
  14.715 -    *val=0;
  14.716 -  } else if (rational_digits==0) {
  14.717 -    /* floating point */
  14.718 -    #if PAWN_CELL_SIZE==32
  14.719 -      float value=(float)fnum;
  14.720 -      *val=*((cell *)&value);
  14.721 -      #if !defined NDEBUG
  14.722 -        /* I assume that the C/C++ compiler stores "float" values in IEEE 754
  14.723 -         * format (as mandated in the ANSI standard). Test this assumption
  14.724 -         * anyway.
  14.725 -         * Note: problems have been reported with GCC 3.2.x, version 3.3.x works.
  14.726 -         */
  14.727 -        { float test1 = 0.0, test2 = 50.0, test3 = -50.0;
  14.728 -          uint32_t bit = 1;
  14.729 -          /* test 0.0 == all bits 0 */
  14.730 -          assert(*(uint32_t*)&test1==0x00000000L);
  14.731 -          /* test sign & magnitude format */
  14.732 -          assert(((*(uint32_t*)&test2) ^ (*(uint32_t*)&test3)) == (bit << (PAWN_CELL_SIZE-1)));
  14.733 -          /* test a known value */
  14.734 -          assert(*(uint32_t*)&test2==0x42480000L);
  14.735 -        }
  14.736 -      #endif
  14.737 -    #elif PAWN_CELL_SIZE==64
  14.738 -      *val=*((cell *)&fnum);
  14.739 -      #if !defined NDEBUG
  14.740 -        /* I assume that the C/C++ compiler stores "double" values in IEEE 754
  14.741 -         * format (as mandated in the ANSI standard).
  14.742 -         */
  14.743 -        { float test1 = 0.0, test2 = 50.0, test3 = -50.0;
  14.744 -          uint64_t bit = 1;
  14.745 -          /* test 0.0 == all bits 0 */
  14.746 -          assert(*(uint64_t*)&test1==0x00000000L);
  14.747 -          /* test sign & magnitude format */
  14.748 -          assert(((*(uint64_t*)&test2) ^ (*(uint64_t*)&test3)) == (bit << (PAWN_CELL_SIZE-1)));
  14.749 -        }
  14.750 -      #endif
  14.751 -    #else
  14.752 -      #error Unsupported cell size
  14.753 -    #endif
  14.754 -  } else {
  14.755 -    /* fixed point */
  14.756 -    *val=(cell)dnum;
  14.757 -  } /* if */
  14.758 -
  14.759 -  return (int)(ptr-curptr);
  14.760 -}
  14.761 -
  14.762 -/*  number
  14.763 - *
  14.764 - *  Reads in a number (binary, decimal or hexadecimal). It returns the number
  14.765 - *  of characters processed or 0 if the symbol couldn't be interpreted as a
  14.766 - *  number (in this case the argument "val" remains unchanged). This routine
  14.767 - *  relies on the 'early dropout' implementation of the logical or (||)
  14.768 - *  operator.
  14.769 - *
  14.770 - *  Note: the routine doesn't check for a sign (+ or -). The - is checked
  14.771 - *        for at "hier2()" (in fact, it is viewed as an operator, not as a
  14.772 - *        sign) and the + is invalid (as in K&R C, and unlike ANSI C).
  14.773 - */
  14.774 -static int number(cell *val,const unsigned char *curptr)
  14.775 -{
  14.776 -  int i;
  14.777 -  cell value;
  14.778 -
  14.779 -  if ((i=btoi(&value,curptr))!=0      /* binary? */
  14.780 -      || (i=htoi(&value,curptr))!=0   /* hexadecimal? */
  14.781 -      || (i=dtoi(&value,curptr))!=0)  /* decimal? */
  14.782 -  {
  14.783 -    *val=value;
  14.784 -    return i;
  14.785 -  } else {
  14.786 -    return 0;                      /* else not a number */
  14.787 -  } /* if */
  14.788 -}
  14.789 -
  14.790 -static void chrcat(char *str,char chr)
  14.791 -{
  14.792 -  str=strchr(str,'\0');
  14.793 -  *str++=chr;
  14.794 -  *str='\0';
  14.795 -}
  14.796 -
  14.797 -static int preproc_expr(cell *val,int *tag)
  14.798 -{
  14.799 -  int result;
  14.800 -  int index;
  14.801 -  cell code_index;
  14.802 -  char *term;
  14.803 -
  14.804 -  /* Disable staging; it should be disabled already because
  14.805 -   * expressions may not be cut off half-way between conditional
  14.806 -   * compilations. Reset the staging index, but keep the code
  14.807 -   * index.
  14.808 -   */
  14.809 -  if (stgget(&index,&code_index)) {
  14.810 -    error(57);                          /* unfinished expression */
  14.811 -    stgdel(0,code_index);
  14.812 -    stgset(FALSE);
  14.813 -  } /* if */
  14.814 -  assert((lptr-pline)<(int)strlen((char*)pline));   /* lptr must point inside the string */
  14.815 -  #if !defined NO_DEFINE
  14.816 -    /* preprocess the string */
  14.817 -    substallpatterns(pline,sLINEMAX);
  14.818 -    assert((lptr-pline)<(int)strlen((char*)pline)); /* lptr must STILL point inside the string */
  14.819 -  #endif
  14.820 -  /* append a special symbol to the string, so the expression
  14.821 -   * analyzer won't try to read a next line when it encounters
  14.822 -   * an end-of-line
  14.823 -   */
  14.824 -  assert(strlen((char*)pline)<sLINEMAX);
  14.825 -  term=strchr((char*)pline,'\0');
  14.826 -  assert(term!=NULL);
  14.827 -  chrcat((char*)pline,PREPROC_TERM);    /* the "DEL" code (see SC.H) */
  14.828 -  result=constexpr(val,tag,NULL);       /* get value (or 0 on error) */
  14.829 -  *term='\0';                           /* erase the token (if still present) */
  14.830 -  lexclr(FALSE);                        /* clear any "pushed" tokens */
  14.831 -  return result;
  14.832 -}
  14.833 -
  14.834 -/* getstring
  14.835 - * Returns returns a pointer behind the closing quote or to the other
  14.836 - * character that caused the input to be ended.
  14.837 - */
  14.838 -static const unsigned char *getstring(unsigned char *dest,int max,const unsigned char *line)
  14.839 -{
  14.840 -  assert(dest!=NULL && line!=NULL);
  14.841 -  *dest='\0';
  14.842 -  while (*line<=' ' && *line!='\0')
  14.843 -    line++;             /* skip whitespace */
  14.844 -  if (*line=='"') {
  14.845 -    int len=0;
  14.846 -    line++;             /* skip " */
  14.847 -    while (*line!='"' && *line!='\0') {
  14.848 -      if (len<max-1)
  14.849 -        dest[len++]=*line;
  14.850 -      line++;
  14.851 -    } /* if */
  14.852 -    dest[len]='\0';
  14.853 -    if (*line=='"')
  14.854 -      line++;           /* skip closing " */
  14.855 -    else
  14.856 -      error(37);        /* invalid string */
  14.857 -  } else {
  14.858 -    error(37);          /* invalid string */
  14.859 -  } /* if */
  14.860 -  return line;
  14.861 -}
  14.862 -
  14.863 -enum {
  14.864 -  CMD_NONE,
  14.865 -  CMD_TERM,
  14.866 -  CMD_EMPTYLINE,
  14.867 -  CMD_CONDFALSE,
  14.868 -  CMD_INCLUDE,
  14.869 -  CMD_DEFINE,
  14.870 -  CMD_IF,
  14.871 -  CMD_DIRECTIVE,
  14.872 -};
  14.873 -
  14.874 -/*  command
  14.875 - *
  14.876 - *  Recognizes the compiler directives. The function returns:
  14.877 - *     CMD_NONE         the line must be processed
  14.878 - *     CMD_TERM         a pending expression must be completed before processing further lines
  14.879 - *     Other value: the line must be skipped, because:
  14.880 - *     CMD_CONDFALSE    false "#if.." code
  14.881 - *     CMD_EMPTYLINE    line is empty
  14.882 - *     CMD_INCLUDE      the line contains a #include directive
  14.883 - *     CMD_DEFINE       the line contains a #subst directive
  14.884 - *     CMD_IF           the line contains a #if/#else/#endif directive
  14.885 - *     CMD_DIRECTIVE    the line contains some other compiler directive
  14.886 - *
  14.887 - *  Global variables: iflevel, ifstack (altered)
  14.888 - *                    lptr      (altered)
  14.889 - */
  14.890 -static int command(void)
  14.891 -{
  14.892 -  int tok,ret;
  14.893 -  cell val;
  14.894 -  char *str;
  14.895 -  int index;
  14.896 -  cell code_index;
  14.897 -
  14.898 -  while (*lptr<=' ' && *lptr!='\0')
  14.899 -    lptr+=1;
  14.900 -  if (*lptr=='\0')
  14.901 -    return CMD_EMPTYLINE;       /* empty line */
  14.902 -  if (*lptr!='#')
  14.903 -    return SKIPPING ? CMD_CONDFALSE : CMD_NONE; /* it is not a compiler directive */
  14.904 -  /* compiler directive found */
  14.905 -  indent_nowarn=TRUE;           /* allow loose indentation" */
  14.906 -  lexclr(FALSE);                /* clear any "pushed" tokens */
  14.907 -  /* on a pending expression, force to return a silent ';' token and force to
  14.908 -   * re-read the line
  14.909 -   */
  14.910 -  if (!sc_needsemicolon && stgget(&index,&code_index)) {
  14.911 -    lptr=term_expr;
  14.912 -    return CMD_TERM;
  14.913 -  } /* if */
  14.914 -  tok=lex(&val,&str);
  14.915 -  ret=SKIPPING ? CMD_CONDFALSE : CMD_DIRECTIVE;  /* preset 'ret' to CMD_DIRECTIVE (most common case) */
  14.916 -  switch (tok) {
  14.917 -  case tpIF:                    /* conditional compilation */
  14.918 -    ret=CMD_IF;
  14.919 -    assert(iflevel>=0);
  14.920 -    if (iflevel>=sCOMP_STACK)
  14.921 -      error(102,"Conditional compilation stack"); /* table overflow */
  14.922 -    iflevel++;
  14.923 -    if (SKIPPING)
  14.924 -      break;                    /* break out of switch */
  14.925 -    skiplevel=iflevel;
  14.926 -    preproc_expr(&val,NULL);    /* get value (or 0 on error) */
  14.927 -    ifstack[iflevel-1]=(char)(val ? PARSEMODE : SKIPMODE);
  14.928 -    check_empty(lptr);
  14.929 -    break;
  14.930 -  case tpELSE:
  14.931 -  case tpELSEIF:
  14.932 -    ret=CMD_IF;
  14.933 -    assert(iflevel>=0);
  14.934 -    if (iflevel==0) {
  14.935 -      error(26);                /* no matching #if */
  14.936 -      errorset(sRESET,0);
  14.937 -    } else {
  14.938 -      /* check for earlier #else */
  14.939 -      if ((ifstack[iflevel-1] & HANDLED_ELSE)==HANDLED_ELSE) {
  14.940 -        if (tok==tpELSEIF)
  14.941 -          error(61);            /* #elseif directive may not follow an #else */
  14.942 -        else
  14.943 -          error(60);            /* multiple #else directives between #if ... #endif */
  14.944 -        errorset(sRESET,0);
  14.945 -      } else {
  14.946 -        assert(iflevel>0);
  14.947 -        /* if there has been a "parse mode" on this level, set "skip mode",
  14.948 -         * otherwise, clear "skip mode"
  14.949 -         */
  14.950 -        if ((ifstack[iflevel-1] & PARSEMODE)==PARSEMODE) {
  14.951 -          /* there has been a parse mode already on this level, so skip the rest */
  14.952 -          ifstack[iflevel-1] |= (char)SKIPMODE;
  14.953 -        } else {
  14.954 -          /* previous conditions were all FALSE */
  14.955 -          if (tok==tpELSEIF) {
  14.956 -            /* get new expression */
  14.957 -            preproc_expr(&val,NULL);  /* get value (or 0 on error) */
  14.958 -            ifstack[iflevel-1]=(char)(val ? PARSEMODE : SKIPMODE);
  14.959 -          } else {
  14.960 -            /* a simple #else, clear skip mode */
  14.961 -            ifstack[iflevel-1] &= (char)~SKIPMODE;
  14.962 -          } /* if */
  14.963 -        } /* if */
  14.964 -      } /* if */
  14.965 -    } /* if */
  14.966 -    check_empty(lptr);
  14.967 -    break;
  14.968 -  case tpENDIF:
  14.969 -    ret=CMD_IF;
  14.970 -    if (iflevel==0){
  14.971 -      error(26);        /* no matching "#if" */
  14.972 -      errorset(sRESET,0);
  14.973 -    } else {
  14.974 -      iflevel--;
  14.975 -      if (iflevel<skiplevel)
  14.976 -        skiplevel=iflevel;
  14.977 -    } /* if */
  14.978 -    check_empty(lptr);
  14.979 -    break;
  14.980 -  case tINCLUDE:                /* #include directive */
  14.981 -  case tpTRYINCLUDE:
  14.982 -    ret=CMD_INCLUDE;
  14.983 -    if (!SKIPPING)
  14.984 -      doinclude(tok==tpTRYINCLUDE);
  14.985 -    break;
  14.986 -  case tpFILE:
  14.987 -    if (!SKIPPING) {
  14.988 -      char pathname[_MAX_PATH];
  14.989 -      lptr=getstring((unsigned char*)pathname,sizeof pathname,lptr);
  14.990 -      if (strlen(pathname)>0) {
  14.991 -        free(inpfname);
  14.992 -        inpfname=duplicatestring(pathname);
  14.993 -        if (inpfname==NULL)
  14.994 -          error(103);           /* insufficient memory */
  14.995 -      } /* if */
  14.996 -    } /* if */
  14.997 -    check_empty(lptr);
  14.998 -    break;
  14.999 -  case tpLINE:
 14.1000 -    if (!SKIPPING) {
 14.1001 -      if (lex(&val,&str)!=tNUMBER)
 14.1002 -        error(8);               /* invalid/non-constant expression */
 14.1003 -      fline=(int)val;
 14.1004 -    } /* if */
 14.1005 -    check_empty(lptr);
 14.1006 -    break;
 14.1007 -  case tpASSERT:
 14.1008 -    if (!SKIPPING && (sc_debug & sCHKBOUNDS)!=0) {
 14.1009 -      for (str=(char*)lptr; *str<=' ' && *str!='\0'; str++)
 14.1010 -        /* nothing */;          /* save start of expression */
 14.1011 -      preproc_expr(&val,NULL);  /* get constant expression (or 0 on error) */
 14.1012 -      if (!val)
 14.1013 -        error(110,str);         /* assertion failed */
 14.1014 -      check_empty(lptr);
 14.1015 -    } /* if */
 14.1016 -    break;
 14.1017 -  case tpPRAGMA:
 14.1018 -    if (!SKIPPING) {
 14.1019 -      if (lex(&val,&str)==tSYMBOL) {
 14.1020 -        if (strcmp(str,"amxlimit")==0) {
 14.1021 -          preproc_expr(&pc_amxlimit,NULL);
 14.1022 -        } else if (strcmp(str,"amxram")==0) {
 14.1023 -          preproc_expr(&pc_amxram,NULL);
 14.1024 -        } else if (strcmp(str,"codepage")==0) {
 14.1025 -          char name[sNAMEMAX+1];
 14.1026 -          while (*lptr<=' ' && *lptr!='\0')
 14.1027 -            lptr++;
 14.1028 -          if (*lptr=='"') {
 14.1029 -            lptr=getstring((unsigned char*)name,sizeof name,lptr);
 14.1030 -          } else {
 14.1031 -            int i;
 14.1032 -            for (i=0; i<sizeof name && alphanum(*lptr); i++,lptr++)
 14.1033 -              name[i]=*lptr;
 14.1034 -            name[i]='\0';
 14.1035 -          } /* if */
 14.1036 -          if (!cp_set(name))
 14.1037 -            error(108);         /* codepage mapping file not found */
 14.1038 -        } else if (strcmp(str,"compress")==0) {
 14.1039 -          cell val;
 14.1040 -          preproc_expr(&val,NULL);
 14.1041 -          sc_compress=(int)val; /* switch code packing on/off */
 14.1042 -        } else if (strcmp(str,"ctrlchar")==0) {
 14.1043 -          while (*lptr<=' ' && *lptr!='\0')
 14.1044 -            lptr++;
 14.1045 -          if (*lptr=='\0') {
 14.1046 -            sc_ctrlchar=sc_ctrlchar_org;
 14.1047 -          } else {
 14.1048 -            if (lex(&val,&str)!=tNUMBER)
 14.1049 -              error(27);          /* invalid character constant */
 14.1050 -            sc_ctrlchar=(char)val;
 14.1051 -          } /* if */
 14.1052 -        } else if (strcmp(str,"depricated")==0) {
 14.1053 -          while (*lptr<=' ' && *lptr!='\0')
 14.1054 -            lptr++;
 14.1055 -          pc_depricate=(char*)malloc(strlen((char*)lptr)+1);
 14.1056 -          if (pc_depricate!=NULL)
 14.1057 -            strcpy(pc_depricate,(char*)lptr);
 14.1058 -          lptr=(unsigned char*)strchr((char*)lptr,'\0'); /* skip to end (ignore "extra characters on line") */
 14.1059 -        } else if (strcmp(str,"dynamic")==0) {
 14.1060 -          preproc_expr(&pc_stksize,NULL);
 14.1061 -        } else if (strcmp(str,"library")==0) {
 14.1062 -          char name[sNAMEMAX+1];
 14.1063 -          while (*lptr<=' ' && *lptr!='\0')
 14.1064 -            lptr++;
 14.1065 -          if (*lptr=='"') {
 14.1066 -            lptr=getstring((unsigned char*)name,sizeof name,lptr);
 14.1067 -          } else {
 14.1068 -            int i;
 14.1069 -            for (i=0; i<sizeof name && (alphanum(*lptr) || *lptr=='-'); i++,lptr++)
 14.1070 -              name[i]=*lptr;
 14.1071 -            name[i]='\0';
 14.1072 -          } /* if */
 14.1073 -          if (strlen(name)==0) {
 14.1074 -            curlibrary=NULL;
 14.1075 -          } else if (strcmp(name,"-")==0) {
 14.1076 -            pc_addlibtable=FALSE;
 14.1077 -          } else {
 14.1078 -            /* add the name if it does not yet exist in the table */
 14.1079 -            if (find_constval(&libname_tab,name,0)==NULL)
 14.1080 -              curlibrary=append_constval(&libname_tab,name,0,0);
 14.1081 -          } /* if */
 14.1082 -        } else if (strcmp(str,"pack")==0) {
 14.1083 -          cell val;
 14.1084 -          preproc_expr(&val,NULL);      /* default = packed/unpacked */
 14.1085 -          sc_packstr=(int)val;
 14.1086 -        } else if (strcmp(str,"rational")==0) {
 14.1087 -          char name[sNAMEMAX+1];
 14.1088 -          cell digits=0;
 14.1089 -          int i;
 14.1090 -          /* first gather all information, start with the tag name */
 14.1091 -          while (*lptr<=' ' && *lptr!='\0')
 14.1092 -            lptr++;
 14.1093 -          for (i=0; i<sizeof name && alphanum(*lptr); i++,lptr++)
 14.1094 -            name[i]=*lptr;
 14.1095 -          name[i]='\0';
 14.1096 -          /* then the precision (for fixed point arithmetic) */
 14.1097 -          while (*lptr<=' ' && *lptr!='\0')
 14.1098 -            lptr++;
 14.1099 -          if (*lptr=='(') {
 14.1100 -            preproc_expr(&digits,NULL);
 14.1101 -            if (digits<=0 || digits>9) {
 14.1102 -              error(68);        /* invalid rational number precision */
 14.1103 -              digits=0;
 14.1104 -            } /* if */
 14.1105 -            if (*lptr==')')
 14.1106 -              lptr++;
 14.1107 -          } /* if */
 14.1108 -          /* add the tag (make it public) and check the values */
 14.1109 -          i=pc_addtag(name);
 14.1110 -          exporttag(i);
 14.1111 -          if (sc_rationaltag==0 || (sc_rationaltag==i && rational_digits==(int)digits)) {
 14.1112 -            sc_rationaltag=i;
 14.1113 -            rational_digits=(int)digits;
 14.1114 -          } else {
 14.1115 -            error(69);          /* rational number format already set, can only be set once */
 14.1116 -          } /* if */
 14.1117 -        } else if (strcmp(str,"semicolon")==0) {
 14.1118 -          cell val;
 14.1119 -          preproc_expr(&val,NULL);
 14.1120 -          sc_needsemicolon=(int)val;
 14.1121 -        } else if (strcmp(str,"tabsize")==0) {
 14.1122 -          cell val;
 14.1123 -          preproc_expr(&val,NULL);
 14.1124 -          sc_tabsize=(int)val;
 14.1125 -        } else if (strcmp(str,"align")==0) {
 14.1126 -          sc_alignnext=TRUE;
 14.1127 -        } else if (strcmp(str,"unused")==0) {
 14.1128 -          char name[sNAMEMAX+1];
 14.1129 -          int i,comma;
 14.1130 -          symbol *sym;
 14.1131 -          do {
 14.1132 -            /* get the name */
 14.1133 -            while (*lptr<=' ' && *lptr!='\0')
 14.1134 -              lptr++;
 14.1135 -            for (i=0; i<sizeof name && alphanum(*lptr); i++,lptr++)
 14.1136 -              name[i]=*lptr;
 14.1137 -            name[i]='\0';
 14.1138 -            /* get the symbol */
 14.1139 -            sym=findloc(name);
 14.1140 -            if (sym==NULL)
 14.1141 -              sym=findglb(name,sSTATEVAR);
 14.1142 -            if (sym!=NULL) {
 14.1143 -              sym->usage |= uREAD;
 14.1144 -              if (sym->ident==iVARIABLE || sym->ident==iREFERENCE
 14.1145 -                  || sym->ident==iARRAY || sym->ident==iREFARRAY)
 14.1146 -                sym->usage |= uWRITTEN;
 14.1147 -            } else {
 14.1148 -              error(17,name);     /* undefined symbol */
 14.1149 -            } /* if */
 14.1150 -            /* see if a comma follows the name */
 14.1151 -            while (*lptr<=' ' && *lptr!='\0')
 14.1152 -              lptr++;
 14.1153 -            comma= (*lptr==',');
 14.1154 -            if (comma)
 14.1155 -              lptr++;
 14.1156 -          } while (comma);
 14.1157 -        } else {
 14.1158 -          error(207);           /* unknown #pragma */
 14.1159 -        } /* if */
 14.1160 -      } else {
 14.1161 -        error(207);             /* unknown #pragma */
 14.1162 -      } /* if */
 14.1163 -      check_empty(lptr);
 14.1164 -    } /* if */
 14.1165 -    break;
 14.1166 -  case tpENDINPUT:
 14.1167 -  case tpENDSCRPT:
 14.1168 -    if (!SKIPPING) {
 14.1169 -      check_empty(lptr);
 14.1170 -      assert(inpf!=NULL);
 14.1171 -      if (inpf!=inpf_org)
 14.1172 -        pc_closesrc(inpf);
 14.1173 -      inpf=NULL;
 14.1174 -    } /* if */
 14.1175 -    break;
 14.1176 -#if !defined NOEMIT
 14.1177 -  case tpEMIT: {
 14.1178 -    /* write opcode to output file */
 14.1179 -    char name[40];
 14.1180 -    int i;
 14.1181 -    while (*lptr<=' ' && *lptr!='\0')
 14.1182 -      lptr++;
 14.1183 -    for (i=0; i<40 && (isalpha(*lptr) || *lptr=='.'); i++,lptr++)
 14.1184 -      name[i]=(char)tolower(*lptr);
 14.1185 -    name[i]='\0';
 14.1186 -    stgwrite("\t");
 14.1187 -    stgwrite(name);
 14.1188 -    stgwrite(" ");
 14.1189 -    code_idx+=opcodes(1);
 14.1190 -    /* write parameter (if any) */
 14.1191 -    while (*lptr<=' ' && *lptr!='\0')
 14.1192 -      lptr++;
 14.1193 -    if (*lptr!='\0') {
 14.1194 -      symbol *sym;
 14.1195 -      tok=lex(&val,&str);
 14.1196 -      switch (tok) {
 14.1197 -      case tNUMBER:
 14.1198 -      case tRATIONAL:
 14.1199 -        outval(val,FALSE);
 14.1200 -        code_idx+=opargs(1);
 14.1201 -        break;
 14.1202 -      case tSYMBOL:
 14.1203 -        sym=findloc(str);
 14.1204 -        if (sym==NULL)
 14.1205 -          sym=findglb(str,sSTATEVAR);
 14.1206 -        if (sym==NULL || sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0) {
 14.1207 -          error(17,str);        /* undefined symbol */
 14.1208 -        } else {
 14.1209 -          outval(sym->addr,FALSE);
 14.1210 -          /* mark symbol as "used", unknown whether for read or write */
 14.1211 -          markusage(sym,uREAD | uWRITTEN);
 14.1212 -          code_idx+=opargs(1);
 14.1213 -        } /* if */
 14.1214 -        break;
 14.1215 -      default: {
 14.1216 -        char s2[20];
 14.1217 -        extern char *sc_tokens[];/* forward declaration */
 14.1218 -        if (tok<256)
 14.1219 -          sprintf(s2,"%c",(char)tok);
 14.1220 -        else
 14.1221 -          strcpy(s2,sc_tokens[tok-tFIRST]);
 14.1222 -        error(1,sc_tokens[tSYMBOL-tFIRST],s2);
 14.1223 -        break;
 14.1224 -      } /* case */
 14.1225 -      } /* switch */
 14.1226 -    } /* if */
 14.1227 -    stgwrite("\n");
 14.1228 -    check_empty(lptr);
 14.1229 -    break;
 14.1230 -  } /* case */
 14.1231 -#endif
 14.1232 -#if !defined NO_DEFINE
 14.1233 -  case tpDEFINE: {
 14.1234 -    ret=CMD_DEFINE;
 14.1235 -    if (!SKIPPING) {
 14.1236 -      char *pattern,*substitution;
 14.1237 -      const unsigned char *start,*end;
 14.1238 -      int count,prefixlen;
 14.1239 -      stringpair *def;
 14.1240 -      /* find the pattern to match */
 14.1241 -      while (*lptr<=' ' && *lptr!='\0')
 14.1242 -        lptr++;
 14.1243 -      start=lptr;       /* save starting point of the match pattern */
 14.1244 -      count=0;
 14.1245 -      while (*lptr>' ' && *lptr!='\0') {
 14.1246 -        litchar(&lptr,0); /* litchar() advances "lptr" and handles escape characters */
 14.1247 -        count++;
 14.1248 -      } /* while */
 14.1249 -      end=lptr;
 14.1250 -      /* check pattern to match */
 14.1251 -      if (!alpha(*start)) {
 14.1252 -        error(74);      /* pattern must start with an alphabetic character */
 14.1253 -        break;
 14.1254 -      } /* if */
 14.1255 -      /* store matched pattern */
 14.1256 -      pattern=(char*)malloc(count+1);
 14.1257 -      if (pattern==NULL)
 14.1258 -        error(103);     /* insufficient memory */
 14.1259 -      lptr=start;
 14.1260 -      count=0;
 14.1261 -      while (lptr!=end) {
 14.1262 -        assert(lptr<end);
 14.1263 -        assert(*lptr!='\0');
 14.1264 -        pattern[count++]=(char)litchar(&lptr,0);
 14.1265 -      } /* while */
 14.1266 -      pattern[count]='\0';
 14.1267 -      /* special case, erase trailing variable, because it could match anything */
 14.1268 -      if (count>=2 && isdigit(pattern[count-1]) && pattern[count-2]=='%')
 14.1269 -        pattern[count-2]='\0';
 14.1270 -      /* find substitution string */
 14.1271 -      while (*lptr<=' ' && *lptr!='\0')
 14.1272 -        lptr++;
 14.1273 -      start=lptr;       /* save starting point of the match pattern */
 14.1274 -      count=0;
 14.1275 -      end=NULL;
 14.1276 -      while (*lptr!='\0') {
 14.1277 -        /* keep position of the start of trailing whitespace */
 14.1278 -        if (*lptr<=' ') {
 14.1279 -          if (end==NULL)
 14.1280 -            end=lptr;
 14.1281 -        } else {
 14.1282 -          end=NULL;
 14.1283 -        } /* if */
 14.1284 -        count++;
 14.1285 -        lptr++;
 14.1286 -      } /* while */
 14.1287 -      if (end==NULL)
 14.1288 -        end=lptr;
 14.1289 -      /* store matched substitution */
 14.1290 -      substitution=(char*)malloc(count+1);  /* +1 for '\0' */
 14.1291 -      if (substitution==NULL)
 14.1292 -        error(103);     /* insufficient memory */
 14.1293 -      lptr=start;
 14.1294 -      count=0;
 14.1295 -      while (lptr!=end) {
 14.1296 -        assert(lptr<end);
 14.1297 -        assert(*lptr!='\0');
 14.1298 -        substitution[count++]=*lptr++;
 14.1299 -      } /* while */
 14.1300 -      substitution[count]='\0';
 14.1301 -      /* check whether the definition already exists */
 14.1302 -      for (prefixlen=0,start=(unsigned char*)pattern; alphanum(*start); prefixlen++,start++)
 14.1303 -        /* nothing */;
 14.1304 -      assert(prefixlen>0);
 14.1305 -      if ((def=find_subst(pattern,prefixlen))!=NULL) {
 14.1306 -        if (strcmp(def->first,pattern)!=0 || strcmp(def->second,substitution)!=0)
 14.1307 -          error(201,pattern);   /* redefinition of macro (non-identical) */
 14.1308 -        delete_subst(pattern,prefixlen);
 14.1309 -      } /* if */
 14.1310 -      /* add the pattern/substitution pair to the list */
 14.1311 -      assert(strlen(pattern)>0);
 14.1312 -      insert_subst(pattern,substitution,prefixlen);
 14.1313 -      free(pattern);
 14.1314 -      free(substitution);
 14.1315 -    } /* if */
 14.1316 -    break;
 14.1317 -  } /* case */
 14.1318 -  case tpUNDEF:
 14.1319 -    if (!SKIPPING) {
 14.1320 -      if (lex(&val,&str)==tSYMBOL) {
 14.1321 -        ret=delete_subst(str,strlen(str));
 14.1322 -        if (!ret) {
 14.1323 -          /* also undefine normal constants */
 14.1324 -          symbol *sym=findconst(str,NULL);
 14.1325 -          if (sym!=NULL && (sym->usage & (uENUMROOT | uENUMFIELD))==0) {
 14.1326 -            delete_symbol(&glbtab,sym);
 14.1327 -            ret=TRUE;
 14.1328 -          } /* if */
 14.1329 -        } /* if */
 14.1330 -        if (!ret)
 14.1331 -          error(17,str);        /* undefined symbol */
 14.1332 -      } else {
 14.1333 -        error(20,str);          /* invalid symbol name */
 14.1334 -      } /* if */
 14.1335 -      check_empty(lptr);
 14.1336 -    } /* if */
 14.1337 -    break;
 14.1338 -#endif
 14.1339 -  case tpERROR:
 14.1340 -    while (*lptr<=' ' && *lptr!='\0')
 14.1341 -      lptr++;
 14.1342 -    if (!SKIPPING)
 14.1343 -      error(111,lptr);  /* user error */
 14.1344 -    break;
 14.1345 -  default:
 14.1346 -    error(31);          /* unknown compiler directive */
 14.1347 -    ret=SKIPPING ? CMD_CONDFALSE : CMD_NONE;  /* process as normal line */
 14.1348 -  } /* switch */
 14.1349 -  return ret;
 14.1350 -}
 14.1351 -
 14.1352 -#if !defined NO_DEFINE
 14.1353 -static int is_startstring(const unsigned char *string)
 14.1354 -{
 14.1355 -  if (*string=='\"' || *string=='\'')
 14.1356 -    return TRUE;                        /* "..." */
 14.1357 -
 14.1358 -  if (*string=='!') {
 14.1359 -    string++;
 14.1360 -    if (*string=='\"' || *string=='\'')
 14.1361 -      return TRUE;                      /* !"..." */
 14.1362 -    if (*string==sc_ctrlchar) {
 14.1363 -      string++;
 14.1364 -      if (*string=='\"' || *string=='\'')
 14.1365 -        return TRUE;                    /* !\"..." */
 14.1366 -    } /* if */
 14.1367 -  } else if (*string==sc_ctrlchar) {
 14.1368 -    string++;
 14.1369 -    if (*string=='\"' || *string=='\'')
 14.1370 -      return TRUE;                      /* \"..." */
 14.1371 -    if (*string=='!') {
 14.1372 -      string++;
 14.1373 -      if (*string=='\"' || *string=='\'')
 14.1374 -        return TRUE;                    /* \!"..." */
 14.1375 -    } /* if */
 14.1376 -  } /* if */
 14.1377 -
 14.1378 -  return FALSE;
 14.1379 -}
 14.1380 -
 14.1381 -static const unsigned char *skipstring(const unsigned char *string)
 14.1382 -{
 14.1383 -  char endquote;
 14.1384 -  int flags=0;
 14.1385 -
 14.1386 -  while (*string=='!' || *string==sc_ctrlchar) {
 14.1387 -    if (*string==sc_ctrlchar)
 14.1388 -      flags=RAWMODE;
 14.1389 -    string++;
 14.1390 -  } /* while */
 14.1391 -
 14.1392 -  endquote=*string;
 14.1393 -  assert(endquote=='"' || endquote=='\'');
 14.1394 -  string++;             /* skip open quote */
 14.1395 -  while (*string!=endquote && *string!='\0')
 14.1396 -    litchar(&string,flags);
 14.1397 -  return string;
 14.1398 -}
 14.1399 -
 14.1400 -static const unsigned char *skippgroup(const unsigned char *string)
 14.1401 -{
 14.1402 -  int nest=0;
 14.1403 -  char open=*string;
 14.1404 -  char close;
 14.1405 -
 14.1406 -  switch (open) {
 14.1407 -  case '(':
 14.1408 -    close=')';
 14.1409 -    break;
 14.1410 -  case '{':
 14.1411 -    close='}';
 14.1412 -    break;
 14.1413 -  case '[':
 14.1414 -    close=']';
 14.1415 -    break;
 14.1416 -  case '<':
 14.1417 -    close='>';
 14.1418 -    break;
 14.1419 -  default:
 14.1420 -    assert(0);
 14.1421 -	close='\0';         /* only to avoid a compiler warning */
 14.1422 -  }/* switch */
 14.1423 -
 14.1424 -  string++;
 14.1425 -  while (*string!=close || nest>0) {
 14.1426 -    if (*string==open)
 14.1427 -      nest++;
 14.1428 -    else if (*string==close)
 14.1429 -      nest--;
 14.1430 -    else if (is_startstring(string))
 14.1431 -      string=skipstring(string);
 14.1432 -    if (*string=='\0')
 14.1433 -      break;
 14.1434 -    string++;
 14.1435 -  } /* while */
 14.1436 -  return string;
 14.1437 -}
 14.1438 -
 14.1439 -static char *strdel(char *str,size_t len)
 14.1440 -{
 14.1441 -  size_t length=strlen(str);
 14.1442 -  if (len>length)
 14.1443 -    len=length;
 14.1444 -  memmove(str, str+len, length-len+1);  /* include EOS byte */
 14.1445 -  return str;
 14.1446 -}
 14.1447 -
 14.1448 -static char *strins(char *dest,char *src,size_t srclen)
 14.1449 -{
 14.1450 -  size_t destlen=strlen(dest);
 14.1451 -  assert(srclen<=strlen(src));
 14.1452 -  memmove(dest+srclen, dest, destlen+1);/* include EOS byte */
 14.1453 -  memcpy(dest, src, srclen);
 14.1454 -  return dest;
 14.1455 -}
 14.1456 -
 14.1457 -static int substpattern(unsigned char *line,size_t buffersize,char *pattern,char *substitution)
 14.1458 -{
 14.1459 -  int prefixlen;
 14.1460 -  const unsigned char *p,*s,*e;
 14.1461 -  unsigned char *args[10];
 14.1462 -  int match,arg,len;
 14.1463 -
 14.1464 -  memset(args,0,sizeof args);
 14.1465 -
 14.1466 -  /* check the length of the prefix */
 14.1467 -  for (prefixlen=0,s=(unsigned char*)pattern; alphanum(*s); prefixlen++,s++)
 14.1468 -    /* nothing */;
 14.1469 -  assert(prefixlen>0);
 14.1470 -  assert(strncmp((char*)line,pattern,prefixlen)==0);
 14.1471 -
 14.1472 -  /* pattern prefix matches; match the rest of the pattern, gather
 14.1473 -   * the parameters
 14.1474 -   */
 14.1475 -  s=line+prefixlen;
 14.1476 -  p=(unsigned char*)pattern+prefixlen;
 14.1477 -  match=TRUE;         /* so far, pattern matches */
 14.1478 -  while (match && *s!='\0' && *p!='\0') {
 14.1479 -    if (*p=='%') {
 14.1480 -      p++;            /* skip '%' */
 14.1481 -      if (isdigit(*p)) {
 14.1482 -        arg=*p-'0';
 14.1483 -        assert(arg>=0 && arg<=9);
 14.1484 -        p++;          /* skip parameter id */
 14.1485 -        assert(*p!='\0');
 14.1486 -        /* match the source string up to the character after the digit
 14.1487 -         * (skipping strings in the process
 14.1488 -         */
 14.1489 -        e=s;
 14.1490 -        while (*e!=*p && *e!='\0' && *e!='\n') {
 14.1491 -          if (is_startstring(e))              /* skip strings */
 14.1492 -            e=skipstring(e);
 14.1493 -          else if (strchr("({[",*e)!=NULL)    /* skip parenthized groups */
 14.1494 -            e=skippgroup(e);
 14.1495 -          if (*e!='\0')
 14.1496 -            e++;      /* skip non-alphapetic character (or closing quote of
 14.1497 -                       * a string, or the closing paranthese of a group) */
 14.1498 -        } /* while */
 14.1499 -        /* store the parameter (overrule any earlier) */
 14.1500 -        if (args[arg]!=NULL)
 14.1501 -          free(args[arg]);
 14.1502 -        len=(int)(e-s);
 14.1503 -        args[arg]=(unsigned char*)malloc(len+1);
 14.1504 -        if (args[arg]==NULL)
 14.1505 -          error(103); /* insufficient memory */
 14.1506 -        strlcpy((char*)args[arg],(char*)s,len+1);
 14.1507 -        /* character behind the pattern was matched too */
 14.1508 -        if (*e==*p) {
 14.1509 -          s=e+1;
 14.1510 -        } else if (*e=='\n' && *p==';' && *(p+1)=='\0' && !sc_needsemicolon) {
 14.1511 -          s=e;    /* allow a trailing ; in the pattern match to end of line */
 14.1512 -        } else {
 14.1513 -          assert(*e=='\0' || *e=='\n');
 14.1514 -          match=FALSE;
 14.1515 -          s=e;
 14.1516 -        } /* if */
 14.1517 -        p++;
 14.1518 -      } else {
 14.1519 -        match=FALSE;
 14.1520 -      } /* if */
 14.1521 -    } else if (*p==';' && *(p+1)=='\0' && !sc_needsemicolon) {
 14.1522 -      /* source may be ';' or end of the line */
 14.1523 -      while (*s<=' ' && *s!='\0')
 14.1524 -        s++;          /* skip white space */
 14.1525 -      if (*s!=';' && *s!='\0')
 14.1526 -        match=FALSE;
 14.1527 -      p++;            /* skip the semicolon in the pattern */
 14.1528 -    } else {
 14.1529 -      cell ch;
 14.1530 -      /* skip whitespace between two non-alphanumeric characters, except
 14.1531 -       * for two identical symbols
 14.1532 -       */
 14.1533 -      assert((char*)p>pattern);
 14.1534 -      if (!alphanum(*p) && *(p-1)!=*p)
 14.1535 -        while (*s<=' ' && *s!='\0')
 14.1536 -          s++;                  /* skip white space */
 14.1537 -      ch=litchar(&p,0);         /* this increments "p" */
 14.1538 -      if (*s!=ch)
 14.1539 -        match=FALSE;
 14.1540 -      else
 14.1541 -        s++;                    /* this character matches */
 14.1542 -    } /* if */
 14.1543 -  } /* while */
 14.1544 -
 14.1545 -  if (match && *p=='\0') {
 14.1546 -    /* if the last character to match is an alphanumeric character, the
 14.1547 -     * current character in the source may not be alphanumeric
 14.1548 -     */
 14.1549 -    assert(p>(unsigned char*)pattern);
 14.1550 -    if (alphanum(*(p-1)) && alphanum(*s))
 14.1551 -      match=FALSE;
 14.1552 -  } /* if */
 14.1553 -
 14.1554 -  if (match) {
 14.1555 -    /* calculate the length of the substituted string */
 14.1556 -    for (e=(unsigned char*)substitution,len=0; *e!='\0'; e++) {
 14.1557 -      if (*e=='%' && isdigit(*(e+1))) {
 14.1558 -        arg=*(e+1)-'0';
 14.1559 -        assert(arg>=0 && arg<=9);
 14.1560 -        if (args[arg]!=NULL)
 14.1561 -          len+=strlen((char*)args[arg]);
 14.1562 -        else
 14.1563 -          len+=2;     /* copy '%' plus digit */
 14.1564 -        e++;          /* skip %, digit is skipped later */
 14.1565 -      } else {
 14.1566 -        len++;
 14.1567 -      } /* if */
 14.1568 -    } /* for */
 14.1569 -    /* check length of the string after substitution */
 14.1570 -    if (strlen((char*)line) + len - (int)(s-line) > buffersize) {
 14.1571 -      error(75);      /* line too long */
 14.1572 -    } else {
 14.1573 -      /* substitute pattern */
 14.1574 -      strdel((char*)line,(int)(s-line));
 14.1575 -      for (e=(unsigned char*)substitution,s=line; *e!='\0'; e++) {
 14.1576 -        if (*e=='%' && isdigit(*(e+1))) {
 14.1577 -          arg=*(e+1)-'0';
 14.1578 -          assert(arg>=0 && arg<=9);
 14.1579 -          if (args[arg]!=NULL) {
 14.1580 -            strins((char*)s,(char*)args[arg],strlen((char*)args[arg]));
 14.1581 -            s+=strlen((char*)args[arg]);
 14.1582 -          } else {
 14.1583 -            error(236); /* parameter does not exist, incorrect #define pattern */
 14.1584 -            strins((char*)s,(char*)e,2);
 14.1585 -            s+=2;
 14.1586 -          } /* if */
 14.1587 -          e++;          /* skip %, digit is skipped later */
 14.1588 -        } else {
 14.1589 -          strins((char*)s,(char*)e,1);
 14.1590 -          s++;
 14.1591 -        } /* if */
 14.1592 -      } /* for */
 14.1593 -    } /* if */
 14.1594 -  } /* if */
 14.1595 -
 14.1596 -  for (arg=0; arg<10; arg++)
 14.1597 -    if (args[arg]!=NULL)
 14.1598 -      free(args[arg]);
 14.1599 -
 14.1600 -  return match;
 14.1601 -}
 14.1602 -
 14.1603 -static void substallpatterns(unsigned char *line,int buffersize)
 14.1604 -{
 14.1605 -  unsigned char *start, *end;
 14.1606 -  int prefixlen;
 14.1607 -  stringpair *subst;
 14.1608 -
 14.1609 -  start=line;
 14.1610 -  while (*start!='\0') {
 14.1611 -    /* find the start of a prefix (skip all non-alphabetic characters),
 14.1612 -     * also skip strings
 14.1613 -     */
 14.1614 -    while (!alpha(*start) && *start!='\0') {
 14.1615 -      /* skip strings */
 14.1616 -      if (is_startstring(start)) {
 14.1617 -        start=(unsigned char *)skipstring(start);
 14.1618 -        if (*start=='\0')
 14.1619 -          break;        /* abort loop on error */
 14.1620 -      } /* if */
 14.1621 -      start++;          /* skip non-alphapetic character (or closing quote of a string) */
 14.1622 -    } /* while */
 14.1623 -    if (*start=='\0')
 14.1624 -      break;            /* abort loop on error */
 14.1625 -    /* if matching the operator "defined", skip it plus the symbol behind it */
 14.1626 -    if (strncmp((char*)start,"defined",7)==0 && *(start+7)<=' ') {
 14.1627 -      start+=7;         /* skip "defined" */
 14.1628 -      /* skip white space & parantheses */
 14.1629 -      while (*start<=' ' && *start!='\0' || *start=='(')
 14.1630 -        start++;
 14.1631 -      /* skip the symbol behind it */
 14.1632 -      while (alphanum(*start))
 14.1633 -        start++;
 14.1634 -      /* drop back into the main loop */
 14.1635 -      continue;
 14.1636 -    } /* if */
 14.1637 -    /* get the prefix (length), look for a matching definition */
 14.1638 -    prefixlen=0;
 14.1639 -    end=start;
 14.1640 -    while (alphanum(*end)) {
 14.1641 -      prefixlen++;
 14.1642 -      end++;
 14.1643 -    } /* while */
 14.1644 -    assert(prefixlen>0);
 14.1645 -    subst=find_subst((char*)start,prefixlen);
 14.1646 -    if (subst!=NULL) {
 14.1647 -      /* properly match the pattern and substitute */
 14.1648 -      if (!substpattern(start,buffersize-(int)(start-line),subst->first,subst->second))
 14.1649 -        start=end;      /* match failed, skip this prefix */
 14.1650 -      /* match succeeded: do not update "start", because the substitution text
 14.1651 -       * may be matched by other macros
 14.1652 -       */
 14.1653 -    } else {
 14.1654 -      start=end;        /* no macro with this prefix, skip this prefix */
 14.1655 -    } /* if */
 14.1656 -  } /* while */
 14.1657 -}
 14.1658 -#endif
 14.1659 -
 14.1660 -/*  preprocess
 14.1661 - *
 14.1662 - *  Reads a line by readline() into "pline" and performs basic preprocessing:
 14.1663 - *  deleting comments, skipping lines with false "#if.." code and recognizing
 14.1664 - *  other compiler directives. There is an indirect recursion: lex() calls
 14.1665 - *  preprocess() if a new line must be read, preprocess() calls command(),
 14.1666 - *  which at his turn calls lex() to identify the token.
 14.1667 - *
 14.1668 - *  Global references: lptr     (altered)
 14.1669 - *                     pline    (altered)
 14.1670 - *                     freading (referred to only)
 14.1671 - */
 14.1672 -SC_FUNC void preprocess(void)
 14.1673 -{
 14.1674 -  int iscommand;
 14.1675 -
 14.1676 -  if (!freading)
 14.1677 -    return;
 14.1678 -  do {
 14.1679 -    readline(pline);
 14.1680 -    stripcom(pline);    /* ??? no need for this when reading back from list file (in the second pass) */
 14.1681 -    lptr=pline;         /* set "line pointer" to start of the parsing buffer */
 14.1682 -    iscommand=command();
 14.1683 -    if (iscommand!=CMD_NONE)
 14.1684 -      errorset(sRESET,0); /* reset error flag ("panic mode") on empty line or directive */
 14.1685 -    #if !defined NO_DEFINE
 14.1686 -      if (iscommand==CMD_NONE) {
 14.1687 -        assert(lptr!=term_expr);
 14.1688 -        substallpatterns(pline,sLINEMAX);
 14.1689 -        lptr=pline;       /* reset "line pointer" to start of the parsing buffer */
 14.1690 -      } /* if */
 14.1691 -    #endif
 14.1692 -    if (sc_status==statFIRST && sc_listing && freading
 14.1693 -        && (iscommand==CMD_NONE || iscommand==CMD_EMPTYLINE || iscommand==CMD_DIRECTIVE))
 14.1694 -    {
 14.1695 -      listline++;
 14.1696 -      if (fline!=listline) {
 14.1697 -        listline=fline;
 14.1698 -        setlinedirect(fline);
 14.1699 -      } /* if */
 14.1700 -      if (iscommand==CMD_EMPTYLINE)
 14.1701 -        pc_writeasm(outf,"\n");
 14.1702 -      else
 14.1703 -        pc_writeasm(outf,(char*)pline);
 14.1704 -    } /* if */
 14.1705 -  } while (iscommand!=CMD_NONE && iscommand!=CMD_TERM && freading); /* enddo */
 14.1706 -}
 14.1707 -
 14.1708 -static const unsigned char *unpackedstring(const unsigned char *lptr,int flags)
 14.1709 -{
 14.1710 -  while (*lptr!='\"' && *lptr!='\0') {
 14.1711 -    if (*lptr=='\a') {          /* ignore '\a' (which was inserted at a line concatenation) */
 14.1712 -      lptr++;
 14.1713 -      continue;
 14.1714 -    } /* if */
 14.1715 -    litadd(litchar(&lptr,flags | UTF8MODE));  /* litchar() alters "lptr" */
 14.1716 -  } /* while */
 14.1717 -  litadd(0);                    /* terminate string */
 14.1718 -  return lptr;
 14.1719 -}
 14.1720 -
 14.1721 -static const unsigned char *packedstring(const unsigned char *lptr,int flags)
 14.1722 -{
 14.1723 -  int i;
 14.1724 -  ucell val,c;
 14.1725 -
 14.1726 -  i=sizeof(ucell)-(sCHARBITS/8); /* start at most significant byte */
 14.1727 -  val=0;
 14.1728 -  while (*lptr!='\"' && *lptr!='\0') {
 14.1729 -    if (*lptr=='\a') {          /* ignore '\a' (which was inserted at a line concatenation) */
 14.1730 -      lptr++;
 14.1731 -      continue;
 14.1732 -    } /* if */
 14.1733 -    c=litchar(&lptr,flags);     /* litchar() alters "lptr" */
 14.1734 -    if (c>=(ucell)(1 << sCHARBITS))
 14.1735 -      error(43);                /* character constant exceeds range */
 14.1736 -    val |= (c << 8*i);
 14.1737 -    if (i==0) {
 14.1738 -      litadd(val);
 14.1739 -      val=0;
 14.1740 -    } /* if */
 14.1741 -    i=(i+sizeof(ucell)-(sCHARBITS/8)) % sizeof(ucell);
 14.1742 -  } /* if */
 14.1743 -  /* save last code; make sure there is at least one terminating zero character */
 14.1744 -  if (i!=(int)(sizeof(ucell)-(sCHARBITS/8)))
 14.1745 -    litadd(val);        /* at least one zero character in "val" */
 14.1746 -  else
 14.1747 -    litadd(0);          /* add full cell of zeros */
 14.1748 -  return lptr;
 14.1749 -}
 14.1750 -
 14.1751 -/*  lex(lexvalue,lexsym)        Lexical Analysis
 14.1752 - *
 14.1753 - *  lex() first deletes leading white space, then checks for multi-character
 14.1754 - *  operators, keywords (including most compiler directives), numbers,
 14.1755 - *  labels, symbols and literals (literal characters are converted to a number
 14.1756 - *  and are returned as such). If every check fails, the line must contain
 14.1757 - *  a single-character operator. So, lex() returns this character. In the other
 14.1758 - *  case (something did match), lex() returns the number of the token. All
 14.1759 - *  these tokens have been assigned numbers above 255.
 14.1760 - *
 14.1761 - *  Some tokens have "attributes":
 14.1762 - *     tNUMBER        the value of the number is return in "lexvalue".
 14.1763 - *     tRATIONAL      the value is in IEEE 754 encoding or in fixed point
 14.1764 - *                    encoding in "lexvalue".
 14.1765 - *     tSYMBOL        the first sNAMEMAX characters of the symbol are
 14.1766 - *                    stored in a buffer, a pointer to this buffer is
 14.1767 - *                    returned in "lexsym".
 14.1768 - *     tLABEL         the first sNAMEMAX characters of the label are
 14.1769 - *                    stored in a buffer, a pointer to this buffer is
 14.1770 - *                    returned in "lexsym".
 14.1771 - *     tSTRING        the string is stored in the literal pool, the index
 14.1772 - *                    in the literal pool to this string is stored in
 14.1773 - *                    "lexvalue".
 14.1774 - *
 14.1775 - *  lex() stores all information (the token found and possibly its attribute)
 14.1776 - *  in global variables. This allows a token to be examined twice. If "_pushed"
 14.1777 - *  is true, this information is returned.
 14.1778 - *
 14.1779 - *  Global references: lptr          (altered)
 14.1780 - *                     fline         (referred to only)
 14.1781 - *                     litidx        (referred to only)
 14.1782 - *                     _lextok, _lexval, _lexstr
 14.1783 - *                     _pushed
 14.1784 - */
 14.1785 -
 14.1786 -static int _pushed;
 14.1787 -static int _lextok;
 14.1788 -static cell _lexval;
 14.1789 -static char _lexstr[sLINEMAX+1];
 14.1790 -static int _lexnewline;
 14.1791 -
 14.1792 -SC_FUNC void lexinit(void)
 14.1793 -{
 14.1794 -  stkidx=0;             /* index for pushstk() and popstk() */
 14.1795 -  iflevel=0;            /* preprocessor: nesting of "#if" is currently 0 */
 14.1796 -  skiplevel=0;          /* preprocessor: not currently skipping */
 14.1797 -  icomment=0;           /* currently not in a multiline comment */
 14.1798 -  _pushed=FALSE;        /* no token pushed back into lex */
 14.1799 -  _lexnewline=FALSE;
 14.1800 -}
 14.1801 -
 14.1802 -char *sc_tokens[] = {
 14.1803 -         "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
 14.1804 -         "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
 14.1805 -         "...", "..", "::",
 14.1806 -         "assert", "break", "case", "char", "const", "continue", "default",
 14.1807 -         "defined", "do", "else", "enum", "exit", "for", "forward", "goto",
 14.1808 -         "if", "native", "new", "decl", "operator", "public", "return", "sizeof",
 14.1809 -         "sleep", "state", "static", "stock", "switch", "tagof", "while",
 14.1810 -         "#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
 14.1811 -         "#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma",
 14.1812 -         "#tryinclude", "#undef",
 14.1813 -         ";", ";", "-integer value-", "-rational value-", "-identifier-",
 14.1814 -         "-label-", "-string-"
 14.1815 -       };
 14.1816 -
 14.1817 -SC_FUNC int lex(cell *lexvalue,char **lexsym)
 14.1818 -{
 14.1819 -  int i,toolong,newline,stringflags;
 14.1820 -  char **tokptr;
 14.1821 -  const unsigned char *starttoken;
 14.1822 -
 14.1823 -  if (_pushed) {
 14.1824 -    _pushed=FALSE;      /* reset "_pushed" flag */
 14.1825 -    *lexvalue=_lexval;
 14.1826 -    *lexsym=_lexstr;
 14.1827 -    return _lextok;
 14.1828 -  } /* if */
 14.1829 -
 14.1830 -  _lextok=0;            /* preset all values */
 14.1831 -  _lexval=0;
 14.1832 -  _lexstr[0]='\0';
 14.1833 -  *lexvalue=_lexval;
 14.1834 -  *lexsym=_lexstr;
 14.1835 -  _lexnewline=FALSE;
 14.1836 -  if (!freading)
 14.1837 -    return 0;
 14.1838 -
 14.1839 -  newline= (lptr==pline);       /* does lptr point to start of line buffer */
 14.1840 -  while (*lptr<=' ') {          /* delete leading white space */
 14.1841 -    if (*lptr=='\0') {
 14.1842 -      preprocess();             /* preprocess resets "lptr" */
 14.1843 -      if (!freading)
 14.1844 -        return 0;
 14.1845 -      if (lptr==term_expr)      /* special sequence to terminate a pending expression */
 14.1846 -        return (_lextok=tENDEXPR);
 14.1847 -      _lexnewline=TRUE;         /* set this after preprocess(), because
 14.1848 -                                 * preprocess() calls lex() recursively */
 14.1849 -      newline=TRUE;
 14.1850 -    } else {
 14.1851 -      lptr+=1;
 14.1852 -    } /* if */
 14.1853 -  } /* while */
 14.1854 -  if (newline) {
 14.1855 -    stmtindent=0;
 14.1856 -    for (i=0; i<(int)(lptr-pline); i++)
 14.1857 -      if (pline[i]=='\t' && sc_tabsize>0)
 14.1858 -        stmtindent += (int)(sc_tabsize - (stmtindent+sc_tabsize) % sc_tabsize);
 14.1859 -      else
 14.1860 -        stmtindent++;
 14.1861 -  } /* if */
 14.1862 -
 14.1863 -  i=tFIRST;
 14.1864 -  tokptr=sc_tokens;
 14.1865 -  while (i<=tMIDDLE) {  /* match multi-character operators */
 14.1866 -    if (*lptr==**tokptr && match(*tokptr,FALSE)) {
 14.1867 -      _lextok=i;
 14.1868 -      if (pc_docexpr)   /* optionally concatenate to documentation string */
 14.1869 -        insert_autolist(*tokptr);
 14.1870 -      return _lextok;
 14.1871 -    } /* if */
 14.1872 -    i+=1;
 14.1873 -    tokptr+=1;
 14.1874 -  } /* while */
 14.1875 -  while (i<=tLAST) {    /* match reserved words and compiler directives */
 14.1876 -    if (*lptr==**tokptr && match(*tokptr,TRUE)) {
 14.1877 -      _lextok=i;
 14.1878 -      errorset(sRESET,0); /* reset error flag (clear the "panic mode")*/
 14.1879 -      if (pc_docexpr)   /* optionally concatenate to documentation string */
 14.1880 -        insert_autolist(*tokptr);
 14.1881 -      return _lextok;
 14.1882 -    } /* if */
 14.1883 -    i+=1;
 14.1884 -    tokptr+=1;
 14.1885 -  } /* while */
 14.1886 -
 14.1887 -  starttoken=lptr;      /* save start pointer (for concatenating to documentation string) */
 14.1888 -  if ((i=number(&_lexval,lptr))!=0) {   /* number */
 14.1889 -    _lextok=tNUMBER;
 14.1890 -    *lexvalue=_lexval;
 14.1891 -    lptr+=i;
 14.1892 -  } else if ((i=ftoi(&_lexval,lptr))!=0) {
 14.1893 -    _lextok=tRATIONAL;
 14.1894 -    *lexvalue=_lexval;
 14.1895 -    lptr+=i;
 14.1896 -  } else if (alpha(*lptr)) {            /* symbol or label */
 14.1897 -    /*  Note: only sNAMEMAX characters are significant. The compiler
 14.1898 -     *        generates a warning if a symbol exceeds this length.
 14.1899 -     */
 14.1900 -    _lextok=tSYMBOL;
 14.1901 -    i=0;
 14.1902 -    toolong=0;
 14.1903 -    while (alphanum(*lptr)){
 14.1904 -      _lexstr[i]=*lptr;
 14.1905 -      lptr+=1;
 14.1906 -      if (i<sNAMEMAX)
 14.1907 -        i+=1;
 14.1908 -      else
 14.1909 -        toolong=1;
 14.1910 -    } /* while */
 14.1911 -    _lexstr[i]='\0';
 14.1912 -    if (toolong)
 14.1913 -      error(200,_lexstr,sNAMEMAX);  /* symbol too long, truncated to sNAMEMAX chars */
 14.1914 -    if (_lexstr[0]==PUBLIC_CHAR && _lexstr[1]=='\0') {
 14.1915 -      _lextok=PUBLIC_CHAR;  /* '@' all alone is not a symbol, it is an operator */
 14.1916 -    } else if (_lexstr[0]=='_' && _lexstr[1]=='\0') {
 14.1917 -      _lextok='_';      /* '_' by itself is not a symbol, it is a placeholder */
 14.1918 -    } /* if */
 14.1919 -    if (*lptr==':' && *(lptr+1)!=':' && _lextok!=PUBLIC_CHAR) {
 14.1920 -      if (sc_allowtags) {
 14.1921 -        _lextok=tLABEL; /* it wasn't a normal symbol, it was a label/tagname */
 14.1922 -        lptr+=1;        /* skip colon */
 14.1923 -      } else if (find_constval(&tagname_tab,_lexstr,0)!=NULL) {
 14.1924 -        /* this looks like a tag override (because a tag with this name
 14.1925 -         * exists), but tags are not allowed right now, so it is probably an
 14.1926 -         * error
 14.1927 -         */
 14.1928 -        error(220);
 14.1929 -      } /* if */
 14.1930 -    } /* if */
 14.1931 -  } else if (*lptr=='\"' || *lptr==sc_ctrlchar && *(lptr+1)=='\"')
 14.1932 -  {                                     /* unpacked string literal */
 14.1933 -    _lextok=tSTRING;
 14.1934 -    stringflags= (*lptr==sc_ctrlchar) ? RAWMODE : 0;
 14.1935 -    *lexvalue=_lexval=litidx;
 14.1936 -    lptr+=1;            /* skip double quote */
 14.1937 -    if ((stringflags & RAWMODE)!=0)
 14.1938 -      lptr+=1;          /* skip "escape" character too */
 14.1939 -    lptr=sc_packstr ? packedstring(lptr,stringflags) : unpackedstring(lptr,stringflags);
 14.1940 -    if (*lptr=='\"')
 14.1941 -      lptr+=1;          /* skip final quote */
 14.1942 -    else
 14.1943 -      error(37);        /* invalid (non-terminated) string */
 14.1944 -  } else if (*lptr=='!' && *(lptr+1)=='\"'
 14.1945 -             || *lptr=='!' && *(lptr+1)==sc_ctrlchar && *(lptr+2)=='\"'
 14.1946 -             || *lptr==sc_ctrlchar && *(lptr+1)=='!' && *(lptr+2)=='\"')
 14.1947 -  {                                     /* packed string literal */
 14.1948 -    _lextok=tSTRING;
 14.1949 -    stringflags= (*lptr==sc_ctrlchar || *(lptr+1)==sc_ctrlchar) ? RAWMODE : 0;
 14.1950 -    *lexvalue=_lexval=litidx;
 14.1951 -    lptr+=2;            /* skip exclamation point and double quote */
 14.1952 -    if ((stringflags & RAWMODE)!=0)
 14.1953 -      lptr+=1;          /* skip "escape" character too */
 14.1954 -    lptr=sc_packstr ? unpackedstring(lptr,stringflags) : packedstring(lptr,stringflags);
 14.1955 -    if (*lptr=='\"')
 14.1956 -      lptr+=1;          /* skip final quote */
 14.1957 -    else
 14.1958 -      error(37);        /* invalid (non-terminated) string */
 14.1959 -  } else if (*lptr=='\'') {             /* character literal */
 14.1960 -    lptr+=1;            /* skip quote */
 14.1961 -    _lextok=tNUMBER;
 14.1962 -    *lexvalue=_lexval=litchar(&lptr,UTF8MODE);
 14.1963 -    if (*lptr=='\'')
 14.1964 -      lptr+=1;          /* skip final quote */
 14.1965 -    else
 14.1966 -      error(27);        /* invalid character constant (must be one character) */
 14.1967 -  } else if (*lptr==';') {      /* semicolumn resets "error" flag */
 14.1968 -    _lextok=';';
 14.1969 -    lptr+=1;
 14.1970 -    errorset(sRESET,0); /* reset error flag (clear the "panic mode")*/
 14.1971 -  } else {
 14.1972 -    _lextok=*lptr;      /* if every match fails, return the character */
 14.1973 -    lptr+=1;            /* increase the "lptr" pointer */
 14.1974 -  } /* if */
 14.1975 -
 14.1976 -  if (pc_docexpr) {     /* optionally concatenate to documentation string */
 14.1977 -    char *docstr=(char*)malloc(((int)(lptr-starttoken)+1)*sizeof(char));
 14.1978 -    if (docstr!=NULL) {
 14.1979 -      strlcpy(docstr,(char*)starttoken,(int)(lptr-starttoken)+1);
 14.1980 -      insert_autolist(docstr);
 14.1981 -      free(docstr);
 14.1982 -    } /* if */
 14.1983 -  } /* if */
 14.1984 -  return _lextok;
 14.1985 -}
 14.1986 -
 14.1987 -/*  lexpush
 14.1988 - *
 14.1989 - *  Pushes a token back, so the next call to lex() will return the token
 14.1990 - *  last examined, instead of a new token.
 14.1991 - *
 14.1992 - *  Only one token can be pushed back.
 14.1993 - *
 14.1994 - *  In fact, lex() already stores the information it finds into global
 14.1995 - *  variables, so all that is to be done is set a flag that informs lex()
 14.1996 - *  to read and return the information from these variables, rather than
 14.1997 - *  to read in a new token from the input file.
 14.1998 - */
 14.1999 -SC_FUNC void lexpush(void)
 14.2000 -{
 14.2001 -  assert(_pushed==FALSE);
 14.2002 -  _pushed=TRUE;
 14.2003 -}
 14.2004 -
 14.2005 -/*  lexclr
 14.2006 - *
 14.2007 - *  Sets the variable "_pushed" to 0 to make sure lex() will read in a new
 14.2008 - *  symbol (a not continue with some old one). This is required upon return
 14.2009 - *  from Assembler mode, and in a few cases after detecting an syntax error.
 14.2010 - */
 14.2011 -SC_FUNC void lexclr(int clreol)
 14.2012 -{
 14.2013 -  _pushed=FALSE;
 14.2014 -  if (clreol) {
 14.2015 -    lptr=(unsigned char*)strchr((char*)pline,'\0');
 14.2016 -    assert(lptr!=NULL);
 14.2017 -  } /* if */
 14.2018 -}
 14.2019 -
 14.2020 -/*  matchtoken
 14.2021 - *
 14.2022 - *  This routine is useful if only a simple check is needed. If the token
 14.2023 - *  differs from the one expected, it is pushed back.
 14.2024 - *  This function returns 1 for "token found" and 2 for "implied statement
 14.2025 - *  termination token" found --the statement termination is an end of line in
 14.2026 - *  an expression where there is no pending operation. Such an implied token
 14.2027 - *  (i.e. not present in the source code) should not be pushed back, which is
 14.2028 - *  why it is sometimes important to distinguish the two.
 14.2029 - */
 14.2030 -SC_FUNC int matchtoken(int token)
 14.2031 -{
 14.2032 -  cell val;
 14.2033 -  char *str;
 14.2034 -  int tok;
 14.2035 -
 14.2036 -  tok=lex(&val,&str);
 14.2037 -  if (tok==token || token==tTERM && (tok==';' || tok==tENDEXPR)) {
 14.2038 -    return 1;
 14.2039 -  } else if (!sc_needsemicolon && token==tTERM && (_lexnewline || !freading)) {
 14.2040 -    /* Push "tok" back, because it is the token following the implicit statement
 14.2041 -     * termination (newline) token.
 14.2042 -     */
 14.2043 -    lexpush();
 14.2044 -    return 2;
 14.2045 -  } else {
 14.2046 -    lexpush();
 14.2047 -    return 0;
 14.2048 -  } /* if */
 14.2049 -}
 14.2050 -
 14.2051 -/*  tokeninfo
 14.2052 - *
 14.2053 - *  Returns additional information of a token after using "matchtoken()"
 14.2054 - *  or needtoken(). It does no harm using this routine after a call to
 14.2055 - *  "lex()", but lex() already returns the same information.
 14.2056 - *
 14.2057 - *  The token itself is the return value. Normally, this one is already known.
 14.2058 - */
 14.2059 -SC_FUNC int tokeninfo(cell *val,char **str)
 14.2060 -{
 14.2061 -  /* if the token was pushed back, tokeninfo() returns the token and
 14.2062 -   * parameters of the *next* token, not of the *current* token.
 14.2063 -   */
 14.2064 -  assert(!_pushed);
 14.2065 -  *val=_lexval;
 14.2066 -  *str=_lexstr;
 14.2067 -  return _lextok;
 14.2068 -}
 14.2069 -
 14.2070 -/*  needtoken
 14.2071 - *
 14.2072 - *  This routine checks for a required token and gives an error message if
 14.2073 - *  it isn't there (and returns 0/FALSE in that case). Like function matchtoken(),
 14.2074 - *  this function returns 1 for "token found" and 2 for "statement termination
 14.2075 - *  token" found; see function matchtoken() for details.
 14.2076 - *
 14.2077 - *  Global references: _lextok;
 14.2078 - */
 14.2079 -SC_FUNC int needtoken(int token)
 14.2080 -{
 14.2081 -  char s1[20],s2[20];
 14.2082 -  int t;
 14.2083 -
 14.2084 -  if ((t=matchtoken(token))!=0) {
 14.2085 -    return t;
 14.2086 -  } else {
 14.2087 -    /* token already pushed back */
 14.2088 -    assert(_pushed);
 14.2089 -    if (token<256)
 14.2090 -      sprintf(s1,"%c",(char)token);        /* single character token */
 14.2091 -    else
 14.2092 -      strcpy(s1,sc_tokens[token-tFIRST]);  /* multi-character symbol */
 14.2093 -    if (!freading)
 14.2094 -      strcpy(s2,"-end of file-");
 14.2095 -    else if (_lextok<256)
 14.2096 -      sprintf(s2,"%c",(char)_lextok);
 14.2097 -    else
 14.2098 -      strcpy(s2,sc_tokens[_lextok-tFIRST]);
 14.2099 -    error(1,s1,s2);     /* expected ..., but found ... */
 14.2100 -    return FALSE;
 14.2101 -  } /* if */
 14.2102 -}
 14.2103 -
 14.2104 -/*  match
 14.2105 - *
 14.2106 - *  Compares a series of characters from the input file with the characters
 14.2107 - *  in "st" (that contains a token). If the token on the input file matches
 14.2108 - *  "st", the input file pointer "lptr" is adjusted to point to the next
 14.2109 - *  token, otherwise "lptr" remains unaltered.
 14.2110 - *
 14.2111 - *  If the parameter "end: is true, match() requires that the first character
 14.2112 - *  behind the recognized token is non-alphanumeric.
 14.2113 - *
 14.2114 - *  Global references: lptr   (altered)
 14.2115 - */
 14.2116 -static int match(char *st,int end)
 14.2117 -{
 14.2118 -  int k;
 14.2119 -  const unsigned char *ptr;
 14.2120 -
 14.2121 -  k=0;
 14.2122 -  ptr=lptr;
 14.2123 -  while (st[k]) {
 14.2124 -    if ((unsigned char)st[k]!=*ptr)
 14.2125 -      return 0;
 14.2126 -    k+=1;
 14.2127 -    ptr+=1;
 14.2128 -  } /* while */
 14.2129 -  if (end) {            /* symbol must terminate with non-alphanumeric char */
 14.2130 -    if (alphanum(*ptr))
 14.2131 -      return 0;
 14.2132 -  } /* if */
 14.2133 -  lptr=ptr;     /* match found, skip symbol */
 14.2134 -  return 1;
 14.2135 -}
 14.2136 -
 14.2137 -static void chk_grow_litq(void)
 14.2138 -{
 14.2139 -  if (litidx>=litmax) {
 14.2140 -    cell *p;
 14.2141 -
 14.2142 -    litmax+=sDEF_LITMAX;
 14.2143 -    p=(cell *)realloc(litq,litmax*sizeof(cell));
 14.2144 -    if (p==NULL)
 14.2145 -      error(102,"literal table");   /* literal table overflow (fatal error) */
 14.2146 -    litq=p;
 14.2147 -  } /* if */
 14.2148 -}
 14.2149 -
 14.2150 -/*  litadd
 14.2151 - *
 14.2152 - *  Adds a value at the end of the literal queue. The literal queue is used
 14.2153 - *  for literal strings used in functions and for initializing array variables.
 14.2154 - *
 14.2155 - *  Global references: litidx  (altered)
 14.2156 - *                     litq    (altered)
 14.2157 - */
 14.2158 -SC_FUNC void litadd(cell value)
 14.2159 -{
 14.2160 -  chk_grow_litq();
 14.2161 -  assert(litidx<litmax);
 14.2162 -  litq[litidx++]=value;
 14.2163 -}
 14.2164 -
 14.2165 -/*  litinsert
 14.2166 - *
 14.2167 - *  Inserts a value into the literal queue. This is sometimes necessary for
 14.2168 - *  initializing multi-dimensional arrays.
 14.2169 - *
 14.2170 - *  Global references: litidx  (altered)
 14.2171 - *                     litq    (altered)
 14.2172 - */
 14.2173 -SC_FUNC void litinsert(cell value,int pos)
 14.2174 -{
 14.2175 -  chk_grow_litq();
 14.2176 -  assert(litidx<litmax);
 14.2177 -  assert(pos>=0 && pos<=litidx);
 14.2178 -  memmove(litq+(pos+1),litq+pos,(litidx-pos)*sizeof(cell));
 14.2179 -  litidx++;
 14.2180 -  litq[pos]=value;
 14.2181 -}
 14.2182 -
 14.2183 -/*  litchar
 14.2184 - *
 14.2185 - *  Return current literal character and increase the pointer to point
 14.2186 - *  just behind this literal character.
 14.2187 - *
 14.2188 - *  Note: standard "escape sequences" are suported, but the backslash may be
 14.2189 - *        replaced by another character; the syntax '\ddd' is supported,
 14.2190 - *        but ddd must be decimal!
 14.2191 - */
 14.2192 -static cell litchar(const unsigned char **lptr,int flags)
 14.2193 -{
 14.2194 -  cell c=0;
 14.2195 -  const unsigned char *cptr;
 14.2196 -
 14.2197 -  cptr=*lptr;
 14.2198 -  if ((flags & RAWMODE)!=0 || *cptr!=sc_ctrlchar) {  /* no escape character */
 14.2199 -    #if !defined NO_UTF8
 14.2200 -      if (sc_is_utf8 && (flags & UTF8MODE)!=0) {
 14.2201 -        c=get_utf8_char(cptr,&cptr);
 14.2202 -        assert(c>=0);   /* file was already scanned for conformance to UTF-8 */
 14.2203 -      } else {
 14.2204 -    #endif
 14.2205 -      #if !defined NO_CODEPAGE
 14.2206 -        c=cp_translate(cptr,&cptr);
 14.2207 -      #else
 14.2208 -        c=*cptr;
 14.2209 -        cptr+=1;
 14.2210 -      #endif
 14.2211 -    #if !defined NO_UTF8
 14.2212 -      } /* if */
 14.2213 -    #endif
 14.2214 -  } else {
 14.2215 -    cptr+=1;
 14.2216 -    if (*cptr==sc_ctrlchar) {
 14.2217 -      c=*cptr;          /* \\ == \ (the escape character itself) */
 14.2218 -      cptr+=1;
 14.2219 -    } else {
 14.2220 -      switch (*cptr) {
 14.2221 -      case 'a':         /* \a == audible alarm */
 14.2222 -        c=7;
 14.2223 -        cptr+=1;
 14.2224 -        break;
 14.2225 -      case 'b':         /* \b == backspace */
 14.2226 -        c=8;
 14.2227 -        cptr+=1;
 14.2228 -        break;
 14.2229 -      case 'e':         /* \e == escape */
 14.2230 -        c=27;
 14.2231 -        cptr+=1;
 14.2232 -        break;
 14.2233 -      case 'f':         /* \f == form feed */
 14.2234 -        c=12;
 14.2235 -        cptr+=1;
 14.2236 -        break;
 14.2237 -      case 'n':         /* \n == NewLine character */
 14.2238 -        c=10;
 14.2239 -        cptr+=1;
 14.2240 -        break;
 14.2241 -      case 'r':         /* \r == carriage return */
 14.2242 -        c=13;
 14.2243 -        cptr+=1;
 14.2244 -        break;
 14.2245 -      case 't':         /* \t == horizontal TAB */
 14.2246 -        c=9;
 14.2247 -        cptr+=1;
 14.2248 -        break;
 14.2249 -      case 'v':         /* \v == vertical TAB */
 14.2250 -        c=11;
 14.2251 -        cptr+=1;
 14.2252 -        break;
 14.2253 -      case 'x':
 14.2254 -        cptr+=1;
 14.2255 -        c=0;
 14.2256 -        while (ishex(*cptr)) {
 14.2257 -          if (isdigit(*cptr))
 14.2258 -            c=(c<<4)+(*cptr-'0');
 14.2259 -          else
 14.2260 -            c=(c<<4)+(tolower(*cptr)-'a'+10);
 14.2261 -          cptr++;
 14.2262 -        } /* while */
 14.2263 -        if (*cptr==';')
 14.2264 -          cptr++;       /* swallow a trailing ';' */
 14.2265 -        break;
 14.2266 -      case '\'':        /* \' == ' (single quote) */
 14.2267 -      case '"':         /* \" == " (single quote) */
 14.2268 -      case '%':         /* \% == % (percent) */
 14.2269 -        c=*cptr;
 14.2270 -        cptr+=1;
 14.2271 -        break;
 14.2272 -      default:
 14.2273 -        if (isdigit(*cptr)) {   /* \ddd */
 14.2274 -          c=0;
 14.2275 -          while (*cptr>='0' && *cptr<='9')  /* decimal! */
 14.2276 -            c=c*10 + *cptr++ - '0';
 14.2277 -          if (*cptr==';')
 14.2278 -            cptr++;     /* swallow a trailing ';' */
 14.2279 -        } else {
 14.2280 -          error(27);    /* invalid character constant */
 14.2281 -        } /* if */
 14.2282 -      } /* switch */
 14.2283 -    } /* if */
 14.2284 -  } /* if */
 14.2285 -  *lptr=cptr;
 14.2286 -  assert(c>=0);
 14.2287 -  return c;
 14.2288 -}
 14.2289 -
 14.2290 -/*  alpha
 14.2291 - *
 14.2292 - *  Test if character "c" is alphabetic ("a".."z"), an underscore ("_")
 14.2293 - *  or an "at" sign ("@"). The "@" is an extension to standard C.
 14.2294 - */
 14.2295 -static int alpha(char c)
 14.2296 -{
 14.2297 -  return (isalpha(c) || c=='_' || c==PUBLIC_CHAR);
 14.2298 -}
 14.2299 -
 14.2300 -/*  alphanum
 14.2301 - *
 14.2302 - *  Test if character "c" is alphanumeric ("a".."z", "0".."9", "_" or "@")
 14.2303 - */
 14.2304 -SC_FUNC int alphanum(char c)
 14.2305 -{
 14.2306 -  return (alpha(c) || isdigit(c));
 14.2307 -}
 14.2308 -
 14.2309 -/*  ishex
 14.2310 - *
 14.2311 - *  Test if character "c" is a hexadecimal digit ("0".."9" or "a".."f").
 14.2312 - */
 14.2313 -SC_FUNC int ishex(char c)
 14.2314 -{
 14.2315 -  return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F');
 14.2316 -}
 14.2317 -
 14.2318 -/* The local variable table must be searched backwards, so that the deepest
 14.2319 - * nesting of local variables is searched first. The simplest way to do
 14.2320 - * this is to insert all new items at the head of the list.
 14.2321 - * In the global list, the symbols are kept in sorted order, so that the
 14.2322 - * public functions are written in sorted order.
 14.2323 - */
 14.2324 -static symbol *add_symbol(symbol *root,symbol *entry,int sort)
 14.2325 -{
 14.2326 -  symbol *newsym;
 14.2327 -
 14.2328 -  if (sort)
 14.2329 -    while (root->next!=NULL && strcmp(entry->name,root->next->name)>0)
 14.2330 -      root=root->next;
 14.2331 -
 14.2332 -  if ((newsym=(symbol *)malloc(sizeof(symbol)))==NULL) {
 14.2333 -    error(103);
 14.2334 -    return NULL;
 14.2335 -  } /* if */
 14.2336 -  memcpy(newsym,entry,sizeof(symbol));
 14.2337 -  newsym->next=root->next;
 14.2338 -  root->next=newsym;
 14.2339 -  return newsym;
 14.2340 -}
 14.2341 -
 14.2342 -static void free_symbol(symbol *sym)
 14.2343 -{
 14.2344 -  arginfo *arg;
 14.2345 -
 14.2346 -  /* free all sub-symbol allocated memory blocks, depending on the
 14.2347 -   * kind of the symbol
 14.2348 -   */
 14.2349 -  assert(sym!=NULL);
 14.2350 -  if (sym->ident==iFUNCTN) {
 14.2351 -    /* run through the argument list; "default array" arguments
 14.2352 -     * must be freed explicitly; the tag list must also be freed */
 14.2353 -    assert(sym->dim.arglist!=NULL);
 14.2354 -    for (arg=sym->dim.arglist; arg->ident!=0; arg++) {
 14.2355 -      if (arg->ident==iREFARRAY && arg->hasdefault)
 14.2356 -        free(arg->defvalue.array.data);
 14.2357 -      else if (arg->ident==iVARIABLE
 14.2358 -               && ((arg->hasdefault & uSIZEOF)!=0 || (arg->hasdefault & uTAGOF)!=0))
 14.2359 -        free(arg->defvalue.size.symname);
 14.2360 -      assert(arg->tags!=NULL);
 14.2361 -      free(arg->tags);
 14.2362 -    } /* for */
 14.2363 -    free(sym->dim.arglist);
 14.2364 -    if (sym->states!=NULL) {
 14.2365 -      delete_consttable(sym->states);
 14.2366 -      free(sym->states);
 14.2367 -    } /* if */
 14.2368 -  } else if (sym->ident==iVARIABLE || sym->ident==iARRAY) {
 14.2369 -    if (sym->states!=NULL) {
 14.2370 -      delete_consttable(sym->states);
 14.2371 -      free(sym->states);
 14.2372 -    } /* if */
 14.2373 -  } else if (sym->ident==iCONSTEXPR && (sym->usage & uENUMROOT)==uENUMROOT) {
 14.2374 -    /* free the constant list of an enum root */
 14.2375 -    assert(sym->dim.enumlist!=NULL);
 14.2376 -    delete_consttable(sym->dim.enumlist);
 14.2377 -    free(sym->dim.enumlist);
 14.2378 -  } /* if */
 14.2379 -  assert(sym->refer!=NULL);
 14.2380 -  free(sym->refer);
 14.2381 -  if (sym->documentation!=NULL)
 14.2382 -    free(sym->documentation);
 14.2383 -  free(sym);
 14.2384 -}
 14.2385 -
 14.2386 -SC_FUNC void delete_symbol(symbol *root,symbol *sym)
 14.2387 -{
 14.2388 -  /* find the symbol and its predecessor
 14.2389 -   * (this function assumes that you will never delete a symbol that is not
 14.2390 -   * in the table pointed at by "root")
 14.2391 -   */
 14.2392 -  assert(root!=sym);
 14.2393 -  while (root->next!=sym) {
 14.2394 -    root=root->next;
 14.2395 -    assert(root!=NULL);
 14.2396 -  } /* while */
 14.2397 -
 14.2398 -  /* unlink it, then free it */
 14.2399 -  root->next=sym->next;
 14.2400 -  free_symbol(sym);
 14.2401 -}
 14.2402 -
 14.2403 -SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions)
 14.2404 -{
 14.2405 -  symbol *sym,*parent_sym;
 14.2406 -  constvalue *stateptr;
 14.2407 -  int mustdelete;
 14.2408 -
 14.2409 -  /* erase only the symbols with a deeper nesting level than the
 14.2410 -   * specified nesting level */
 14.2411 -  while (root->next!=NULL) {
 14.2412 -    sym=root->next;
 14.2413 -    if (sym->compound<level)
 14.2414 -      break;
 14.2415 -    switch (sym->ident) {
 14.2416 -    case iLABEL:
 14.2417 -      mustdelete=delete_labels;
 14.2418 -      break;
 14.2419 -    case iVARIABLE:
 14.2420 -    case iARRAY:
 14.2421 -      /* do not delete global variables if functions are preserved */
 14.2422 -      mustdelete=delete_functions;
 14.2423 -      break;
 14.2424 -    case iREFERENCE:
 14.2425 -      /* always delete references (only exist as function parameters) */
 14.2426 -      mustdelete=TRUE;
 14.2427 -      break;
 14.2428 -    case iREFARRAY:
 14.2429 -      /* a global iREFARRAY symbol is the return value of a function: delete
 14.2430 -       * this only if "globals" must be deleted; other iREFARRAY instances
 14.2431 -       * (locals) are also deleted
 14.2432 -       */
 14.2433 -      mustdelete=delete_functions;
 14.2434 -      for (parent_sym=sym->parent; parent_sym!=NULL && parent_sym->ident!=iFUNCTN; parent_sym=parent_sym->parent)
 14.2435 -        assert(parent_sym->ident==iREFARRAY);
 14.2436 -      assert(parent_sym==NULL || (parent_sym->ident==iFUNCTN && parent_sym->parent==NULL));
 14.2437 -      if (parent_sym==NULL || parent_sym->ident!=iFUNCTN)
 14.2438 -        mustdelete=TRUE;
 14.2439 -      break;
 14.2440 -    case iCONSTEXPR:
 14.2441 -      /* delete constants, except predefined constants */
 14.2442 -      mustdelete=delete_functions || (sym->usage & uPREDEF)==0;
 14.2443 -      break;
 14.2444 -    case iFUNCTN:
 14.2445 -      /* optionally preserve globals (variables & functions), but
 14.2446 -       * NOT native functions
 14.2447 -       */
 14.2448 -      mustdelete=delete_functions || (sym->usage & uNATIVE)!=0;
 14.2449 -      assert(sym->parent==NULL);
 14.2450 -      break;
 14.2451 -    case iARRAYCELL:
 14.2452 -    case iARRAYCHAR:
 14.2453 -    case iEXPRESSION:
 14.2454 -    case iVARARGS:
 14.2455 -    default:
 14.2456 -      assert(0);
 14.2457 -      break;
 14.2458 -    } /* switch */
 14.2459 -    if (mustdelete) {
 14.2460 -      root->next=sym->next;
 14.2461 -      free_symbol(sym);
 14.2462 -    } else {
 14.2463 -      /* if the function was prototyped, but not implemented in this source,
 14.2464 -       * mark it as such, so that its use can be flagged
 14.2465 -       */
 14.2466 -      if (sym->ident==iFUNCTN && (sym->usage & uDEFINE)==0)
 14.2467 -        sym->usage |= uMISSING;
 14.2468 -      if (sym->ident==iFUNCTN || sym->ident==iVARIABLE || sym->ident==iARRAY)
 14.2469 -        sym->usage &= ~uDEFINE; /* clear "defined" flag */
 14.2470 -      /* set all states as "undefined" too */
 14.2471 -      if (sym->states!=NULL)
 14.2472 -        for (stateptr=sym->states->next; stateptr!=NULL; stateptr=stateptr->next)
 14.2473 -          stateptr->value=0;
 14.2474 -      /* for user defined operators, also remove the "prototyped" flag, as
 14.2475 -       * user-defined operators *must* be declared before use
 14.2476 -       */
 14.2477 -      if (sym->ident==iFUNCTN && !alpha(*sym->name))
 14.2478 -        sym->usage &= ~uPROTOTYPED;
 14.2479 -      root=sym;                 /* skip the symbol */
 14.2480 -    } /* if */
 14.2481 -  } /* if */
 14.2482 -}
 14.2483 -
 14.2484 -/* The purpose of the hash is to reduce the frequency of a "name"
 14.2485 - * comparison (which is costly). There is little interest in avoiding
 14.2486 - * clusters in similar names, which is why this function is plain simple.
 14.2487 - */
 14.2488 -SC_FUNC uint32_t namehash(const char *name)
 14.2489 -{
 14.2490 -  const unsigned char *ptr=(const unsigned char *)name;
 14.2491 -  int len=strlen(name);
 14.2492 -  if (len==0)
 14.2493 -    return 0L;
 14.2494 -  assert(len<256);
 14.2495 -  return (len<<24Lu) + (ptr[0]<<16Lu) + (ptr[len-1]<<8Lu) + (ptr[len>>1Lu]);
 14.2496 -}
 14.2497 -
 14.2498 -static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int automaton,int *cmptag)
 14.2499 -{
 14.2500 -  symbol *firstmatch=NULL;
 14.2501 -  symbol *sym=root->next;
 14.2502 -  int count=0;
 14.2503 -  unsigned long hash=namehash(name);
 14.2504 -  while (sym!=NULL) {
 14.2505 -    if (hash==sym->hash && strcmp(name,sym->name)==0        /* check name */
 14.2506 -        && (sym->parent==NULL || sym->ident==iCONSTEXPR)    /* sub-types (hierarchical types) are skipped, except for enum fields */
 14.2507 -        && (sym->fnumber<0 || sym->fnumber==fnumber))       /* check file number for scope */
 14.2508 -    {
 14.2509 -      assert(sym->states==NULL || sym->states->next!=NULL); /* first element of the state list is the "root" */
 14.2510 -      if (sym->ident==iFUNCTN
 14.2511 -          || automaton<0 && sym->states==NULL
 14.2512 -          || automaton>=0 && sym->states!=NULL && state_getfsa(sym->states->next->index)==automaton)
 14.2513 -      {
 14.2514 -        if (cmptag==NULL)
 14.2515 -          return sym;   /* return first match */
 14.2516 -        /* return closest match or first match; count number of matches */
 14.2517 -        if (firstmatch==NULL)
 14.2518 -          firstmatch=sym;
 14.2519 -        assert(cmptag!=NULL);
 14.2520 -        if (*cmptag==0)
 14.2521 -          count++;
 14.2522 -        if (*cmptag==sym->tag) {
 14.2523 -          *cmptag=1;    /* good match found, set number of matches to 1 */
 14.2524 -          return sym;
 14.2525 -        } /* if */
 14.2526 -      } /* if */
 14.2527 -    } /*  */
 14.2528 -    sym=sym->next;
 14.2529 -  } /* while */
 14.2530 -  if (cmptag!=NULL && firstmatch!=NULL)
 14.2531 -    *cmptag=count;
 14.2532 -  return firstmatch;
 14.2533 -}
 14.2534 -
 14.2535 -static symbol *find_symbol_child(const symbol *root,const symbol *sym)
 14.2536 -{
 14.2537 -  symbol *ptr=root->next;
 14.2538 -  while (ptr!=NULL) {
 14.2539 -    if (ptr->parent==sym)
 14.2540 -      return ptr;
 14.2541 -    ptr=ptr->next;
 14.2542 -  } /* while */
 14.2543 -  return NULL;
 14.2544 -}
 14.2545 -
 14.2546 -/* Adds "bywhom" to the list of referrers of "entry". Typically,
 14.2547 - * bywhom will be the function that uses a variable or that calls
 14.2548 - * the function.
 14.2549 - */
 14.2550 -SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
 14.2551 -{
 14.2552 -  int count;
 14.2553 -
 14.2554 -  assert(bywhom!=NULL);         /* it makes no sense to add a "void" referrer */
 14.2555 -  assert(entry!=NULL);
 14.2556 -  assert(entry->refer!=NULL);
 14.2557 -
 14.2558 -  /* see if it is already there */
 14.2559 -  for (count=0; count<entry->numrefers && entry->refer[count]!=bywhom; count++)
 14.2560 -    /* nothing */;
 14.2561 -  if (count<entry->numrefers) {
 14.2562 -    assert(entry->refer[count]==bywhom);
 14.2563 -    return TRUE;
 14.2564 -  } /* if */
 14.2565 -
 14.2566 -  /* see if there is an empty spot in the referrer list */
 14.2567 -  for (count=0; count<entry->numrefers && entry->refer[count]!=NULL; count++)
 14.2568 -    /* nothing */;
 14.2569 -  assert(count <= entry->numrefers);
 14.2570 -  if (count==entry->numrefers) {
 14.2571 -    symbol **refer;
 14.2572 -    int newsize=2*entry->numrefers;
 14.2573 -    assert(newsize>0);
 14.2574 -    /* grow the referrer list */
 14.2575 -    refer=(symbol**)realloc(entry->refer,newsize*sizeof(symbol*));
 14.2576 -    if (refer==NULL)
 14.2577 -      return FALSE;             /* insufficient memory */
 14.2578 -    /* initialize the new entries */
 14.2579 -    entry->refer=refer;
 14.2580 -    for (count=entry->numrefers; count<newsize; count++)
 14.2581 -      entry->refer[count]=NULL;
 14.2582 -    count=entry->numrefers;     /* first empty spot */
 14.2583 -    entry->numrefers=newsize;
 14.2584 -  } /* if */
 14.2585 -
 14.2586 -  /* add the referrer */
 14.2587 -  assert(entry->refer[count]==NULL);
 14.2588 -  entry->refer[count]=bywhom;
 14.2589 -  return TRUE;
 14.2590 -}
 14.2591 -
 14.2592 -SC_FUNC void markusage(symbol *sym,int usage)
 14.2593 -{
 14.2594 -  assert(sym!=NULL);
 14.2595 -  sym->usage |= (char)usage;
 14.2596 -  if ((usage & uWRITTEN)!=0)
 14.2597 -    sym->lnumber=fline;
 14.2598 -  /* check if (global) reference must be added to the symbol */
 14.2599 -  if ((usage & (uREAD | uWRITTEN))!=0) {
 14.2600 -    /* only do this for global symbols */
 14.2601 -    if (sym->vclass==sGLOBAL) {
 14.2602 -      /* "curfunc" should always be valid, since statements may not occurs
 14.2603 -       * outside functions; in the case of syntax errors, however, the
 14.2604 -       * compiler may arrive through this function
 14.2605 -       */
 14.2606 -      if (curfunc!=NULL)
 14.2607 -        refer_symbol(sym,curfunc);
 14.2608 -    } /* if */
 14.2609 -  } /* if */
 14.2610 -}
 14.2611 -
 14.2612 -
 14.2613 -/*  findglb
 14.2614 - *
 14.2615 - *  Returns a pointer to the global symbol (if found) or NULL (if not found)
 14.2616 - */
 14.2617 -SC_FUNC symbol *findglb(const char *name,int filter)
 14.2618 -{
 14.2619 -  /* find a symbol with a matching automaton first */
 14.2620 -  symbol *sym=NULL;
 14.2621 -
 14.2622 -  if (filter>sGLOBAL && sc_curstates>0) {
 14.2623 -    /* find a symbol whose state list matches the current fsa */
 14.2624 -    sym=find_symbol(&glbtab,name,fcurrent,state_getfsa(sc_curstates),NULL);
 14.2625 -    if (sym!=NULL && sym->ident!=iFUNCTN) {
 14.2626 -      /* if sym!=NULL, we found a variable in the automaton; now we should
 14.2627 -       * also verify whether there is an intersection between the symbol's
 14.2628 -       * state list and the current state list
 14.2629 -       */
 14.2630 -      assert(sym->states!=NULL && sym->states->next!=NULL);
 14.2631 -      if (!state_conflict_id(sc_curstates,sym->states->next->index))
 14.2632 -        sym=NULL;
 14.2633 -    } /* if */
 14.2634 -  } /* if */
 14.2635 -
 14.2636 -  /* if no symbol with a matching automaton exists, find a variable/function
 14.2637 -   * that has no state(s) attached to it
 14.2638 -   */
 14.2639 -  if (sym==NULL)
 14.2640 -    sym=find_symbol(&glbtab,name,fcurrent,-1,NULL);
 14.2641 -  return sym;
 14.2642 -}
 14.2643 -
 14.2644 -/*  findloc
 14.2645 - *
 14.2646 - *  Returns a pointer to the local symbol (if found) or NULL (if not found).
 14.2647 - *  See add_symbol() how the deepest nesting level is searched first.
 14.2648 - */
 14.2649 -SC_FUNC symbol *findloc(const char *name)
 14.2650 -{
 14.2651 -  return find_symbol(&loctab,name,-1,-1,NULL);
 14.2652 -}
 14.2653 -
 14.2654 -SC_FUNC symbol *findconst(const char *name,int *cmptag)
 14.2655 -{
 14.2656 -  symbol *sym;
 14.2657 -
 14.2658 -  sym=find_symbol(&loctab,name,-1,-1,cmptag);  /* try local symbols first */
 14.2659 -  if (sym==NULL || sym->ident!=iCONSTEXPR)     /* not found, or not a constant */
 14.2660 -    sym=find_symbol(&glbtab,name,fcurrent,-1,cmptag);
 14.2661 -  if (sym==NULL || sym->ident!=iCONSTEXPR)
 14.2662 -    return NULL;
 14.2663 -  assert(sym->parent==NULL || (sym->usage & uENUMFIELD)!=0);
 14.2664 -  /* ^^^ constants have no hierarchy, but enumeration fields may have a parent */
 14.2665 -  return sym;
 14.2666 -}
 14.2667 -
 14.2668 -SC_FUNC symbol *finddepend(const symbol *parent)
 14.2669 -{
 14.2670 -  symbol *sym;
 14.2671 -
 14.2672 -  sym=find_symbol_child(&loctab,parent);    /* try local symbols first */
 14.2673 -  if (sym==NULL)                            /* not found */
 14.2674 -    sym=find_symbol_child(&glbtab,parent);
 14.2675 -  return sym;
 14.2676 -}
 14.2677 -
 14.2678 -/*  addsym
 14.2679 - *
 14.2680 - *  Adds a symbol to the symbol table (either global or local variables,
 14.2681 - *  or global and local constants).
 14.2682 - */
 14.2683 -SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,int usage)
 14.2684 -{
 14.2685 -  symbol entry, **refer;
 14.2686 -
 14.2687 -  /* labels may only be defined once */
 14.2688 -  assert(ident!=iLABEL || findloc(name)==NULL);
 14.2689 -
 14.2690 -  /* create an empty referrer list */
 14.2691 -  if ((refer=(symbol**)malloc(sizeof(symbol*)))==NULL) {
 14.2692 -    error(103);         /* insufficient memory */
 14.2693 -    return NULL;
 14.2694 -  } /* if */
 14.2695 -  *refer=NULL;
 14.2696 -
 14.2697 -  /* first fill in the entry */
 14.2698 -  memset(&entry,0,sizeof entry);
 14.2699 -  strcpy(entry.name,name);
 14.2700 -  entry.hash=namehash(name);
 14.2701 -  entry.addr=addr;
 14.2702 -  entry.codeaddr=code_idx;
 14.2703 -  entry.vclass=(char)vclass;
 14.2704 -  entry.ident=(char)ident;
 14.2705 -  entry.tag=tag;
 14.2706 -  entry.usage=(char)usage;
 14.2707 -  entry.fnumber=-1;     /* assume global visibility (ignored for local symbols) */
 14.2708 -  entry.lnumber=fline;
 14.2709 -  entry.numrefers=1;
 14.2710 -  entry.refer=refer;
 14.2711 -
 14.2712 -  /* then insert it in the list */
 14.2713 -  if (vclass==sGLOBAL)
 14.2714 -    return add_symbol(&glbtab,&entry,TRUE);
 14.2715 -  else
 14.2716 -    return add_symbol(&loctab,&entry,FALSE);
 14.2717 -}
 14.2718 -
 14.2719 -SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
 14.2720 -                            int dim[],int numdim,int idxtag[])
 14.2721 -{
 14.2722 -  symbol *sym;
 14.2723 -
 14.2724 -  /* global variables may only be defined once
 14.2725 -   * One complication is that functions returning arrays declare an array
 14.2726 -   * with the same name as the function, so the assertion must allow for
 14.2727 -   * this special case. Another complication is that variables may be
 14.2728 -   * "redeclared" if they are local to an automaton (and findglb() will find
 14.2729 -   * the symbol without states if no symbol with states exists).
 14.2730 -   */
 14.2731 -  assert(vclass!=sGLOBAL || (sym=findglb(name,sGLOBAL))==NULL || (sym->usage & uDEFINE)==0
 14.2732 -         || sym->ident==iFUNCTN && sym==curfunc
 14.2733 -         || sym->states==NULL && sc_curstates>0);
 14.2734 -
 14.2735 -  if (ident==iARRAY || ident==iREFARRAY) {
 14.2736 -    symbol *parent=NULL,*top;
 14.2737 -    int level;
 14.2738 -    sym=NULL;                   /* to avoid a compiler warning */
 14.2739 -    for (level=0; level<numdim; level++) {
 14.2740 -      top=addsym(name,addr,ident,vclass,tag,uDEFINE);
 14.2741 -      top->dim.array.length=dim[level];
 14.2742 -      top->dim.array.level=(short)(numdim-level-1);
 14.2743 -      top->x.tags.index=idxtag[level];
 14.2744 -      top->parent=parent;
 14.2745 -      parent=top;
 14.2746 -      if (level==0)
 14.2747 -        sym=top;
 14.2748 -    } /* for */
 14.2749 -  } else {
 14.2750 -    sym=addsym(name,addr,ident,vclass,tag,uDEFINE);
 14.2751 -  } /* if */
 14.2752 -  return sym;
 14.2753 -}
 14.2754 -
 14.2755 -/*  getlabel
 14.2756 - *
 14.2757 - *  Returns te next internal label number. The global variable sc_labnum is
 14.2758 - *  initialized to zero.
 14.2759 - */
 14.2760 -SC_FUNC int getlabel(void)
 14.2761 -{
 14.2762 -  return sc_labnum++;
 14.2763 -}
 14.2764 -
 14.2765 -/*  itoh
 14.2766 - *
 14.2767 - *  Converts a number to a hexadecimal string and returns a pointer to that
 14.2768 - *  string. This function is NOT re-entrant.
 14.2769 - */
 14.2770 -SC_FUNC char *itoh(ucell val)
 14.2771 -{
 14.2772 -static char itohstr[30];
 14.2773 -  char *ptr;
 14.2774 -  int i,nibble[16];             /* a 64-bit hexadecimal cell has 16 nibbles */
 14.2775 -  int max;
 14.2776 -
 14.2777 -  #if PAWN_CELL_SIZE==16
 14.2778 -    max=4;
 14.2779 -  #elif PAWN_CELL_SIZE==32
 14.2780 -    max=8;
 14.2781 -  #elif PAWN_CELL_SIZE==64
 14.2782 -    max=16;
 14.2783 -  #else
 14.2784 -    #error Unsupported cell size
 14.2785 -  #endif
 14.2786 -  ptr=itohstr;
 14.2787 -  for (i=0; i<max; i+=1){
 14.2788 -    nibble[i]=(int)(val & 0x0f);        /* nibble 0 is lowest nibble */
 14.2789 -    val>>=4;
 14.2790 -  } /* endfor */
 14.2791 -  i=max-1;
 14.2792 -  while (nibble[i]==0 && i>0)   /* search for highest non-zero nibble */
 14.2793 -    i-=1;
 14.2794 -  while (i>=0){
 14.2795 -    if (nibble[i]>=10)
 14.2796 -      *ptr++=(char)('a'+(nibble[i]-10));
 14.2797 -    else
 14.2798 -      *ptr++=(char)('0'+nibble[i]);
 14.2799 -    i-=1;
 14.2800 -  } /* while */
 14.2801 -  *ptr='\0';            /* and a zero-terminator */
 14.2802 -  return itohstr;
 14.2803 -}
 14.2804 -
    15.1 --- a/compiler-init/sc3.c	Sat Jul 15 01:36:48 2006 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,2453 +0,0 @@
    15.4 -/*  Pawn compiler - Recursive descend expresion parser
    15.5 - *
    15.6 - *  Copyright (c) ITB CompuPhase, 1997-2005
    15.7 - *
    15.8 - *  This software is provided "as-is", without any express or implied warranty.
    15.9 - *  In no event will the authors be held liable for any damages arising from
   15.10 - *  the use of this software.
   15.11 - *
   15.12 - *  Permission is granted to anyone to use this software for any purpose,
   15.13 - *  including commercial applications, and to alter it and redistribute it
   15.14 - *  freely, subject to the following restrictions:
   15.15 - *
   15.16 - *  1.  The origin of this software must not be misrepresented; you must not
   15.17 - *      claim that you wrote the original software. If you use this software in
   15.18 - *      a product, an acknowledgment in the product documentation would be
   15.19 - *      appreciated but is not required.
   15.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
   15.21 - *      misrepresented as being the original software.
   15.22 - *  3.  This notice may not be removed or altered from any source distribution.
   15.23 - *
   15.24 - *  Version: $Id: sc3.c 3598 2006-07-04 13:44:04Z thiadmer $
   15.25 - */
   15.26 -#include <assert.h>
   15.27 -#include <stdio.h>
   15.28 -#include <stdlib.h>     /* for _MAX_PATH */
   15.29 -#include <string.h>
   15.30 -#if defined FORTIFY
   15.31 -  #include <alloc/fortify.h>
   15.32 -#endif
   15.33 -#include "sc.h"
   15.34 -
   15.35 -static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
   15.36 -                int (*hier)(value*),value *lval);
   15.37 -static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval);
   15.38 -static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
   15.39 -                 char *forcetag,int chkbitwise);
   15.40 -static int plnge1(int (*hier)(value *lval),value *lval);
   15.41 -static void plnge2(void (*oper)(void),
   15.42 -                   int (*hier)(value *lval),
   15.43 -                   value *lval1,value *lval2);
   15.44 -static cell calc(cell left,void (*oper)(),cell right,char *boolresult);
   15.45 -static int hier14(value *lval);
   15.46 -static int hier13(value *lval);
   15.47 -static int hier12(value *lval);
   15.48 -static int hier11(value *lval);
   15.49 -static int hier10(value *lval);
   15.50 -static int hier9(value *lval);
   15.51 -static int hier8(value *lval);
   15.52 -static int hier7(value *lval);
   15.53 -static int hier6(value *lval);
   15.54 -static int hier5(value *lval);
   15.55 -static int hier4(value *lval);
   15.56 -static int hier3(value *lval);
   15.57 -static int hier2(value *lval);
   15.58 -static int hier1(value *lval1);
   15.59 -static int primary(value *lval);
   15.60 -static void clear_value(value *lval);
   15.61 -static void callfunction(symbol *sym,value *lval_result,int matchparanthesis);
   15.62 -static int dbltest(void (*oper)(),value *lval1,value *lval2);
   15.63 -static int commutative(void (*oper)());
   15.64 -static int constant(value *lval);
   15.65 -
   15.66 -static char lastsymbol[sNAMEMAX+1]; /* name of last function/variable */
   15.67 -static int bitwise_opercount;   /* count of bitwise operators in an expression */
   15.68 -static int decl_heap=0;
   15.69 -
   15.70 -/* Function addresses of binary operators for signed operations */
   15.71 -static void (*op1[17])(void) = {
   15.72 -  os_mult,os_div,os_mod,        /* hier3, index 0 */
   15.73 -  ob_add,ob_sub,                /* hier4, index 3 */
   15.74 -  ob_sal,os_sar,ou_sar,         /* hier5, index 5 */
   15.75 -  ob_and,                       /* hier6, index 8 */
   15.76 -  ob_xor,                       /* hier7, index 9 */
   15.77 -  ob_or,                        /* hier8, index 10 */
   15.78 -  os_le,os_ge,os_lt,os_gt,      /* hier9, index 11 */
   15.79 -  ob_eq,ob_ne,                  /* hier10, index 15 */
   15.80 -};
   15.81 -/* These two functions are defined because the functions inc() and dec() in
   15.82 - * SC4.C have a different prototype than the other code generation functions.
   15.83 - * The arrays for user-defined functions use the function pointers for
   15.84 - * identifying what kind of operation is requested; these functions must all
   15.85 - * have the same prototype. As inc() and dec() are special cases already, it
   15.86 - * is simplest to add two "do-nothing" functions.
   15.87 - */
   15.88 -static void user_inc(void) {}
   15.89 -static void user_dec(void) {}
   15.90 -
   15.91 -/*
   15.92 - *  Searches for a binary operator a list of operators. The list is stored in
   15.93 - *  the array "list". The last entry in the list should be set to 0.
   15.94 - *
   15.95 - *  The index of an operator in "list" (if found) is returned in "opidx". If
   15.96 - *  no operator is found, nextop() returns 0.
   15.97 - *
   15.98 - *  If an operator is found in the expression, it cannot be used in a function
   15.99 - *  call with omitted parantheses. Mark this...
  15.100 - *
  15.101 - *  Global references: sc_allowproccall   (modified)
  15.102 - */
  15.103 -static int nextop(int *opidx,int *list)
  15.104 -{
  15.105 -  *opidx=0;
  15.106 -  while (*list){
  15.107 -    if (matchtoken(*list)){
  15.108 -      sc_allowproccall=FALSE;
  15.109 -      return TRUE;      /* found! */
  15.110 -    } else {
  15.111 -      list+=1;
  15.112 -      *opidx+=1;
  15.113 -    } /* if */
  15.114 -  } /* while */
  15.115 -  return FALSE;         /* entire list scanned, nothing found */
  15.116 -}
  15.117 -
  15.118 -SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
  15.119 -                         value *lval,int *resulttag)
  15.120 -{
  15.121 -static char *binoperstr[] = { "*", "/", "%", "+", "-", "", "", "",
  15.122 -                              "", "", "", "<=", ">=", "<", ">", "==", "!=" };
  15.123 -static int binoper_savepri[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  15.124 -                                 FALSE, FALSE, FALSE, FALSE, FALSE,
  15.125 -                                 TRUE, TRUE, TRUE, TRUE, FALSE, FALSE };
  15.126 -static char *unoperstr[] = { "!", "-", "++", "--" };
  15.127 -static void (*unopers[])(void) = { lneg, neg, user_inc, user_dec };
  15.128 -  char opername[4] = "", symbolname[sNAMEMAX+1];
  15.129 -  int i,swapparams,savepri,savealt;
  15.130 -  int paramspassed;
  15.131 -  symbol *sym;
  15.132 -
  15.133 -  /* since user-defined operators on untagged operands are forbidden, we have
  15.134 -   * a quick exit.
  15.135 -   */
  15.136 -  assert(numparam==1 || numparam==2);
  15.137 -  if (tag1==0 && (numparam==1 || tag2==0))
  15.138 -    return FALSE;
  15.139 -
  15.140 -  savepri=savealt=FALSE;
  15.141 -  /* find the name with the operator */
  15.142 -  if (numparam==2) {
  15.143 -    if (oper==NULL) {
  15.144 -      /* assignment operator: a special case */
  15.145 -      strcpy(opername,"=");
  15.146 -      if (lval!=NULL && (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR))
  15.147 -        savealt=TRUE;
  15.148 -    } else {
  15.149 -      assert( (sizeof binoperstr / sizeof binoperstr[0]) == (sizeof op1 / sizeof op1[0]) );
  15.150 -      for (i=0; i<sizeof op1 / sizeof op1[0]; i++) {
  15.151 -        if (oper==op1[i]) {
  15.152 -          strcpy(opername,binoperstr[i]);
  15.153 -          savepri=binoper_savepri[i];
  15.154 -          break;
  15.155 -        } /* if */
  15.156 -      } /* for */
  15.157 -    } /* if */
  15.158 -  } else {
  15.159 -    assert(oper!=NULL);
  15.160 -    assert(numparam==1);
  15.161 -    /* try a select group of unary operators */
  15.162 -    assert( (sizeof unoperstr / sizeof unoperstr[0]) == (sizeof unopers / sizeof unopers[0]) );
  15.163 -    if (opername[0]=='\0') {
  15.164 -      for (i=0; i<sizeof unopers / sizeof unopers[0]; i++) {
  15.165 -        if (oper==unopers[i]) {
  15.166 -          strcpy(opername,unoperstr[i]);
  15.167 -          break;
  15.168 -        } /* if */
  15.169 -      } /* for */
  15.170 -    } /* if */
  15.171 -  } /* if */
  15.172 -  /* if not found, quit */
  15.173 -  if (opername[0]=='\0')
  15.174 -    return FALSE;
  15.175 -
  15.176 -  /* create a symbol name from the tags and the operator name */
  15.177 -  assert(numparam==1 || numparam==2);
  15.178 -  operator_symname(symbolname,opername,tag1,tag2,numparam,tag2);
  15.179 -  swapparams=FALSE;
  15.180 -  sym=findglb(symbolname,sGLOBAL);
  15.181 -  if (sym==NULL /*|| (sym->usage & uDEFINE)==0*/) {  /* ??? should not check uDEFINE; first pass clears these bits */
  15.182 -    /* check for commutative operators */
  15.183 -    if (tag1==tag2 || oper==NULL || !commutative(oper))
  15.184 -      return FALSE;             /* not commutative, cannot swap operands */
  15.185 -    /* if arrived here, the operator is commutative and the tags are different,
  15.186 -     * swap tags and try again
  15.187 -     */
  15.188 -    assert(numparam==2);        /* commutative operator must be a binary operator */
  15.189 -    operator_symname(symbolname,opername,tag2,tag1,numparam,tag1);
  15.190 -    swapparams=TRUE;
  15.191 -    sym=findglb(symbolname,sGLOBAL);
  15.192 -    if (sym==NULL /*|| (sym->usage & uDEFINE)==0*/)
  15.193 -      return FALSE;
  15.194 -  } /* if */
  15.195 -
  15.196 -  /* check existance and the proper declaration of this function */
  15.197 -  if ((sym->usage & uMISSING)!=0 || (sym->usage & uPROTOTYPED)==0) {
  15.198 -    char symname[2*sNAMEMAX+16];  /* allow space for user defined operators */
  15.199 -    funcdisplayname(symname,sym->name);
  15.200 -    if ((sym->usage & uMISSING)!=0)
  15.201 -      error(4,symname);           /* function not defined */
  15.202 -    if ((sym->usage & uPROTOTYPED)==0)
  15.203 -      error(71,symname);          /* operator must be declared before use */
  15.204 -  } /* if */
  15.205 -
  15.206 -  /* we don't want to use the redefined operator in the function that
  15.207 -   * redefines the operator itself, otherwise the snippet below gives
  15.208 -   * an unexpected recursion:
  15.209 -   *    fixed:operator+(fixed:a, fixed:b)
  15.210 -   *        return a + b
  15.211 -   */
  15.212 -  if (sym==curfunc)
  15.213 -    return FALSE;
  15.214 -
  15.215 -  /* for increment and decrement operators, the symbol must first be loaded
  15.216 -   * (and stored back afterwards)
  15.217 -   */
  15.218 -  if (oper==user_inc || oper==user_dec) {
  15.219 -    assert(!savepri);
  15.220 -    assert(lval!=NULL);
  15.221 -    if (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR)
  15.222 -      pushreg(sPRI);            /* save current address in PRI */
  15.223 -    rvalue(lval);               /* get the symbol's value in PRI */
  15.224 -  } /* if */
  15.225 -
  15.226 -  assert(!savepri || !savealt); /* either one MAY be set, but not both */
  15.227 -  if (savepri) {
  15.228 -    /* the chained comparison operators require that the ALT register is
  15.229 -     * unmodified, so we save it here; actually, we save PRI because the normal
  15.230 -     * instruction sequence (without user operator) swaps PRI and ALT
  15.231 -     */
  15.232 -    pushreg(sPRI);              /* right-hand operand is in PRI */
  15.233 -  } else if (savealt) {
  15.234 -    /* for the assignment operator, ALT may contain an address at which the
  15.235 -     * result must be stored; this address must be preserved accross the
  15.236 -     * call
  15.237 -     */
  15.238 -    assert(lval!=NULL);         /* this was checked earlier */
  15.239 -    assert(lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR); /* checked earlier */
  15.240 -    pushreg(sALT);
  15.241 -  } /* if */
  15.242 -
  15.243 -  /* push parameters, call the function */
  15.244 -  paramspassed= (oper==NULL) ? 1 : numparam;
  15.245 -  switch (paramspassed) {
  15.246 -  case 1:
  15.247 -    pushreg(sPRI);
  15.248 -    break;
  15.249 -  case 2:
  15.250 -    /* note that 1) a function expects that the parameters are pushed
  15.251 -     * in reversed order, and 2) the left operand is in the secondary register
  15.252 -     * and the right operand is in the primary register */
  15.253 -    if (swapparams) {
  15.254 -      pushreg(sALT);
  15.255 -      pushreg(sPRI);
  15.256 -    } else {
  15.257 -      pushreg(sPRI);
  15.258 -      pushreg(sALT);
  15.259 -    } /* if */
  15.260 -    break;
  15.261 -  default:
  15.262 -    assert(0);
  15.263 -  } /* switch */
  15.264 -  markexpr(sPARM,NULL,0);       /* mark the end of a sub-expression */
  15.265 -  pushval((cell)paramspassed*sizeof(cell));
  15.266 -  assert(sym->ident==iFUNCTN);
  15.267 -  ffcall(sym,NULL,paramspassed);
  15.268 -  if (sc_status!=statSKIP)
  15.269 -    markusage(sym,uREAD);       /* do not mark as "used" when this call itself is skipped */
  15.270 -  if ((sym->usage & uNATIVE)!=0 && sym->x.lib!=NULL)
  15.271 -    sym->x.lib->value += 1;     /* increment "usage count" of the library */
  15.272 -  sideeffect=TRUE;              /* assume functions carry out a side-effect */
  15.273 -  assert(resulttag!=NULL);
  15.274 -  *resulttag=sym->tag;          /* save tag of the called function */
  15.275 -
  15.276 -  if (savepri || savealt)
  15.277 -    popreg(sALT);               /* restore the saved PRI/ALT that into ALT */
  15.278 -  if (oper==user_inc || oper==user_dec) {
  15.279 -    assert(lval!=NULL);
  15.280 -    if (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR)
  15.281 -      popreg(sALT);             /* restore address (in ALT) */
  15.282 -    store(lval);                /* store PRI in the symbol */
  15.283 -    moveto1();                  /* make sure PRI is restored on exit */
  15.284 -  } /* if */
  15.285 -  return TRUE;
  15.286 -}
  15.287 -
  15.288 -SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
  15.289 -{
  15.290 -  if (formaltag!=actualtag) {
  15.291 -    /* if the formal tag is zero and the actual tag is not "fixed", the actual
  15.292 -     * tag is "coerced" to zero
  15.293 -     */
  15.294 -    if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0)
  15.295 -      return FALSE;
  15.296 -  } /* if */
  15.297 -  return TRUE;
  15.298 -}
  15.299 -
  15.300 -/*
  15.301 - *  The AMX pseudo-processor has no direct support for logical (boolean)
  15.302 - *  operations. These have to be done via comparing and jumping. Since we are
  15.303 - *  already jumping through the code, we might as well implement an "early
  15.304 - *  drop-out" evaluation (also called "short-circuit"). This conforms to
  15.305 - *  standard C:
  15.306 - *
  15.307 - *  expr1 || expr2           expr2 will only be evaluated if expr1 is false.
  15.308 - *  expr1 && expr2           expr2 will only be evaluated if expr1 is true.
  15.309 - *
  15.310 - *  expr1 || expr2 && expr3  expr2 will only be evaluated if expr1 is false
  15.311 - *                           and expr3 will only be evaluated if expr1 is
  15.312 - *                           false and expr2 is true.
  15.313 - *
  15.314 - *  Code generation for the last example proceeds thus:
  15.315 - *
  15.316 - *      evaluate expr1
  15.317 - *      operator || found
  15.318 - *      jump to "l1" if result of expr1 not equal to 0
  15.319 - *      evaluate expr2
  15.320 - *      ->  operator && found; skip to higher level in hierarchy diagram
  15.321 - *          jump to "l2" if result of expr2 equal to 0
  15.322 - *          evaluate expr3
  15.323 - *          jump to "l2" if result of expr3 equal to 0
  15.324 - *          set expression result to 1 (true)
  15.325 - *          jump to "l3"
  15.326 - *      l2: set expression result to 0 (false)
  15.327 - *      l3:
  15.328 - *      <-  drop back to previous hierarchy level
  15.329 - *      jump to "l1" if result of expr2 && expr3 not equal to 0
  15.330 - *      set expression result to 0 (false)
  15.331 - *      jump to "l4"
  15.332 - *  l1: set expression result to 1 (true)
  15.333 - *  l4:
  15.334 - *
  15.335 - */
  15.336 -
  15.337 -/*  Skim over terms adjoining || and && operators
  15.338 - *  dropval   The value of the expression after "dropping out". An "or" drops
  15.339 - *            out when the left hand is TRUE, so dropval must be 1 on "or"
  15.340 - *            expressions.
  15.341 - *  endval    The value of the expression when no expression drops out. In an
  15.342 - *            "or" expression, this happens when both the left hand and the
  15.343 - *            right hand are FALSE, so endval must be 0 for "or" expressions.
  15.344 - */
  15.345 -static int skim(int *opstr,void (*testfunc)(int),int dropval,int endval,
  15.346 -                int (*hier)(value*),value *lval)
  15.347 -{
  15.348 -  int lvalue,hits,droplab,endlab,opidx;
  15.349 -  int allconst,foundop;
  15.350 -  cell constval;
  15.351 -  int index;
  15.352 -  cell cidx;
  15.353 -
  15.354 -  stgget(&index,&cidx);         /* mark position in code generator */
  15.355 -  hits=FALSE;                   /* no logical operators "hit" yet */
  15.356 -  allconst=TRUE;                /* assume all values "const" */
  15.357 -  constval=0;
  15.358 -  droplab=0;                    /* to avoid a compiler warning */
  15.359 -  for ( ;; ) {
  15.360 -    lvalue=plnge1(hier,lval);   /* evaluate left expression */
  15.361 -
  15.362 -    allconst= allconst && (lval->ident==iCONSTEXPR);
  15.363 -    if (allconst) {
  15.364 -      if (hits) {
  15.365 -        /* one operator was already found */
  15.366 -        if (testfunc==jmp_ne0)
  15.367 -          lval->constval= lval->constval || constval;
  15.368 -        else
  15.369 -          lval->constval= lval->constval && constval;
  15.370 -      } /* if */
  15.371 -      constval=lval->constval;  /* save result accumulated so far */
  15.372 -    } /* if */
  15.373 -
  15.374 -    foundop=nextop(&opidx,opstr);
  15.375 -    if ((foundop || hits) && (lval->ident==iARRAY || lval->ident==iREFARRAY))
  15.376 -      error(33, lval->sym ? (lval->sym->name ? lval->sym->name : "-unknown") : "-unknown-");  /* array was not indexed in an expression */
  15.377 -    if (foundop) {
  15.378 -      if (!hits) {
  15.379 -        /* this is the first operator in the list */
  15.380 -        hits=TRUE;
  15.381 -        droplab=getlabel();
  15.382 -      } /* if */
  15.383 -      dropout(lvalue,testfunc,droplab,lval);
  15.384 -    } else if (hits) {                       /* no (more) identical operators */
  15.385 -      dropout(lvalue,testfunc,droplab,lval); /* found at least one operator! */
  15.386 -      ldconst(endval,sPRI);
  15.387 -      jumplabel(endlab=getlabel());
  15.388 -      setlabel(droplab);
  15.389 -      ldconst(dropval,sPRI);
  15.390 -      setlabel(endlab);
  15.391 -      lval->sym=NULL;
  15.392 -      lval->tag=pc_addtag("bool");  /* force tag to be "bool" */
  15.393 -      if (allconst) {
  15.394 -        lval->ident=iCONSTEXPR;
  15.395 -        lval->constval=constval;
  15.396 -        stgdel(index,cidx);         /* scratch generated code and calculate */
  15.397 -      } else {
  15.398 -        lval->ident=iEXPRESSION;
  15.399 -        lval->constval=0;
  15.400 -      } /* if */
  15.401 -      return FALSE;
  15.402 -    } else {
  15.403 -      return lvalue;            /* none of the operators in "opstr" were found */
  15.404 -    } /* if */
  15.405 -
  15.406 -  } /* while */
  15.407 -}
  15.408 -
  15.409 -/*
  15.410 - *  Reads into the primary register the variable pointed to by lval if
  15.411 - *  plunging through the hierarchy levels detected an lvalue. Otherwise
  15.412 - *  if a constant was detected, it is loaded. If there is no constant and
  15.413 - *  no lvalue, the primary register must already contain the expression
  15.414 - *  result.
  15.415 - *
  15.416 - *  After that, the compare routines "jmp_ne0" or "jmp_eq0" are called, which
  15.417 - *  compare the primary register against 0, and jump to the "early drop-out"
  15.418 - *  label "exit1" if the condition is true.
  15.419 - */
  15.420 -static void dropout(int lvalue,void (*testfunc)(int val),int exit1,value *lval)
  15.421 -{
  15.422 -  if (lvalue)
  15.423 -    rvalue(lval);
  15.424 -  else if (lval->ident==iCONSTEXPR)
  15.425 -    ldconst(lval->constval,sPRI);
  15.426 -  (*testfunc)(exit1);
  15.427 -}
  15.428 -
  15.429 -static void checkfunction(value *lval)
  15.430 -{
  15.431 -  symbol *sym=lval->sym;
  15.432 -
  15.433 -  if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
  15.434 -    return;             /* no known symbol, or not a function result */
  15.435 -
  15.436 -  if ((sym->usage & uDEFINE)!=0) {
  15.437 -    /* function is defined, can now check the return value (but make an
  15.438 -     * exception for directly recursive functions)
  15.439 -     */
  15.440 -    if (sym!=curfunc && (sym->usage & uRETVALUE)==0) {
  15.441 -      char symname[2*sNAMEMAX+16];  /* allow space for user defined operators */
  15.442 -      funcdisplayname(symname,sym->name);
  15.443 -      error(209,symname);       /* function should return a value */
  15.444 -    } /* if */
  15.445 -  } else {
  15.446 -    /* function not yet defined, set */
  15.447 -    sym->usage|=uRETVALUE;      /* make sure that a future implementation of
  15.448 -                                 * the function uses "return <value>" */
  15.449 -  } /* if */
  15.450 -}
  15.451 -
  15.452 -/*
  15.453 - *  Plunge to a lower level
  15.454 - */
  15.455 -static int plnge(int *opstr,int opoff,int (*hier)(value *lval),value *lval,
  15.456 -                 char *forcetag,int chkbitwise)
  15.457 -{
  15.458 -  int lvalue,opidx;
  15.459 -  int count;
  15.460 -  value lval2 = {0};
  15.461 -
  15.462 -  lvalue=plnge1(hier,lval);
  15.463 -  if (nextop(&opidx,opstr)==0)
  15.464 -    return lvalue;              /* no operator in "opstr" found */
  15.465 -  if (lvalue)
  15.466 -    rvalue(lval);
  15.467 -  count=0;
  15.468 -  do {
  15.469 -    if (chkbitwise && count++>0 && bitwise_opercount!=0)
  15.470 -      error(212);
  15.471 -    opidx+=opoff;               /* add offset to index returned by nextop() */
  15.472 -    plnge2(op1[opidx],hier,lval,&lval2);
  15.473 -    if (op1[opidx]==ob_and || op1[opidx]==ob_or)
  15.474 -      bitwise_opercount++;
  15.475 -    if (forcetag!=NULL)
  15.476 -      lval->tag=pc_addtag(forcetag);
  15.477 -  } while (nextop(&opidx,opstr)); /* do */
  15.478 -  return FALSE;         /* result of expression is not an lvalue */
  15.479 -}
  15.480 -
  15.481 -/*  plnge_rel
  15.482 - *
  15.483 - *  Binary plunge to lower level; this is very simular to plnge, but
  15.484 - *  it has special code generation sequences for chained operations.
  15.485 - */
  15.486 -static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval)
  15.487 -{
  15.488 -  int lvalue,opidx;
  15.489 -  value lval2={0};
  15.490 -  int count;
  15.491 -
  15.492 -  /* this function should only be called for relational operators */
  15.493 -  assert(op1[opoff]==os_le);
  15.494 -  lvalue=plnge1(hier,lval);
  15.495 -  if (nextop(&opidx,opstr)==0)
  15.496 -    return lvalue;              /* no operator in "opstr" found */
  15.497 -  if (lvalue)
  15.498 -    rvalue(lval);
  15.499 -  count=0;
  15.500 -  lval->boolresult=TRUE;
  15.501 -  do {
  15.502 -    /* same check as in plnge(), but "chkbitwise" is always TRUE */
  15.503 -    if (count>0 && bitwise_opercount!=0)
  15.504 -      error(212);
  15.505 -    if (count>0) {
  15.506 -      relop_prefix();
  15.507 -      *lval=lval2;      /* copy right hand expression of the previous iteration */
  15.508 -    } /* if */
  15.509 -    opidx+=opoff;
  15.510 -    plnge2(op1[opidx],hier,lval,&lval2);
  15.511 -    if (count++>0)
  15.512 -      relop_suffix();
  15.513 -  } while (nextop(&opidx,opstr)); /* enddo */
  15.514 -  lval->constval=lval->boolresult;
  15.515 -  lval->tag=pc_addtag("bool");    /* force tag to be "bool" */
  15.516 -  return FALSE;         /* result of expression is not an lvalue */
  15.517 -}
  15.518 -
  15.519 -/*  plnge1
  15.520 - *
  15.521 - *  Unary plunge to lower level
  15.522 - *  Called by: skim(), plnge(), plnge2(), plnge_rel(), hier14() and hier13()
  15.523 - */
  15.524 -static int plnge1(int (*hier)(value *lval),value *lval)
  15.525 -{
  15.526 -  int lvalue,index;
  15.527 -  cell cidx;
  15.528 -
  15.529 -  stgget(&index,&cidx); /* mark position in code generator */
  15.530 -  lvalue=(*hier)(lval);
  15.531 -  if (lval->ident==iCONSTEXPR)
  15.532 -    stgdel(index,cidx); /* load constant later */
  15.533 -  return lvalue;
  15.534 -}
  15.535 -
  15.536 -/*  plnge2
  15.537 - *
  15.538 - *  Binary plunge to lower level
  15.539 - *  Called by: plnge(), plnge_rel(), hier14() and hier1()
  15.540 - */
  15.541 -static void plnge2(void (*oper)(void),
  15.542 -                   int (*hier)(value *lval),
  15.543 -                   value *lval1,value *lval2)
  15.544 -{
  15.545 -  int index;
  15.546 -  cell cidx;
  15.547 -
  15.548 -  stgget(&index,&cidx);             /* mark position in code generator */
  15.549 -  if (lval1->ident==iCONSTEXPR) {   /* constant on left side; it is not yet loaded */
  15.550 -    if (plnge1(hier,lval2))
  15.551 -      rvalue(lval2);                /* load lvalue now */
  15.552 -    else if (lval2->ident==iCONSTEXPR)
  15.553 -      ldconst(lval2->constval<<dbltest(oper,lval2,lval1),sPRI);
  15.554 -    ldconst(lval1->constval<<dbltest(oper,lval2,lval1),sALT);
  15.555 -                   /* ^ doubling of constants operating on integer addresses */
  15.556 -                   /*   is restricted to "add" and "subtract" operators */
  15.557 -  } else {                          /* non-constant on left side */
  15.558 -    pushreg(sPRI);
  15.559 -    if (plnge1(hier,lval2))
  15.560 -      rvalue(lval2);
  15.561 -    if (lval2->ident==iCONSTEXPR) { /* constant on right side */
  15.562 -      if (commutative(oper)) {      /* test for commutative operators */
  15.563 -        value lvaltmp = {0};
  15.564 -        stgdel(index,cidx);         /* scratch pushreg() and constant fetch (then
  15.565 -                                     * fetch the constant again */
  15.566 -        ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sALT);
  15.567 -        /* now, the primary register has the left operand and the secondary
  15.568 -         * register the right operand; swap the "lval" variables so that lval1
  15.569 -         * is associated with the secondary register and lval2 with the
  15.570 -         * primary register, as is the "normal" case.
  15.571 -         */
  15.572 -        lvaltmp=*lval1;
  15.573 -        *lval1=*lval2;
  15.574 -        *lval2=lvaltmp;
  15.575 -      } else {
  15.576 -        ldconst(lval2->constval<<dbltest(oper,lval1,lval2),sPRI);
  15.577 -        popreg(sALT);   /* pop result of left operand into secondary register */
  15.578 -      } /* if */
  15.579 -    } else {            /* non-constants on both sides */
  15.580 -      popreg(sALT);
  15.581 -      if (dbltest(oper,lval1,lval2))
  15.582 -        cell2addr();                    /* double primary register */
  15.583 -      if (dbltest(oper,lval2,lval1))
  15.584 -        cell2addr_alt();                /* double secondary register */
  15.585 -    } /* if */
  15.586 -  } /* if */
  15.587 -  if (oper) {
  15.588 -    /* If used in an expression, a function should return a value.
  15.589 -     * If the function has been defined, we can check this. If the
  15.590 -     * function was not defined, we can set this requirement (so that
  15.591 -     * a future function definition can check this bit.
  15.592 -     */
  15.593 -    checkfunction(lval1);
  15.594 -    checkfunction(lval2);
  15.595 -    if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
  15.596 -      char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
  15.597 -      error(33,ptr);                    /* array must be indexed */
  15.598 -    } else if (lval2->ident==iARRAY || lval2->ident==iREFARRAY) {
  15.599 -      char *ptr=(lval2->sym!=NULL) ? lval2->sym->name : "-unknown-";
  15.600 -      error(33,ptr);                    /* array must be indexed */
  15.601 -    } /* if */
  15.602 -    /* ??? ^^^ should do same kind of error checking with functions */
  15.603 -
  15.604 -    /* check whether an "operator" function is defined for the tag names
  15.605 -     * (a constant expression cannot be optimized in that case)
  15.606 -     */
  15.607 -    if (check_userop(oper,lval1->tag,lval2->tag,2,NULL,&lval1->tag)) {
  15.608 -      lval1->ident=iEXPRESSION;
  15.609 -      lval1->constval=0;
  15.610 -    } else if (lval1->ident==iCONSTEXPR && lval2->ident==iCONSTEXPR) {
  15.611 -      /* only constant expression if both constant */
  15.612 -      stgdel(index,cidx);       /* scratch generated code and calculate */
  15.613 -      if (!matchtag(lval1->tag,lval2->tag,FALSE))
  15.614 -        error(213);             /* tagname mismatch */
  15.615 -      lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
  15.616 -    } else {
  15.617 -      if (!matchtag(lval1->tag,lval2->tag,FALSE))
  15.618 -        error(213);             /* tagname mismatch */
  15.619 -      (*oper)();                /* do the (signed) operation */
  15.620 -      lval1->ident=iEXPRESSION;
  15.621 -    } /* if */
  15.622 -  } /* if */
  15.623 -}
  15.624 -
  15.625 -static cell truemodulus(cell a,cell b)
  15.626 -{
  15.627 -  return (a % b + b) % b;
  15.628 -}
  15.629 -
  15.630 -static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
  15.631 -{
  15.632 -  if (oper==ob_or)
  15.633 -    return (left | right);
  15.634 -  else if (oper==ob_xor)
  15.635 -    return (left ^ right);
  15.636 -  else if (oper==ob_and)
  15.637 -    return (left & right);
  15.638 -  else if (oper==ob_eq)
  15.639 -    return (left == right);
  15.640 -  else if (oper==ob_ne)
  15.641 -    return (left != right);
  15.642 -  else if (oper==os_le)
  15.643 -    return *boolresult &= (char)(left <= right), right;
  15.644 -  else if (oper==os_ge)
  15.645 -    return *boolresult &= (char)(left >= right), right;
  15.646 -  else if (oper==os_lt)
  15.647 -    return *boolresult &= (char)(left < right), right;
  15.648 -  else if (oper==os_gt)
  15.649 -    return *boolresult &= (char)(left > right), right;
  15.650 -  else if (oper==os_sar)
  15.651 -    return (left >> (int)right);
  15.652 -  else if (oper==ou_sar)
  15.653 -    return ((ucell)left >> (ucell)right);
  15.654 -  else if (oper==ob_sal)
  15.655 -    return ((ucell)left << (int)right);
  15.656 -  else if (oper==ob_add)
  15.657 -    return (left + right);
  15.658 -  else if (oper==ob_sub)
  15.659 -    return (left - right);
  15.660 -  else if (oper==os_mult)
  15.661 -    return (left * right);
  15.662 -  else if (oper==os_div)
  15.663 -    return (left - truemodulus(left,right)) / right;
  15.664 -  else if (oper==os_mod)
  15.665 -    return truemodulus(left,right);
  15.666 -  else
  15.667 -    error(29);  /* invalid expression, assumed 0 (this should never occur) */
  15.668 -  return 0;
  15.669 -}
  15.670 -
  15.671 -SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult)
  15.672 -{
  15.673 -  int locheap=decl_heap;
  15.674 -  value lval={0};
  15.675 -
  15.676 -  if (hier14(&lval))
  15.677 -    rvalue(&lval);
  15.678 -  /* scrap any arrays left on the heap */
  15.679 -  assert(decl_heap>=locheap);
  15.680 -  modheap((locheap-decl_heap)*sizeof(cell));  /* remove heap space, so negative delta */
  15.681 -  decl_heap=locheap;
  15.682 -
  15.683 -  if (lval.ident==iCONSTEXPR && val!=NULL)    /* constant expression */
  15.684 -    *val=lval.constval;
  15.685 -  if (tag!=NULL)
  15.686 -    *tag=lval.tag;
  15.687 -  if (symptr!=NULL)
  15.688 -    *symptr=lval.sym;
  15.689 -  if (chkfuncresult)
  15.690 -    checkfunction(&lval);
  15.691 -  return lval.ident;
  15.692 -}
  15.693 -
  15.694 -SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state)
  15.695 -{
  15.696 -  char name[sNAMEMAX+1];
  15.697 -  cell val;
  15.698 -  char *str;
  15.699 -  int fsa,islabel;
  15.700 -
  15.701 -  assert(automaton!=NULL);
  15.702 -  assert(state!=NULL);
  15.703 -  if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
  15.704 -    return 0;
  15.705 -
  15.706 -  tokeninfo(&val,&str);
  15.707 -  assert(strlen(str)<sizeof name);
  15.708 -  strcpy(name,str);
  15.709 -  if (islabel || matchtoken(':')) {
  15.710 -    /* token is an automaton name, add the name and get a new token */
  15.711 -    *automaton=automaton_find(name);
  15.712 -    /* read in the state name before checking the automaton, to keep the parser
  15.713 -     * going (an "unknown automaton" error may occur when the "state" instruction
  15.714 -     * precedes any state definition)
  15.715 -     */
  15.716 -    if (!needtoken(tSYMBOL))
  15.717 -      return 0;
  15.718 -    tokeninfo(&val,&str);        /* do not copy the name yet, must check automaton first */
  15.719 -    if (*automaton==NULL) {
  15.720 -      error(86,name);            /* unknown automaton */
  15.721 -      return 0;
  15.722 -    } /* if */
  15.723 -    assert((*automaton)->index>0);
  15.724 -    assert(strlen(str)<sizeof name);
  15.725 -    strcpy(name,str);
  15.726 -  } else {
  15.727 -    *automaton=automaton_find("");
  15.728 -    assert(*automaton!=NULL);
  15.729 -    assert((*automaton)->index==0);
  15.730 -  } /* if */
  15.731 -  assert(*automaton!=NULL);
  15.732 -  fsa=(*automaton)->index;
  15.733 -
  15.734 -  assert(*automaton!=NULL);
  15.735 -  *state=state_find(name,fsa);
  15.736 -  if (*state==NULL) {
  15.737 -    char *fsaname=(*automaton)->name;
  15.738 -    if (*fsaname=='\0')
  15.739 -      fsaname="<main>";
  15.740 -    error(87,name,fsaname);   /* unknown state for automaton */
  15.741 -    return 0;
  15.742 -  } /* if */
  15.743 -
  15.744 -  return 1;
  15.745 -}
  15.746 -
  15.747 -SC_FUNC cell array_totalsize(symbol *sym)
  15.748 -{
  15.749 -  cell length;
  15.750 -
  15.751 -  assert(sym!=NULL);
  15.752 -  assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
  15.753 -  length=sym->dim.array.length;
  15.754 -  if (sym->dim.array.level > 0) {
  15.755 -    cell sublength=array_totalsize(finddepend(sym));
  15.756 -    if (sublength>0)
  15.757 -      length=length+length*sublength;
  15.758 -    else
  15.759 -      length=0;
  15.760 -  } /* if */
  15.761 -  return length;
  15.762 -}
  15.763 -
  15.764 -static cell array_levelsize(symbol *sym,int level)
  15.765 -{
  15.766 -  assert(sym!=NULL);
  15.767 -  assert(sym->ident==iARRAY || sym->ident==iREFARRAY);
  15.768 -  assert(level <= sym->dim.array.level);
  15.769 -  while (level-- > 0) {
  15.770 -    sym=finddepend(sym);
  15.771 -    assert(sym!=NULL);
  15.772 -  } /* if */
  15.773 -  return sym->dim.array.length;
  15.774 -}
  15.775 -
  15.776 -/*  hier14
  15.777 - *
  15.778 - *  Lowest hierarchy level (except for the , operator).
  15.779 - *
  15.780 - *  Global references: sc_intest        (reffered to only)
  15.781 - *                     sc_allowproccall (modified)
  15.782 - */
  15.783 -static int hier14(value *lval1)
  15.784 -{
  15.785 -  int lvalue;
  15.786 -  value lval2={0},lval3={0};
  15.787 -  void (*oper)(void);
  15.788 -  int tok,level,i;
  15.789 -  cell val;
  15.790 -  char *st;
  15.791 -  int bwcount,leftarray;
  15.792 -  cell arrayidx1[sDIMEN_MAX],arrayidx2[sDIMEN_MAX];  /* last used array indices */
  15.793 -  cell *org_arrayidx;
  15.794 -
  15.795 -  bwcount=bitwise_opercount;
  15.796 -  bitwise_opercount=0;
  15.797 -  /* initialize the index arrays with unlikely constant indices; note that
  15.798 -   * these indices will only be changed when the array is indexed with a
  15.799 -   * constant, and that negative array indices are invalid (so actually, any
  15.800 -   * negative value would do).
  15.801 -   */
  15.802 -  for (i=0; i<sDIMEN_MAX; i++)
  15.803 -    arrayidx1[i]=arrayidx2[i]=(cell)(-1L << (sizeof(cell)*8-1));
  15.804 -  org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
  15.805 -  if (lval1->arrayidx==NULL)
  15.806 -    lval1->arrayidx=arrayidx1;
  15.807 -  lvalue=plnge1(hier13,lval1);
  15.808 -  if (lval1->ident!=iARRAYCELL && lval1->ident!=iARRAYCHAR)
  15.809 -    lval1->arrayidx=NULL;
  15.810 -  if (lval1->ident==iCONSTEXPR) /* load constant here */
  15.811 -    ldconst(lval1->constval,sPRI);
  15.812 -  tok=lex(&val,&st);
  15.813 -  switch (tok) {
  15.814 -    case taOR:
  15.815 -      oper=ob_or;
  15.816 -      break;
  15.817 -    case taXOR:
  15.818 -      oper=ob_xor;
  15.819 -      break;
  15.820 -    case taAND:
  15.821 -      oper=ob_and;
  15.822 -      break;
  15.823 -    case taADD:
  15.824 -      oper=ob_add;
  15.825 -      break;
  15.826 -    case taSUB:
  15.827 -      oper=ob_sub;
  15.828 -      break;
  15.829 -    case taMULT:
  15.830 -      oper=os_mult;
  15.831 -      break;
  15.832 -    case taDIV:
  15.833 -      oper=os_div;
  15.834 -      break;
  15.835 -    case taMOD:
  15.836 -      oper=os_mod;
  15.837 -      break;
  15.838 -    case taSHRU:
  15.839 -      oper=ou_sar;
  15.840 -      break;
  15.841 -    case taSHR:
  15.842 -      oper=os_sar;
  15.843 -      break;
  15.844 -    case taSHL:
  15.845 -      oper=ob_sal;
  15.846 -      break;
  15.847 -    case '=':           /* simple assignment */
  15.848 -      oper=NULL;
  15.849 -      if (sc_intest)
  15.850 -        error(211);     /* possibly unintended assignment */
  15.851 -      break;
  15.852 -    default:
  15.853 -      lexpush();
  15.854 -      bitwise_opercount=bwcount;
  15.855 -      lval1->arrayidx=org_arrayidx; /* restore array index pointer */
  15.856 -      return lvalue;
  15.857 -  } /* switch */
  15.858 -
  15.859 -  /* if we get here, it was an assignment; first check a few special cases
  15.860 -   * and then the general */
  15.861 -  if (lval1->ident==iARRAYCHAR) {
  15.862 -    /* special case, assignment to packed character in a cell is permitted */
  15.863 -    lvalue=TRUE;
  15.864 -  } else if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
  15.865 -    /* array assignment is permitted too (with restrictions) */
  15.866 -    if (oper)
  15.867 -      return error(23); /* array assignment must be simple assigment */
  15.868 -    assert(lval1->sym!=NULL);
  15.869 -    if (array_totalsize(lval1->sym)==0)
  15.870 -      return error(46,lval1->sym->name);        /* unknown array size */
  15.871 -    lvalue=TRUE;
  15.872 -  } /* if */
  15.873 -
  15.874 -  /* operand on left side of assignment must be lvalue */
  15.875 -  if (!lvalue)
  15.876 -    return error(22);                   /* must be lvalue */
  15.877 -  /* may not change "constant" parameters */
  15.878 -  assert(lval1->sym!=NULL);
  15.879 -  if ((lval1->sym->usage & uCONST)!=0)
  15.880 -    return error(22);           /* assignment to const argument */
  15.881 -  sc_allowproccall=FALSE;       /* may no longer use "procedure call" syntax */
  15.882 -
  15.883 -  lval3=*lval1;         /* save symbol to enable storage of expresion result */
  15.884 -  lval1->arrayidx=org_arrayidx; /* restore array index pointer */
  15.885 -  if (lval1->ident==iARRAYCELL || lval1->ident==iARRAYCHAR
  15.886 -      || lval1->ident==iARRAY || lval1->ident==iREFARRAY)
  15.887 -  {
  15.888 -    /* if indirect fetch: save PRI (cell address) */
  15.889 -    if (oper) {
  15.890 -      pushreg(sPRI);
  15.891 -      rvalue(lval1);
  15.892 -    } /* if */
  15.893 -    lval2.arrayidx=arrayidx2;
  15.894 -    plnge2(oper,hier14,lval1,&lval2);
  15.895 -    if (lval2.ident!=iARRAYCELL && lval2.ident!=iARRAYCHAR)
  15.896 -      lval2.arrayidx=NULL;
  15.897 -    if (oper)
  15.898 -      popreg(sALT);
  15.899 -    if (!oper && lval3.arrayidx!=NULL && lval2.arrayidx!=NULL
  15.900 -        && lval3.ident==lval2.ident && lval3.sym==lval2.sym)
  15.901 -    {
  15.902 -      int same=TRUE;
  15.903 -      assert(lval2.arrayidx==arrayidx2);
  15.904 -      for (i=0; i<sDIMEN_MAX; i++)
  15.905 -        same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
  15.906 -        if (same)
  15.907 -          error(226,lval3.sym->name);   /* self-assignment */
  15.908 -    } /* if */
  15.909 -  } else {
  15.910 -    if (oper){
  15.911 -      rvalue(lval1);
  15.912 -      plnge2(oper,hier14,lval1,&lval2);
  15.913 -    } else {
  15.914 -      /* if direct fetch and simple assignment: no "push"
  15.915 -       * and "pop" needed -> call hier14() directly, */
  15.916 -      if (hier14(&lval2))
  15.917 -        rvalue(&lval2);         /* instead of plnge2(). */
  15.918 -      else if (lval2.ident==iVARIABLE)
  15.919 -        lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */
  15.920 -      checkfunction(&lval2);
  15.921 -      /* check whether lval2 and lval3 (old lval1) refer to the same variable */
  15.922 -      if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
  15.923 -        assert(lval3.sym!=NULL);
  15.924 -        error(226,lval3.sym->name);     /* self-assignment */
  15.925 -      } /* if */
  15.926 -    } /* if */
  15.927 -  } /* if */
  15.928 -  /* Array elements are sometimes considered as sub-arrays --when the
  15.929 -   * array index is an enumeration field and the enumeration size is greater
  15.930 -   * than 1. If the expression on the right side of the assignment is a cell,
  15.931 -   * or if an operation is in effect, this does not apply.
  15.932 -   */
  15.933 -  leftarray= lval3.ident==iARRAY || lval3.ident==iREFARRAY
  15.934 -             || ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
  15.935 -                 && lval3.constval>1 && lval3.sym->dim.array.level==0
  15.936 -                 && !oper && (lval2.ident==iARRAY || lval2.ident==iREFARRAY));
  15.937 -  if (leftarray) {
  15.938 -    /* Left operand is an array, right operand should be an array variable
  15.939 -     * of the same size and the same dimension, an array literal (of the
  15.940 -     * same size) or a literal string. For single-dimensional arrays without
  15.941 -     * tag for the index, it is permitted to assign a smaller array into a
  15.942 -     * larger one (without warning). This is to make it easier to work with
  15.943 -     * strings.
  15.944 -     */
  15.945 -    int exactmatch=TRUE;
  15.946 -    int idxtag=0;
  15.947 -    int ltlength=(int)lval3.sym->dim.array.length;
  15.948 -    if ((lval3.ident==iARRAYCELL || lval3.ident==iARRAYCHAR)
  15.949 -        && lval3.constval>0 && lval3.sym->dim.array.level==0)
  15.950 -    {
  15.951 -      ltlength=(int)lval3.constval;
  15.952 -    } /* if */
  15.953 -    if (lval2.ident!=iARRAY && lval2.ident!=iREFARRAY
  15.954 -        && (lval2.sym==NULL || lval2.constval<=0))
  15.955 -      error(33,lval3.sym->name);        /* array must be indexed */
  15.956 -    if (lval2.sym!=NULL) {
  15.957 -      if (lval2.constval==0) {
  15.958 -        val=lval2.sym->dim.array.length;/* array variable */
  15.959 -      } else {
  15.960 -        val=lval2.constval;
  15.961 -        if (lval2.sym->dim.array.level!=0)
  15.962 -          error(28,lval2.sym->name);
  15.963 -      } /* if */
  15.964 -      level=lval2.sym->dim.array.level;
  15.965 -      idxtag=lval2.sym->x.tags.index;
  15.966 -      if (level==0 && idxtag==0 && lval3.sym->x.tags.index==0)
  15.967 -        exactmatch=FALSE;
  15.968 -    } else {
  15.969 -      val=lval2.constval;               /* literal array */
  15.970 -      level=0;
  15.971 -      /* If val is negative, it means that lval2 is a literal string.
  15.972 -       * The string array size may be smaller than the destination
  15.973 -       * array, provided that the destination array does not have an
  15.974 -       * index tag.
  15.975 -       */
  15.976 -      if (val<0) {
  15.977 -        val=-val;
  15.978 -        if (lval3.sym->x.tags.index==0)
  15.979 -          exactmatch=FALSE;
  15.980 -      } /* if */
  15.981 -    } /* if */
  15.982 -    if (lval3.sym->dim.array.level!=level)
  15.983 -      return error(48); /* array dimensions must match */
  15.984 -    else if (ltlength<val || exactmatch && ltlength>val || val==0)
  15.985 -      return error(47); /* array sizes must match */
  15.986 -    else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE))
  15.987 -      error(229,(lval2.sym!=NULL) ? lval2.sym->name : lval3.sym->name); /* index tag mismatch */
  15.988 -    if (level>0) {
  15.989 -      /* check the sizes of all sublevels too */
  15.990 -      symbol *sym1 = lval3.sym;
  15.991 -      symbol *sym2 = lval2.sym;
  15.992 -      int i;
  15.993 -      assert(sym1!=NULL && sym2!=NULL);
  15.994 -      /* ^^^ sym2 must be valid, because only variables can be
  15.995 -       *     multi-dimensional (there are no multi-dimensional literals),
  15.996 -       *     sym1 must be valid because it must be an lvalue
  15.997 -       */
  15.998 -      assert(exactmatch);
  15.999 -      for (i=0; i<level; i++) {
 15.1000 -        sym1=finddepend(sym1);
 15.1001 -        sym2=finddepend(sym2);
 15.1002 -        assert(sym1!=NULL && sym2!=NULL);
 15.1003 -        /* ^^^ both arrays have the same dimensions (this was checked
 15.1004 -         *     earlier) so the dependend should always be found
 15.1005 -         */
 15.1006 -        if (sym1->dim.array.length!=sym2->dim.array.length)
 15.1007 -          error(47);    /* array sizes must match */
 15.1008 -        else if (!matchtag(sym1->x.tags.index,sym2->x.tags.index,TRUE))
 15.1009 -          error(229,sym2->name);  /* index tag mismatch */
 15.1010 -      } /* for */
 15.1011 -      /* get the total size in cells of the multi-dimensional array */
 15.1012 -      val=array_totalsize(lval3.sym);
 15.1013 -      assert(val>0);    /* already checked */
 15.1014 -    } /* if */
 15.1015 -  } else {
 15.1016 -    /* left operand is not an array, right operand should then not be either */
 15.1017 -    if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
 15.1018 -      error(6);         /* must be assigned to an array */
 15.1019 -  } /* if */
 15.1020 -  if (leftarray) {
 15.1021 -    memcopy(val*sizeof(cell));
 15.1022 -  } else {
 15.1023 -    check_userop(NULL,lval2.tag,lval3.tag,2,&lval3,&lval2.tag);
 15.1024 -    store(&lval3);      /* now, store the expression result */
 15.1025 -  } /* if */
 15.1026 -  if (!oper && !matchtag(lval3.tag,lval2.tag,TRUE))
 15.1027 -    error(213);         /* tagname mismatch (if "oper", warning already given in plunge2()) */
 15.1028 -  if (lval3.sym)
 15.1029 -    markusage(lval3.sym,uWRITTEN);
 15.1030 -  sideeffect=TRUE;
 15.1031 -  bitwise_opercount=bwcount;
 15.1032 -  lval1->ident=iEXPRESSION;
 15.1033 -  return FALSE;         /* expression result is never an lvalue */
 15.1034 -}
 15.1035 -
 15.1036 -static int hier13(value *lval)
 15.1037 -{
 15.1038 -  int lvalue=plnge1(hier12,lval);
 15.1039 -  if (matchtoken('?')) {
 15.1040 -    int flab1=getlabel();
 15.1041 -    int flab2=getlabel();
 15.1042 -    value lval2={0};
 15.1043 -    int array1,array2;
 15.1044 -
 15.1045 -    if (lvalue) {
 15.1046 -      rvalue(lval);
 15.1047 -    } else if (lval->ident==iCONSTEXPR) {
 15.1048 -      ldconst(lval->constval,sPRI);
 15.1049 -      error(lval->constval ? 206 : 205);        /* redundant test */
 15.1050 -    } /* if */
 15.1051 -    jmp_eq0(flab1);             /* go to second expression if primary register==0 */
 15.1052 -    PUSHSTK_I(sc_allowtags);
 15.1053 -    sc_allowtags=FALSE;         /* do not allow tagnames here (colon is a special token) */
 15.1054 -    if (hier13(lval))
 15.1055 -      rvalue(lval);
 15.1056 -    if (lval->ident==iCONSTEXPR)        /* load constant here */
 15.1057 -      ldconst(lval->constval,sPRI);
 15.1058 -    sc_allowtags=(short)POPSTK_I();     /* restore */
 15.1059 -    jumplabel(flab2);
 15.1060 -    setlabel(flab1);
 15.1061 -    needtoken(':');
 15.1062 -    if (hier13(&lval2))
 15.1063 -      rvalue(&lval2);
 15.1064 -    if (lval2.ident==iCONSTEXPR)        /* load constant here */
 15.1065 -      ldconst(lval2.constval,sPRI);
 15.1066 -    array1= (lval->ident==iARRAY || lval->ident==iREFARRAY);
 15.1067 -    array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY);
 15.1068 -    if (array1 && !array2) {
 15.1069 -      char *ptr=(lval->sym->name!=NULL) ? lval->sym->name : "-unknown-";
 15.1070 -      error(33,ptr);            /* array must be indexed */
 15.1071 -    } else if (!array1 && array2) {
 15.1072 -      char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-";
 15.1073 -      error(33,ptr);            /* array must be indexed */
 15.1074 -    } /* if */
 15.1075 -    /* ??? if both are arrays, should check dimensions */
 15.1076 -    if (!matchtag(lval->tag,lval2.tag,FALSE))
 15.1077 -      error(213);               /* tagname mismatch ('true' and 'false' expressions) */
 15.1078 -    setlabel(flab2);
 15.1079 -    if (lval->ident==iARRAY)
 15.1080 -      lval->ident=iREFARRAY;    /* iARRAY becomes iREFARRAY */
 15.1081 -    else if (lval->ident!=iREFARRAY)
 15.1082 -      lval->ident=iEXPRESSION;  /* iREFARRAY stays iREFARRAY, rest becomes iEXPRESSION */
 15.1083 -    return FALSE;               /* conditional expression is no lvalue */
 15.1084 -  } else {
 15.1085 -    return lvalue;
 15.1086 -  } /* if */
 15.1087 -}
 15.1088 -
 15.1089 -/* the order of the operators in these lists is important and must be
 15.1090 - * the same as the order of the operators in the array "op1"
 15.1091 - */
 15.1092 -static int list3[]  = {'*','/','%',0};
 15.1093 -static int list4[]  = {'+','-',0};
 15.1094 -static int list5[]  = {tSHL,tSHR,tSHRU,0};
 15.1095 -static int list6[]  = {'&',0};
 15.1096 -static int list7[]  = {'^',0};
 15.1097 -static int list8[]  = {'|',0};
 15.1098 -static int list9[]  = {tlLE,tlGE,'<','>',0};
 15.1099 -static int list10[] = {tlEQ,tlNE,0};
 15.1100 -static int list11[] = {tlAND,0};
 15.1101 -static int list12[] = {tlOR,0};
 15.1102 -
 15.1103 -static int hier12(value *lval)
 15.1104 -{
 15.1105 -  return skim(list12,jmp_ne0,1,0,hier11,lval);
 15.1106 -}
 15.1107 -
 15.1108 -static int hier11(value *lval)
 15.1109 -{
 15.1110 -  return skim(list11,jmp_eq0,0,1,hier10,lval);
 15.1111 -}
 15.1112 -
 15.1113 -static int hier10(value *lval)
 15.1114 -{ /* ==, != */
 15.1115 -  return plnge(list10,15,hier9,lval,"bool",TRUE);
 15.1116 -}                  /* ^ this variable is the starting index in the op1[]
 15.1117 -                    *   array of the operators of this hierarchy level */
 15.1118 -
 15.1119 -static int hier9(value *lval)
 15.1120 -{ /* <=, >=, <, > */
 15.1121 -  return plnge_rel(list9,11,hier8,lval);
 15.1122 -}
 15.1123 -
 15.1124 -static int hier8(value *lval)
 15.1125 -{ /* | */
 15.1126 -  return plnge(list8,10,hier7,lval,NULL,FALSE);
 15.1127 -}
 15.1128 -
 15.1129 -static int hier7(value *lval)
 15.1130 -{ /* ^ */
 15.1131 -  return plnge(list7,9,hier6,lval,NULL,FALSE);
 15.1132 -}
 15.1133 -
 15.1134 -static int hier6(value *lval)
 15.1135 -{ /* & */
 15.1136 -  return plnge(list6,8,hier5,lval,NULL,FALSE);
 15.1137 -}
 15.1138 -
 15.1139 -static int hier5(value *lval)
 15.1140 -{ /* <<, >>, >>> */
 15.1141 -  return plnge(list5,5,hier4,lval,NULL,FALSE);
 15.1142 -}
 15.1143 -
 15.1144 -static int hier4(value *lval)
 15.1145 -{ /* +, - */
 15.1146 -  return plnge(list4,3,hier3,lval,NULL,FALSE);
 15.1147 -}
 15.1148 -
 15.1149 -static int hier3(value *lval)
 15.1150 -{ /* *, /, % */
 15.1151 -  return plnge(list3,0,hier2,lval,NULL,FALSE);
 15.1152 -}
 15.1153 -
 15.1154 -static int hier2(value *lval)
 15.1155 -{
 15.1156 -  int lvalue,tok;
 15.1157 -  int tag,paranthese;
 15.1158 -  cell val;
 15.1159 -  char *st;
 15.1160 -  symbol *sym;
 15.1161 -  int saveresult;
 15.1162 -
 15.1163 -  tok=lex(&val,&st);
 15.1164 -  switch (tok) {
 15.1165 -  case tINC:                    /* ++lval */
 15.1166 -    if (!hier2(lval))
 15.1167 -      return error(22);         /* must be lvalue */
 15.1168 -    assert(lval->sym!=NULL);
 15.1169 -    if ((lval->sym->usage & uCONST)!=0)
 15.1170 -      return error(22);         /* assignment to const argument */
 15.1171 -    if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
 15.1172 -      inc(lval);                /* increase variable first */
 15.1173 -    rvalue(lval);               /* and read the result into PRI */
 15.1174 -    sideeffect=TRUE;
 15.1175 -    return FALSE;               /* result is no longer lvalue */
 15.1176 -  case tDEC:                    /* --lval */
 15.1177 -    if (!hier2(lval))
 15.1178 -      return error(22);         /* must be lvalue */
 15.1179 -    assert(lval->sym!=NULL);
 15.1180 -    if ((lval->sym->usage & uCONST)!=0)
 15.1181 -      return error(22);         /* assignment to const argument */
 15.1182 -    if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
 15.1183 -      dec(lval);                /* decrease variable first */
 15.1184 -    rvalue(lval);               /* and read the result into PRI */
 15.1185 -    sideeffect=TRUE;
 15.1186 -    return FALSE;               /* result is no longer lvalue */
 15.1187 -  case '~':                     /* ~ (one's complement) */
 15.1188 -    if (hier2(lval))
 15.1189 -      rvalue(lval);
 15.1190 -    invert();                   /* bitwise NOT */
 15.1191 -    lval->constval=~lval->constval;
 15.1192 -    return FALSE;
 15.1193 -  case '!':                     /* ! (logical negate) */
 15.1194 -    if (hier2(lval))
 15.1195 -      rvalue(lval);
 15.1196 -    if (check_userop(lneg,lval->tag,0,1,NULL,&lval->tag)) {
 15.1197 -      lval->ident=iEXPRESSION;
 15.1198 -      lval->constval=0;
 15.1199 -    } else {
 15.1200 -      lneg();                   /* 0 -> 1,  !0 -> 0 */
 15.1201 -      lval->constval=!lval->constval;
 15.1202 -      lval->tag=pc_addtag("bool");
 15.1203 -    } /* if */
 15.1204 -    return FALSE;
 15.1205 -  case '-':                     /* unary - (two's complement) */
 15.1206 -    if (hier2(lval))
 15.1207 -      rvalue(lval);
 15.1208 -    /* make a special check for a constant expression with the tag of a
 15.1209 -     * rational number, so that we can simple swap the sign of that constant.
 15.1210 -     */
 15.1211 -    if (lval->ident==iCONSTEXPR && lval->tag==sc_rationaltag && sc_rationaltag!=0) {
 15.1212 -      if (rational_digits==0) {
 15.1213 -        #if PAWN_CELL_SIZE==32
 15.1214 -          float *f = (float *)&lval->constval;
 15.1215 -        #elif PAWN_CELL_SIZE==64
 15.1216 -          double *f = (double *)&lval->constval;
 15.1217 -        #else
 15.1218 -          #error Unsupported cell size
 15.1219 -        #endif
 15.1220 -        *f= - *f; /* this modifies lval->constval */
 15.1221 -      } else {
 15.1222 -        /* the negation of a fixed point number is just an integer negation */
 15.1223 -        lval->constval=-lval->constval;
 15.1224 -      } /* if */
 15.1225 -    } else if (check_userop(neg,lval->tag,0,1,NULL,&lval->tag)) {
 15.1226 -      lval->ident=iEXPRESSION;
 15.1227 -      lval->constval=0;
 15.1228 -    } else {
 15.1229 -      neg();                    /* arithmic negation */
 15.1230 -      lval->constval=-lval->constval;
 15.1231 -    } /* if */
 15.1232 -    return FALSE;
 15.1233 -  case tLABEL:                  /* tagname override */
 15.1234 -    tag=pc_addtag(st);
 15.1235 -    lval->cmptag=tag;
 15.1236 -    lvalue=hier2(lval);
 15.1237 -    lval->tag=tag;
 15.1238 -    return lvalue;
 15.1239 -  case tDEFINED:
 15.1240 -    paranthese=0;
 15.1241 -    while (matchtoken('('))
 15.1242 -      paranthese++;
 15.1243 -    tok=lex(&val,&st);
 15.1244 -    if (tok!=tSYMBOL)
 15.1245 -      return error(20,st);      /* illegal symbol name */
 15.1246 -    sym=findloc(st);
 15.1247 -    if (sym==NULL)
 15.1248 -      sym=findglb(st,sSTATEVAR);
 15.1249 -    if (sym!=NULL && sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0)
 15.1250 -      sym=NULL;                 /* symbol is not a function, it is in the table, but not "defined" */
 15.1251 -    val= (sym!=NULL);
 15.1252 -    if (!val && find_subst(st,strlen(st))!=NULL)
 15.1253 -      val=1;
 15.1254 -    clear_value(lval);
 15.1255 -    lval->ident=iCONSTEXPR;
 15.1256 -    lval->constval= val;
 15.1257 -    lval->tag=pc_addtag("bool");
 15.1258 -    ldconst(lval->constval,sPRI);
 15.1259 -    while (paranthese--)
 15.1260 -      needtoken(')');
 15.1261 -    return FALSE;
 15.1262 -  case tSIZEOF:
 15.1263 -    paranthese=0;
 15.1264 -    while (matchtoken('('))
 15.1265 -      paranthese++;
 15.1266 -    tok=lex(&val,&st);
 15.1267 -    if (tok!=tSYMBOL)
 15.1268 -      return error(20,st);      /* illegal symbol name */
 15.1269 -    sym=findloc(st);
 15.1270 -    if (sym==NULL)
 15.1271 -      sym=findglb(st,sSTATEVAR);
 15.1272 -    if (sym==NULL)
 15.1273 -      return error(17,st);      /* undefined symbol */
 15.1274 -    if (sym->ident==iCONSTEXPR)
 15.1275 -      error(39);                /* constant symbol has no size */
 15.1276 -    else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC)
 15.1277 -      error(72);                /* "function" symbol has no size */
 15.1278 -    else if ((sym->usage & uDEFINE)==0)
 15.1279 -      return error(17,st);      /* undefined symbol (symbol is in the table, but it is "used" only) */
 15.1280 -    clear_value(lval);
 15.1281 -    lval->ident=iCONSTEXPR;
 15.1282 -    lval->constval=1;           /* preset */
 15.1283 -    if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
 15.1284 -      int level;
 15.1285 -      symbol *idxsym=NULL;
 15.1286 -      symbol *subsym=sym;
 15.1287 -      for (level=0; matchtoken('['); level++) {
 15.1288 -        idxsym=NULL;
 15.1289 -        if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
 15.1290 -          char *idxname;
 15.1291 -          int cmptag=subsym->x.tags.index;
 15.1292 -          tokeninfo(&val,&idxname);
 15.1293 -          if ((idxsym=findconst(idxname,&cmptag))==NULL)
 15.1294 -            error(80,idxname);  /* unknown symbol, or non-constant */
 15.1295 -          else if (cmptag>1)
 15.1296 -            error(91,idxname);  /* ambiguous constant */
 15.1297 -        } /* if */
 15.1298 -        needtoken(']');
 15.1299 -        if (subsym!=NULL)
 15.1300 -          subsym=finddepend(subsym);
 15.1301 -      } /* for */
 15.1302 -      if (level>sym->dim.array.level+1)
 15.1303 -        error(28,sym->name);  /* invalid subscript */
 15.1304 -      else if (level==sym->dim.array.level+1)
 15.1305 -        lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
 15.1306 -      else
 15.1307 -        lval->constval=array_levelsize(sym,level);
 15.1308 -      if (lval->constval==0 && strchr((char *)lptr,PREPROC_TERM)==NULL)
 15.1309 -        error(224,st);          /* indeterminate array size in "sizeof" expression */
 15.1310 -    } /* if */
 15.1311 -    ldconst(lval->constval,sPRI);
 15.1312 -    while (paranthese--)
 15.1313 -      needtoken(')');
 15.1314 -    return FALSE;
 15.1315 -  case tTAGOF:
 15.1316 -    paranthese=0;
 15.1317 -    while (matchtoken('('))
 15.1318 -      paranthese++;
 15.1319 -    tok=lex(&val,&st);
 15.1320 -    if (tok!=tSYMBOL && tok!=tLABEL)
 15.1321 -      return error(20,st);      /* illegal symbol name */
 15.1322 -    if (tok==tLABEL) {
 15.1323 -      constvalue *tagsym=find_constval(&tagname_tab,st,0);
 15.1324 -      tag=(int)((tagsym!=NULL) ? tagsym->value : 0);
 15.1325 -    } else {
 15.1326 -      sym=findloc(st);
 15.1327 -      if (sym==NULL)
 15.1328 -        sym=findglb(st,sSTATEVAR);
 15.1329 -      if (sym==NULL)
 15.1330 -        return error(17,st);      /* undefined symbol */
 15.1331 -      if ((sym->usage & uDEFINE)==0)
 15.1332 -        return error(17,st);      /* undefined symbol (symbol is in the table, but it is "used" only) */
 15.1333 -      tag=sym->tag;
 15.1334 -    } /* if */
 15.1335 -    if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
 15.1336 -      int level;
 15.1337 -      symbol *idxsym=NULL;
 15.1338 -      symbol *subsym=sym;
 15.1339 -      for (level=0; matchtoken('['); level++) {
 15.1340 -        idxsym=NULL;
 15.1341 -        if (subsym!=NULL && level==subsym->dim.array.level && matchtoken(tSYMBOL)) {
 15.1342 -          char *idxname;
 15.1343 -          int cmptag=subsym->x.tags.index;
 15.1344 -          tokeninfo(&val,&idxname);
 15.1345 -          if ((idxsym=findconst(idxname,&cmptag))==NULL)
 15.1346 -            error(80,idxname);  /* unknown symbol, or non-constant */
 15.1347 -          else if (cmptag>1)
 15.1348 -            error(91,idxname);  /* ambiguous constant */
 15.1349 -        } /* if */
 15.1350 -        needtoken(']');
 15.1351 -        if (subsym!=NULL)
 15.1352 -          subsym=finddepend(subsym);
 15.1353 -      } /* for */
 15.1354 -      if (level>sym->dim.array.level+1)
 15.1355 -        error(28,sym->name);  /* invalid subscript */
 15.1356 -      else if (level==sym->dim.array.level+1 && idxsym!=NULL)
 15.1357 -        tag= idxsym->x.tags.index;
 15.1358 -    } /* if */
 15.1359 -    exporttag(tag);
 15.1360 -    clear_value(lval);
 15.1361 -    lval->ident=iCONSTEXPR;
 15.1362 -    lval->constval=tag | PUBLICTAG;
 15.1363 -    ldconst(lval->constval,sPRI);
 15.1364 -    while (paranthese--)
 15.1365 -      needtoken(')');
 15.1366 -    return FALSE;
 15.1367 -  case tSTATE: {
 15.1368 -    constvalue *automaton;
 15.1369 -    constvalue *state;
 15.1370 -    if (sc_getstateid(&automaton,&state)) {
 15.1371 -      assert(automaton!=NULL);
 15.1372 -      assert(automaton->index==0 && automaton->name[0]=='\0' || automaton->index>0);
 15.1373 -      loadreg(automaton->value,sALT);
 15.1374 -      assert(state!=NULL);
 15.1375 -      ldconst(state->value,sPRI);
 15.1376 -      ob_eq();
 15.1377 -      clear_value(lval);
 15.1378 -      lval->ident=iEXPRESSION;
 15.1379 -      lval->tag=pc_addtag("bool");
 15.1380 -    } /* if */
 15.1381 -    return FALSE;
 15.1382 -  } /* case */
 15.1383 -  default:
 15.1384 -    lexpush();
 15.1385 -    lvalue=hier1(lval);
 15.1386 -    /* check for postfix operators */
 15.1387 -    if (matchtoken(';')) {
 15.1388 -      /* Found a ';', do not look further for postfix operators */
 15.1389 -      lexpush();                /* push ';' back after successful match */
 15.1390 -      return lvalue;
 15.1391 -    } else if (matchtoken(tTERM)) {
 15.1392 -      /* Found a newline that ends a statement (this is the case when
 15.1393 -       * semicolons are optional). Note that an explicit semicolon was
 15.1394 -       * handled above. This case is similar, except that the token must
 15.1395 -       * not be pushed back.
 15.1396 -       */
 15.1397 -      return lvalue;
 15.1398 -    } else {
 15.1399 -      tok=lex(&val,&st);
 15.1400 -      switch (tok) {
 15.1401 -      case tINC:                /* lval++ */
 15.1402 -        if (!lvalue)
 15.1403 -          return error(22);     /* must be lvalue */
 15.1404 -        assert(lval->sym!=NULL);
 15.1405 -        if ((lval->sym->usage & uCONST)!=0)
 15.1406 -          return error(22);     /* assignment to const argument */
 15.1407 -        /* on incrementing array cells, the address in PRI must be saved for
 15.1408 -         * incremening the value, whereas the current value must be in PRI
 15.1409 -         * on exit.
 15.1410 -         */
 15.1411 -        saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
 15.1412 -        if (saveresult)
 15.1413 -          pushreg(sPRI);        /* save address in PRI */
 15.1414 -        rvalue(lval);           /* read current value into PRI */
 15.1415 -        if (saveresult)
 15.1416 -          swap1();              /* save PRI on the stack, restore address in PRI */
 15.1417 -        if (!check_userop(user_inc,lval->tag,0,1,lval,&lval->tag))
 15.1418 -          inc(lval);            /* increase variable afterwards */
 15.1419 -        if (saveresult)
 15.1420 -          popreg(sPRI);         /* restore PRI (result of rvalue()) */
 15.1421 -        sideeffect=TRUE;
 15.1422 -        return FALSE;           /* result is no longer lvalue */
 15.1423 -      case tDEC:                /* lval-- */
 15.1424 -        if (!lvalue)
 15.1425 -          return error(22);     /* must be lvalue */
 15.1426 -        assert(lval->sym!=NULL);
 15.1427 -        if ((lval->sym->usage & uCONST)!=0)
 15.1428 -          return error(22);     /* assignment to const argument */
 15.1429 -        saveresult= (lval->ident==iARRAYCELL || lval->ident==iARRAYCHAR);
 15.1430 -        if (saveresult)
 15.1431 -          pushreg(sPRI);        /* save address in PRI */
 15.1432 -        rvalue(lval);           /* read current value into PRI */
 15.1433 -        if (saveresult)
 15.1434 -          swap1();              /* save PRI on the stack, restore address in PRI */
 15.1435 -        if (!check_userop(user_dec,lval->tag,0,1,lval,&lval->tag))
 15.1436 -          dec(lval);            /* decrease variable afterwards */
 15.1437 -        if (saveresult)
 15.1438 -          popreg(sPRI);         /* restore PRI (result of rvalue()) */
 15.1439 -        sideeffect=TRUE;
 15.1440 -        return FALSE;
 15.1441 -      case tCHAR:               /* char (compute required # of cells */
 15.1442 -        if (lval->ident==iCONSTEXPR) {
 15.1443 -          lval->constval *= sCHARBITS/8;  /* from char to bytes */
 15.1444 -          lval->constval = (lval->constval + sizeof(cell)-1) / sizeof(cell);
 15.1445 -        } else {
 15.1446 -          if (lvalue)
 15.1447 -            rvalue(lval);       /* fetch value if not already in PRI */
 15.1448 -          char2addr();          /* from characters to bytes */
 15.1449 -          addconst(sizeof(cell)-1);     /* make sure the value is rounded up */
 15.1450 -          addr2cell();          /* truncate to number of cells */
 15.1451 -        } /* if */
 15.1452 -        return FALSE;
 15.1453 -      default:
 15.1454 -        lexpush();
 15.1455 -        return lvalue;
 15.1456 -      } /* switch */
 15.1457 -    } /* if */
 15.1458 -  } /* switch */
 15.1459 -}
 15.1460 -
 15.1461 -/*  hier1
 15.1462 - *
 15.1463 - *  The highest hierarchy level: it looks for pointer and array indices
 15.1464 - *  and function calls.
 15.1465 - *  Generates code to fetch a pointer value if it is indexed and code to
 15.1466 - *  add to the pointer value or the array address (the address is already
 15.1467 - *  read at primary()). It also generates code to fetch a function address
 15.1468 - *  if that hasn't already been done at primary() (check lval[4]) and calls
 15.1469 - *  callfunction() to call the function.
 15.1470 - */
 15.1471 -static int hier1(value *lval1)
 15.1472 -{
 15.1473 -  int lvalue,index,tok,symtok;
 15.1474 -  cell val,cidx;
 15.1475 -  value lval2={0};
 15.1476 -  char *st;
 15.1477 -  char close;
 15.1478 -  symbol *sym;
 15.1479 -  symbol dummysymbol,*cursym;   /* for changing the index tags in case of enumerated pseudo-arrays */
 15.1480 -
 15.1481 -  lvalue=primary(lval1);
 15.1482 -  symtok=tokeninfo(&val,&st);   /* get token read by primary() */
 15.1483 -  cursym=lval1->sym;
 15.1484 -restart:
 15.1485 -  sym=cursym;
 15.1486 -  if (matchtoken('[') || matchtoken('{') || matchtoken('(')) {
 15.1487 -    tok=tokeninfo(&val,&st);    /* get token read by matchtoken() */
 15.1488 -    if (sym==NULL && symtok!=tSYMBOL) {
 15.1489 -      /* we do not have a valid symbol and we appear not to have read a valid
 15.1490 -       * symbol name (so it is unlikely that we would have read a name of an
 15.1491 -       * undefined symbol) */
 15.1492 -      error(29);                /* expression error, assumed 0 */
 15.1493 -      lexpush();                /* analyse '(', '{' or '[' again later */
 15.1494 -      return FALSE;
 15.1495 -    } /* if */
 15.1496 -    if (tok=='[' || tok=='{') { /* subscript */
 15.1497 -      close = (char)((tok=='[') ? ']' : '}');
 15.1498 -      if (sym==NULL) {  /* sym==NULL if lval is a constant or a literal */
 15.1499 -        error(28,"<no variable>");  /* cannot subscript */
 15.1500 -        needtoken(close);
 15.1501 -        return FALSE;
 15.1502 -      } else if (sym->ident!=iARRAY && sym->ident!=iREFARRAY){
 15.1503 -        error(28,sym->name);    /* cannot subscript, variable is not an array */
 15.1504 -        needtoken(close);
 15.1505 -        return FALSE;
 15.1506 -      } else if (sym->dim.array.level>0 && close!=']') {
 15.1507 -        error(51);      /* invalid subscript, must use [ ] */
 15.1508 -        needtoken(close);
 15.1509 -        return FALSE;
 15.1510 -      } /* if */
 15.1511 -      /* set the tag to match (enumeration fields as indices) */
 15.1512 -      lval2.cmptag=sym->x.tags.index;
 15.1513 -      stgget(&index,&cidx);     /* mark position in code generator */
 15.1514 -      pushreg(sPRI);            /* save base address of the array */
 15.1515 -      if (hier14(&lval2))       /* create expression for the array index */
 15.1516 -        rvalue(&lval2);
 15.1517 -      if (lval2.ident==iARRAY || lval2.ident==iREFARRAY)
 15.1518 -        error(33,lval2.sym->name);      /* array must be indexed */
 15.1519 -      needtoken(close);
 15.1520 -      if (!matchtag(sym->x.tags.index,lval2.tag,TRUE))
 15.1521 -        error(213);
 15.1522 -      if (lval2.ident==iCONSTEXPR) {    /* constant expression */
 15.1523 -        stgdel(index,cidx);             /* scratch generated code */
 15.1524 -        if (lval1->arrayidx!=NULL) {    /* keep constant index, for checking */
 15.1525 -          assert(sym->dim.array.level>=0 && sym->dim.array.level<sDIMEN_MAX);
 15.1526 -          lval1->arrayidx[sym->dim.array.level]=lval2.constval;
 15.1527 -        } /* if */
 15.1528 -        if (close==']') {
 15.1529 -          /* normal array index */
 15.1530 -          if (lval2.constval<0 || sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval)
 15.1531 -            error(32,sym->name);        /* array index out of bounds */
 15.1532 -          if (lval2.constval!=0) {
 15.1533 -            /* don't add offsets for zero subscripts */
 15.1534 -            #if PAWN_CELL_SIZE==16
 15.1535 -              ldconst(lval2.constval<<1,sALT);
 15.1536 -            #elif PAWN_CELL_SIZE==32
 15.1537 -              ldconst(lval2.constval<<2,sALT);
 15.1538 -            #elif PAWN_CELL_SIZE==64
 15.1539 -              ldconst(lval2.constval<<3,sALT);
 15.1540 -            #else
 15.1541 -              #error Unsupported cell size
 15.1542 -            #endif
 15.1543 -            ob_add();
 15.1544 -          } /* if */
 15.1545 -        } else {
 15.1546 -          /* character index */
 15.1547 -          if (lval2.constval<0 || sym->dim.array.length!=0
 15.1548 -              && sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval)
 15.1549 -            error(32,sym->name);        /* array index out of bounds */
 15.1550 -          if (lval2.constval!=0) {
 15.1551 -            /* don't add offsets for zero subscripts */
 15.1552 -            #if sCHARBITS==16
 15.1553 -              ldconst(lval2.constval<<1,sALT);/* 16-bit character */
 15.1554 -            #else
 15.1555 -              ldconst(lval2.constval,sALT);   /* 8-bit character */
 15.1556 -            #endif
 15.1557 -            ob_add();
 15.1558 -          } /* if */
 15.1559 -          charalign();                  /* align character index into array */
 15.1560 -        } /* if */
 15.1561 -        /* if the array index is a field from an enumeration, get the tag name
 15.1562 -         * from the field and save the size of the field too.
 15.1563 -         */
 15.1564 -        assert(lval2.sym==NULL || lval2.sym->dim.array.level==0);
 15.1565 -        if (lval2.sym!=NULL && lval2.sym->dim.array.length>0 && sym->dim.array.level==0) {
 15.1566 -          lval1->tag=lval2.sym->x.tags.index;
 15.1567 -          lval1->constval=lval2.sym->dim.array.length;
 15.1568 -        } /* if */
 15.1569 -      } else {
 15.1570 -        /* array index is not constant */
 15.1571 -        lval1->arrayidx=NULL;           /* reset, so won't be checked */
 15.1572 -        if (close==']') {
 15.1573 -          if (sym->dim.array.length!=0)
 15.1574 -            ffbounds(sym->dim.array.length-1);  /* run time check for array bounds */
 15.1575 -          cell2addr();  /* normal array index */
 15.1576 -        } else {
 15.1577 -          if (sym->dim.array.length!=0)
 15.1578 -            ffbounds(sym->dim.array.length*(32/sCHARBITS)-1);
 15.1579 -          char2addr();  /* character array index */
 15.1580 -        } /* if */
 15.1581 -        popreg(sALT);
 15.1582 -        ob_add();       /* base address was popped into secondary register */
 15.1583 -        if (close!=']')
 15.1584 -          charalign();  /* align character index into array */
 15.1585 -      } /* if */
 15.1586 -      /* the indexed item may be another array (multi-dimensional arrays) */
 15.1587 -      assert(cursym==sym && sym!=NULL); /* should still be set */
 15.1588 -      if (sym->dim.array.level>0) {
 15.1589 -        assert(close==']');     /* checked earlier */
 15.1590 -        assert(cursym==lval1->sym);
 15.1591 -        /* read the offset to the subarray and add it to the current address */
 15.1592 -        lval1->ident=iARRAYCELL;
 15.1593 -        pushreg(sPRI);          /* the optimizer makes this to a MOVE.alt */
 15.1594 -        rvalue(lval1);
 15.1595 -        popreg(sALT);
 15.1596 -        ob_add();
 15.1597 -        /* adjust the "value" structure and find the referenced array */
 15.1598 -        lval1->ident=iREFARRAY;
 15.1599 -        lval1->sym=finddepend(sym);
 15.1600 -        assert(lval1->sym!=NULL);
 15.1601 -        assert(lval1->sym->dim.array.level==sym->dim.array.level-1);
 15.1602 -        cursym=lval1->sym;
 15.1603 -        /* try to parse subsequent array indices */
 15.1604 -        lvalue=FALSE;   /* for now, a iREFARRAY is no lvalue */
 15.1605 -        goto restart;
 15.1606 -      } /* if */
 15.1607 -      assert(sym->dim.array.level==0);
 15.1608 -      /* set type to fetch... INDIRECTLY */
 15.1609 -      lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
 15.1610 -      /* if the array index is a field from an enumeration, get the tag name
 15.1611 -       * from the field and save the size of the field too. Otherwise, the
 15.1612 -       * tag is the one from the array symbol.
 15.1613 -       */
 15.1614 -      if (lval2.ident==iCONSTEXPR && lval2.sym!=NULL
 15.1615 -          && lval2.sym->dim.array.length>0 && sym->dim.array.level==0)
 15.1616 -      {
 15.1617 -        lval1->tag=lval2.sym->x.tags.index;
 15.1618 -        lval1->constval=lval2.sym->dim.array.length;
 15.1619 -        if (lval2.tag==sym->x.tags.index && lval1->constval>1 && matchtoken('[')) {
 15.1620 -          /* an array indexed with an enumeration field may be considered a sub-array */
 15.1621 -          lexpush();
 15.1622 -          lvalue=FALSE;   /* for now, a iREFARRAY is no lvalue */
 15.1623 -          lval1->ident=iREFARRAY;
 15.1624 -          /* initialize a dummy symbol, which is a copy of the current symbol,
 15.1625 -           * but with an adjusted index tag
 15.1626 -           */
 15.1627 -          assert(sym!=NULL);
 15.1628 -          dummysymbol=*sym;
 15.1629 -          /* get the tag of the root of the enumeration */
 15.1630 -          assert(lval2.sym!=NULL);
 15.1631 -          dummysymbol.x.tags.index=lval2.sym->x.tags.field;
 15.1632 -          dummysymbol.dim.array.length=lval2.sym->dim.array.length;
 15.1633 -          cursym=&dummysymbol;
 15.1634 -          /* recurse */
 15.1635 -          goto restart;
 15.1636 -        } /* if */
 15.1637 -      } else {
 15.1638 -        assert(sym!=NULL);
 15.1639 -        if (cursym!=&dummysymbol)
 15.1640 -          lval1->tag=sym->tag;
 15.1641 -        lval1->constval=0;
 15.1642 -      } /* if */
 15.1643 -      /* a cell in an array is an lvalue, a character in an array is not
 15.1644 -       * always a *valid* lvalue */
 15.1645 -      return TRUE;
 15.1646 -    } else {            /* tok=='(' -> function(...) */
 15.1647 -      assert(tok=='(');
 15.1648 -      if (sym==NULL
 15.1649 -          || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
 15.1650 -      {
 15.1651 -        if (sym==NULL && sc_status==statFIRST) {
 15.1652 -          /* could be a "use before declaration"; in that case, create a stub
 15.1653 -           * function so that the usage can be marked.
 15.1654 -           */
 15.1655 -          sym=fetchfunc(lastsymbol,0);
 15.1656 -          if (sym==NULL)
 15.1657 -            error(103); /* insufficient memory */
 15.1658 -          markusage(sym,uREAD);
 15.1659 -        } else {
 15.1660 -          return error(12);           /* invalid function call */
 15.1661 -        } /* if */
 15.1662 -      } else if ((sym->usage & uMISSING)!=0) {
 15.1663 -        char symname[2*sNAMEMAX+16];  /* allow space for user defined operators */
 15.1664 -        funcdisplayname(symname,sym->name);
 15.1665 -        error(4,symname);             /* function not defined */
 15.1666 -      } /* if */
 15.1667 -      callfunction(sym,lval1,TRUE);
 15.1668 -      return FALSE;             /* result of function call is no lvalue */
 15.1669 -    } /* if */
 15.1670 -  } /* if */
 15.1671 -  if (sym!=NULL && lval1->ident==iFUNCTN) {
 15.1672 -    assert(sym->ident==iFUNCTN);
 15.1673 -    if (sc_allowproccall) {
 15.1674 -      callfunction(sym,lval1,FALSE);
 15.1675 -    } else {
 15.1676 -      lval1->sym=NULL;
 15.1677 -      lval1->ident=iEXPRESSION;
 15.1678 -      lval1->constval=0;
 15.1679 -      lval1->tag=0;
 15.1680 -      error(76);                /* invalid function call, or syntax error */
 15.1681 -    } /* if */
 15.1682 -    return FALSE;
 15.1683 -  } /* if */
 15.1684 -  return lvalue;
 15.1685 -}
 15.1686 -
 15.1687 -/*  primary
 15.1688 - *
 15.1689 - *  Returns 1 if the operand is an lvalue (everything except arrays, functions
 15.1690 - *  constants and -of course- errors).
 15.1691 - *  Generates code to fetch the address of arrays. Code for constants is
 15.1692 - *  already generated by constant().
 15.1693 - *  This routine first clears the entire lval array (all fields are set to 0).
 15.1694 - *
 15.1695 - *  Global references: sc_intest  (may be altered, but restored upon termination)
 15.1696 - */
 15.1697 -static int primary(value *lval)
 15.1698 -{
 15.1699 -  char *st;
 15.1700 -  int lvalue,tok;
 15.1701 -  cell val;
 15.1702 -  symbol *sym;
 15.1703 -
 15.1704 -  if (matchtoken('(')){         /* sub-expression - (expression,...) */
 15.1705 -    PUSHSTK_I(sc_intest);
 15.1706 -    PUSHSTK_I(sc_allowtags);
 15.1707 -
 15.1708 -    sc_intest=FALSE;            /* no longer in "test" expression */
 15.1709 -    sc_allowtags=TRUE;          /* allow tagnames to be used in parenthesized expressions */
 15.1710 -    sc_allowproccall=FALSE;
 15.1711 -    do
 15.1712 -      lvalue=hier14(lval);
 15.1713 -    while (matchtoken(','));
 15.1714 -    needtoken(')');
 15.1715 -    lexclr(FALSE);              /* clear lex() push-back, it should have been
 15.1716 -                                 * cleared already by needtoken() */
 15.1717 -    sc_allowtags=(short)POPSTK_I();
 15.1718 -    sc_intest=(short)POPSTK_I();
 15.1719 -    return lvalue;
 15.1720 -  } /* if */
 15.1721 -
 15.1722 -  clear_value(lval);    /* clear lval */
 15.1723 -  tok=lex(&val,&st);
 15.1724 -  if (tok==tSYMBOL) {
 15.1725 -    /* lastsymbol is char[sNAMEMAX+1], lex() should have truncated any symbol
 15.1726 -     * to sNAMEMAX significant characters */
 15.1727 -    assert(strlen(st)<sizeof lastsymbol);
 15.1728 -    strcpy(lastsymbol,st);
 15.1729 -  } /* if */
 15.1730 -  if (tok==tSYMBOL && !findconst(st,NULL)) {
 15.1731 -    /* first look for a local variable */
 15.1732 -    if ((sym=findloc(st))!=0) {
 15.1733 -      if (sym->ident==iLABEL) {
 15.1734 -        error(29);          /* expression error, assumed 0 */
 15.1735 -        ldconst(0,sPRI);    /* load 0 */
 15.1736 -        return FALSE;       /* return 0 for labels (expression error) */
 15.1737 -      } /* if */
 15.1738 -      lval->sym=sym;
 15.1739 -      lval->ident=sym->ident;
 15.1740 -      lval->tag=sym->tag;
 15.1741 -      if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
 15.1742 -        address(sym,sPRI);  /* get starting address in primary register */
 15.1743 -        return FALSE;       /* return 0 for array (not lvalue) */
 15.1744 -      } else {
 15.1745 -        return TRUE;        /* return 1 if lvalue (not label or array) */
 15.1746 -      } /* if */
 15.1747 -    } /* if */
 15.1748 -    /* now try a global variable */
 15.1749 -    if ((sym=findglb(st,sSTATEVAR))!=0) {
 15.1750 -      if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) {
 15.1751 -        /* if the function is only in the table because it was inserted as a
 15.1752 -         * stub in the first pass (i.e. it was "used" but never declared or
 15.1753 -         * implemented, issue an error
 15.1754 -         */
 15.1755 -        if ((sym->usage & uPROTOTYPED)==0)
 15.1756 -          error(17,st);
 15.1757 -      } else {
 15.1758 -        if ((sym->usage & uDEFINE)==0)
 15.1759 -          error(17,st);
 15.1760 -        lval->sym=sym;
 15.1761 -        lval->ident=sym->ident;
 15.1762 -        lval->tag=sym->tag;
 15.1763 -        if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
 15.1764 -          address(sym,sPRI);    /* get starting address in primary register */
 15.1765 -          return FALSE;         /* return 0 for array (not lvalue) */
 15.1766 -        } else {
 15.1767 -          return TRUE;          /* return 1 if lvalue (not function or array) */
 15.1768 -        } /* if */
 15.1769 -      } /* if */
 15.1770 -    } else {
 15.1771 -      if (!sc_allowproccall)
 15.1772 -        return error(17,st);    /* undefined symbol */
 15.1773 -      /* an unknown symbol, but used in a way compatible with the "procedure
 15.1774 -       * call" syntax. So assume that the symbol refers to a function.
 15.1775 -       */
 15.1776 -      assert(sc_status==statFIRST);
 15.1777 -      sym=fetchfunc(st,0);
 15.1778 -      if (sym==NULL)
 15.1779 -        error(103);     /* insufficient memory */
 15.1780 -    } /* if */
 15.1781 -    assert(sym!=NULL);
 15.1782 -    assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
 15.1783 -    lval->sym=sym;
 15.1784 -    lval->ident=sym->ident;
 15.1785 -    lval->tag=sym->tag;
 15.1786 -    return FALSE;       /* return 0 for function (not an lvalue) */
 15.1787 -  } /* if */
 15.1788 -  lexpush();            /* push the token, it is analyzed by constant() */
 15.1789 -  if (constant(lval)==0) {
 15.1790 -    error(29);          /* expression error, assumed 0 */
 15.1791 -    ldconst(0,sPRI);    /* load 0 */
 15.1792 -  } /* if */
 15.1793 -  return FALSE;         /* return 0 for constants (or errors) */
 15.1794 -}
 15.1795 -
 15.1796 -static void clear_value(value *lval)
 15.1797 -{
 15.1798 -  lval->sym=NULL;
 15.1799 -  lval->constval=0L;
 15.1800 -  lval->tag=0;
 15.1801 -  lval->ident=0;
 15.1802 -  lval->boolresult=FALSE;
 15.1803 -  /* do not clear lval->arrayidx, it is preset in hier14() */
 15.1804 -  /* do not clear lval->cmptag */
 15.1805 -}
 15.1806 -
 15.1807 -static void setdefarray(cell *string,cell size,cell array_sz,cell *dataaddr,int fconst)
 15.1808 -{
 15.1809 -  /* The routine must copy the default array data onto the heap, as to avoid
 15.1810 -   * that a function can change the default value. An optimization is that
 15.1811 -   * the default array data is "dumped" into the data segment only once (on the
 15.1812 -   * first use).
 15.1813 -   */
 15.1814 -  assert(string!=NULL);
 15.1815 -  assert(size>0);
 15.1816 -  /* check whether to dump the default array */
 15.1817 -  assert(dataaddr!=NULL);
 15.1818 -  if (sc_status==statWRITE && *dataaddr<0) {
 15.1819 -    int i;
 15.1820 -    *dataaddr=(litidx+glb_declared)*sizeof(cell);
 15.1821 -    for (i=0; i<size; i++)
 15.1822 -      litadd(*string++);
 15.1823 -  } /* if */
 15.1824 -
 15.1825 -  /* if the function is known not to modify the array (meaning that it also
 15.1826 -   * does not modify the default value), directly pass the address of the
 15.1827 -   * array in the data segment.
 15.1828 -   */
 15.1829 -  if (fconst) {
 15.1830 -    ldconst(*dataaddr,sPRI);
 15.1831 -  } else {
 15.1832 -    /* Generate the code:
 15.1833 -     *  CONST.pri dataaddr                ;address of the default array data
 15.1834 -     *  HEAP      array_sz*sizeof(cell)   ;heap address in ALT
 15.1835 -     *  MOVS      size*sizeof(cell)       ;copy data from PRI to ALT
 15.1836 -     *  MOVE.PRI                          ;PRI = address on the heap
 15.1837 -     */
 15.1838 -    ldconst(*dataaddr,sPRI);
 15.1839 -    /* "array_sz" is the size of the argument (the value between the brackets
 15.1840 -     * in the declaration), "size" is the size of the default array data.
 15.1841 -     */
 15.1842 -    assert(array_sz>=size);
 15.1843 -    modheap((int)array_sz*sizeof(cell));
 15.1844 -    /* ??? should perhaps fill with zeros first */
 15.1845 -    memcopy(size*sizeof(cell));
 15.1846 -    moveto1();
 15.1847 -  } /* if */
 15.1848 -}
 15.1849 -
 15.1850 -static int findnamedarg(arginfo *arg,char *name)
 15.1851 -{
 15.1852 -  int i;
 15.1853 -
 15.1854 -  for (i=0; arg[i].ident!=0 && arg[i].ident!=iVARARGS; i++)
 15.1855 -    if (strcmp(arg[i].name,name)==0)
 15.1856 -      return i;
 15.1857 -  return -1;
 15.1858 -}
 15.1859 -
 15.1860 -static int checktag(int tags[],int numtags,int exprtag)
 15.1861 -{
 15.1862 -  int i;
 15.1863 -
 15.1864 -  assert(tags!=0);
 15.1865 -  assert(numtags>0);
 15.1866 -  for (i=0; i<numtags; i++)
 15.1867 -    if (matchtag(tags[i],exprtag,TRUE))
 15.1868 -      return TRUE;    /* matching tag */
 15.1869 -  return FALSE;       /* no tag matched */
 15.1870 -}
 15.1871 -
 15.1872 -enum {
 15.1873 -  ARG_UNHANDLED,
 15.1874 -  ARG_IGNORED,
 15.1875 -  ARG_DONE,
 15.1876 -};
 15.1877 -
 15.1878 -/*  callfunction
 15.1879 - *
 15.1880 - *  Generates code to call a function. This routine handles default arguments
 15.1881 - *  and positional as well as named parameters.
 15.1882 - */
 15.1883 -static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
 15.1884 -{
 15.1885 -static long nest_stkusage=0L;
 15.1886 -static int nesting=0;
 15.1887 -  int locheap;
 15.1888 -  int close,lvalue;
 15.1889 -  int argpos;       /* index in the output stream (argpos==nargs if positional parameters) */
 15.1890 -  int argidx=0;     /* index in "arginfo" list */
 15.1891 -  int nargs=0;      /* number of arguments */
 15.1892 -  int heapalloc=0;
 15.1893 -  int namedparams=FALSE;
 15.1894 -  value lval = {0};
 15.1895 -  arginfo *arg;
 15.1896 -  char arglist[sMAXARGS];
 15.1897 -  constvalue arrayszlst = { NULL, "", 0, 0};/* array size list starts empty */
 15.1898 -  constvalue taglst = { NULL, "", 0, 0};    /* tag list starts empty */
 15.1899 -  symbol *symret;
 15.1900 -  cell lexval;
 15.1901 -  char *lexstr;
 15.1902 -
 15.1903 -  assert(sym!=NULL);
 15.1904 -  lval_result->ident=iEXPRESSION; /* preset, may be changed later */
 15.1905 -  lval_result->constval=0;
 15.1906 -  lval_result->tag=sym->tag;
 15.1907 -  /* check whether this is a function that returns an array */
 15.1908 -  symret=finddepend(sym);
 15.1909 -  assert(symret==NULL || symret->ident==iREFARRAY);
 15.1910 -  if (symret!=NULL) {
 15.1911 -    int retsize;
 15.1912 -    /* allocate space on the heap for the array, and pass the pointer to the
 15.1913 -     * reserved memory block as a hidden parameter
 15.1914 -     */
 15.1915 -    retsize=(int)array_totalsize(symret);
 15.1916 -    assert(retsize>0);
 15.1917 -    modheap(retsize*sizeof(cell));/* address is in ALT */
 15.1918 -    pushreg(sALT);                /* pass ALT as the last (hidden) parameter */
 15.1919 -    decl_heap+=retsize;
 15.1920 -    /* also mark the ident of the result as "array" */
 15.1921 -    lval_result->ident=iREFARRAY;
 15.1922 -    lval_result->sym=symret;
 15.1923 -  } /* if */
 15.1924 -  locheap=decl_heap;
 15.1925 -
 15.1926 -  nesting++;
 15.1927 -  assert(nest_stkusage>=0);
 15.1928 -  #if !defined NDEBUG
 15.1929 -    if (nesting==1)
 15.1930 -      assert(nest_stkusage==0);
 15.1931 -  #endif
 15.1932 -  sc_allowproccall=FALSE;       /* parameters may not use procedure call syntax */
 15.1933 -
 15.1934 -  if ((sym->flags & flgDEPRICATED)!=0) {
 15.1935 -    char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
 15.1936 -    error(234,sym->name,ptr);   /* depricated (probably a native function) */
 15.1937 -  } /* if */
 15.1938 -
 15.1939 -  /* run through the arguments */
 15.1940 -  arg=sym->dim.arglist;
 15.1941 -  assert(arg!=NULL);
 15.1942 -  stgmark(sSTARTREORDER);
 15.1943 -  memset(arglist,ARG_UNHANDLED,sizeof arglist);
 15.1944 -  if (matchparanthesis) {
 15.1945 -    /* Opening brace was already parsed, if closing brace follows, this
 15.1946 -     * call passes no parameters.
 15.1947 -     */
 15.1948 -    close=matchtoken(')');
 15.1949 -  } else {
 15.1950 -    /* When we find an end of line here, it may be a function call passing
 15.1951 -     * no parameters, or it may be that the first parameter is on a line
 15.1952 -     * below. But as a parameter can be anything, this is difficult to check.
 15.1953 -     * The only simple check that we have is the use of "named parameters".
 15.1954 -     */
 15.1955 -    close=matchtoken(tTERM);
 15.1956 -    if (close) {
 15.1957 -      close=!matchtoken('.');
 15.1958 -      if (!close)
 15.1959 -        lexpush();                /* reset the '.' */
 15.1960 -    } /* if */
 15.1961 -  } /* if */
 15.1962 -  if (!close) {
 15.1963 -    do {
 15.1964 -      if (matchtoken('.')) {
 15.1965 -        namedparams=TRUE;
 15.1966 -        if (needtoken(tSYMBOL))
 15.1967 -          tokeninfo(&lexval,&lexstr);
 15.1968 -        else
 15.1969 -          lexstr="";
 15.1970 -        argpos=findnamedarg(arg,lexstr);
 15.1971 -        if (argpos<0) {
 15.1972 -          error(17,lexstr);       /* undefined symbol */
 15.1973 -          break;                  /* exit loop, argpos is invalid */
 15.1974 -        } /* if */
 15.1975 -        needtoken('=');
 15.1976 -        argidx=argpos;
 15.1977 -      } else {
 15.1978 -        if (namedparams)
 15.1979 -          error(44);   /* positional parameters must precede named parameters */
 15.1980 -        argpos=nargs;
 15.1981 -      } /* if */
 15.1982 -      /* the number of arguments this was already checked at the declaration
 15.1983 -       * of the function; check it again for functions with a variable
 15.1984 -       * argument list
 15.1985 -       */
 15.1986 -      if (argpos>=sMAXARGS)
 15.1987 -        error(45);                /* too many function arguments */
 15.1988 -      stgmark((char)(sEXPRSTART+argpos));/* mark beginning of new expression in stage */
 15.1989 -      if (arglist[argpos]!=ARG_UNHANDLED)
 15.1990 -        error(58);                /* argument already set */
 15.1991 -      if (matchtoken('_')) {
 15.1992 -        arglist[argpos]=ARG_IGNORED;  /* flag argument as "present, but ignored" */
 15.1993 -        if (arg[argidx].ident==0 || arg[argidx].ident==iVARARGS) {
 15.1994 -          error(202);             /* argument count mismatch */
 15.1995 -        } else if (!arg[argidx].hasdefault) {
 15.1996 -          error(34,nargs+1);      /* argument has no default value */
 15.1997 -        } /* if */
 15.1998 -        if (arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS)
 15.1999 -          argidx++;
 15.2000 -        /* The rest of the code to handle default values is at the bottom
 15.2001 -         * of this routine where default values for unspecified parameters
 15.2002 -         * are (also) handled. Note that above, the argument is flagged as
 15.2003 -         * ARG_IGNORED.
 15.2004 -         */
 15.2005 -      } else {
 15.2006 -        arglist[argpos]=ARG_DONE; /* flag argument as "present" */
 15.2007 -        if (arg[argidx].numtags==1)     /* set the expected tag, if any */
 15.2008 -          lval.cmptag=arg[argidx].tags[0];
 15.2009 -        lvalue=hier14(&lval);
 15.2010 -        assert(sc_status==statFIRST || arg[argidx].tags!=NULL);
 15.2011 -        switch (arg[argidx].ident) {
 15.2012 -        case 0:
 15.2013 -          error(202);             /* argument count mismatch */
 15.2014 -          break;
 15.2015 -        case iVARARGS:
 15.2016 -          /* always pass by reference */
 15.2017 -          if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
 15.2018 -            assert(lval.sym!=NULL);
 15.2019 -            if ((lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0) {
 15.2020 -              /* treat a "const" variable passed to a function with a non-const
 15.2021 -               * "variable argument list" as a constant here */
 15.2022 -              if (!lvalue) {
 15.2023 -                error(22);        /* need lvalue */
 15.2024 -              } else {
 15.2025 -                rvalue(&lval);    /* get value in PRI */
 15.2026 -                setheap_pri();    /* address of the value on the heap in PRI */
 15.2027 -                heapalloc++;
 15.2028 -                nest_stkusage++;
 15.2029 -              } /* if */
 15.2030 -            } else if (lvalue) {
 15.2031 -              address(lval.sym,sPRI);
 15.2032 -            } else {
 15.2033 -              setheap_pri();      /* address of the value on the heap in PRI */
 15.2034 -              heapalloc++;
 15.2035 -              nest_stkusage++;
 15.2036 -            } /* if */
 15.2037 -          } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION
 15.2038 -                     || lval.ident==iARRAYCHAR)
 15.2039 -          {
 15.2040 -            /* fetch value if needed */
 15.2041 -            if (lval.ident==iARRAYCHAR)
 15.2042 -              rvalue(&lval);
 15.2043 -            /* allocate a cell on the heap and store the
 15.2044 -             * value (already in PRI) there */
 15.2045 -            setheap_pri();        /* address of the value on the heap in PRI */
 15.2046 -            heapalloc++;
 15.2047 -            nest_stkusage++;
 15.2048 -          } /* if */
 15.2049 -          /* ??? handle const array passed by reference */
 15.2050 -          /* otherwise, the address is already in PRI */
 15.2051 -          if (lval.sym!=NULL)
 15.2052 -            markusage(lval.sym,uWRITTEN);
 15.2053 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
 15.2054 -            error(213);
 15.2055 -          if (lval.tag!=0)
 15.2056 -            append_constval(&taglst,arg[argidx].name,lval.tag,0);
 15.2057 -          break;
 15.2058 -        case iVARIABLE:
 15.2059 -          if (lval.ident==iLABEL || lval.ident==iFUNCTN || lval.ident==iREFFUNC
 15.2060 -              || lval.ident==iARRAY || lval.ident==iREFARRAY)
 15.2061 -            error(35,argidx+1);   /* argument type mismatch */
 15.2062 -          if (lvalue)
 15.2063 -            rvalue(&lval);        /* get value (direct or indirect) */
 15.2064 -          /* otherwise, the expression result is already in PRI */
 15.2065 -          assert(arg[argidx].numtags>0);
 15.2066 -          check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
 15.2067 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
 15.2068 -            error(213);
 15.2069 -          if (lval.tag!=0)
 15.2070 -            append_constval(&taglst,arg[argidx].name,lval.tag,0);
 15.2071 -          argidx++;               /* argument done */
 15.2072 -          break;
 15.2073 -        case iREFERENCE:
 15.2074 -          if (!lvalue || lval.ident==iARRAYCHAR)
 15.2075 -            error(35,argidx+1);   /* argument type mismatch */
 15.2076 -          if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
 15.2077 -            error(35,argidx+1);   /* argument type mismatch */
 15.2078 -          if (lval.ident==iVARIABLE || lval.ident==iREFERENCE) {
 15.2079 -            if (lvalue) {
 15.2080 -              assert(lval.sym!=NULL);
 15.2081 -              address(lval.sym,sPRI);
 15.2082 -            } else {
 15.2083 -              setheap_pri();      /* address of the value on the heap in PRI */
 15.2084 -              heapalloc++;
 15.2085 -              nest_stkusage++;
 15.2086 -            } /* if */
 15.2087 -          } /* if */
 15.2088 -          /* otherwise, the address is already in PRI */
 15.2089 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
 15.2090 -            error(213);
 15.2091 -          if (lval.tag!=0)
 15.2092 -            append_constval(&taglst,arg[argidx].name,lval.tag,0);
 15.2093 -          argidx++;               /* argument done */
 15.2094 -          if (lval.sym!=NULL)
 15.2095 -            markusage(lval.sym,uWRITTEN);
 15.2096 -          break;
 15.2097 -        case iREFARRAY:
 15.2098 -          if (lval.ident!=iARRAY && lval.ident!=iREFARRAY
 15.2099 -              && lval.ident!=iARRAYCELL)
 15.2100 -          {
 15.2101 -            error(35,argidx+1);   /* argument type mismatch */
 15.2102 -            break;
 15.2103 -          } /* if */
 15.2104 -          if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
 15.2105 -            error(35,argidx+1); /* argument type mismatch */
 15.2106 -          /* Verify that the dimensions match with those in arg[argidx].
 15.2107 -           * A literal array always has a single dimension.
 15.2108 -           * An iARRAYCELL parameter is also assumed to have a single dimension.
 15.2109 -           */
 15.2110 -          if (lval.sym==NULL || lval.ident==iARRAYCELL) {
 15.2111 -            if (arg[argidx].numdim!=1) {
 15.2112 -              error(48);        /* array dimensions must match */
 15.2113 -            } else if (arg[argidx].dim[0]!=0) {
 15.2114 -              assert(arg[argidx].dim[0]>0);
 15.2115 -              if (lval.ident==iARRAYCELL) {
 15.2116 -                error(47);        /* array sizes must match */
 15.2117 -              } else {
 15.2118 -                assert(lval.constval!=0); /* literal array must have a size */
 15.2119 -                /* A literal array must have exactly the same size as the
 15.2120 -                 * function argument; a literal string may be smaller than
 15.2121 -                 * the function argument.
 15.2122 -                 */
 15.2123 -                if (lval.constval>0 && arg[argidx].dim[0]!=lval.constval
 15.2124 -                    || lval.constval<0 && arg[argidx].dim[0] < -lval.constval)
 15.2125 -                  error(47);      /* array sizes must match */
 15.2126 -              } /* if */
 15.2127 -            } /* if */
 15.2128 -            if (lval.ident!=iARRAYCELL) {
 15.2129 -              /* save array size, for default values with uSIZEOF flag */
 15.2130 -              cell array_sz=lval.constval;
 15.2131 -              assert(array_sz!=0);/* literal array must have a size */
 15.2132 -              if (array_sz<0)
 15.2133 -                array_sz= -array_sz;
 15.2134 -              append_constval(&arrayszlst,arg[argidx].name,array_sz,0);
 15.2135 -            } /* if */
 15.2136 -          } else {
 15.2137 -            symbol *sym=lval.sym;
 15.2138 -            short level=0;
 15.2139 -            assert(sym!=NULL);
 15.2140 -            if (sym->dim.array.level+1!=arg[argidx].numdim)
 15.2141 -              error(48);          /* array dimensions must match */
 15.2142 -            /* the lengths for all dimensions must match, unless the dimension
 15.2143 -             * length was defined at zero (which means "undefined")
 15.2144 -             */
 15.2145 -            while (sym->dim.array.level>0) {
 15.2146 -              assert(level<sDIMEN_MAX);
 15.2147 -              if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
 15.2148 -                error(47);        /* array sizes must match */
 15.2149 -              else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
 15.2150 -                error(229,sym->name);   /* index tag mismatch */
 15.2151 -              append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
 15.2152 -              sym=finddepend(sym);
 15.2153 -              assert(sym!=NULL);
 15.2154 -              level++;
 15.2155 -            } /* if */
 15.2156 -            /* the last dimension is checked too, again, unless it is zero */
 15.2157 -            assert(level<sDIMEN_MAX);
 15.2158 -            assert(sym!=NULL);
 15.2159 -            if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level])
 15.2160 -              error(47);          /* array sizes must match */
 15.2161 -            else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE))
 15.2162 -              error(229,sym->name);   /* index tag mismatch */
 15.2163 -            append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level);
 15.2164 -          } /* if */
 15.2165 -          /* address already in PRI */
 15.2166 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
 15.2167 -            error(213);
 15.2168 -          if (lval.tag!=0)
 15.2169 -            append_constval(&taglst,arg[argidx].name,lval.tag,0);
 15.2170 -          // ??? set uWRITTEN?
 15.2171 -          argidx++;               /* argument done */
 15.2172 -          break;
 15.2173 -        } /* switch */
 15.2174 -        pushreg(sPRI);            /* store the function argument on the stack */
 15.2175 -        markexpr(sPARM,NULL,0);   /* mark the end of a sub-expression */
 15.2176 -        nest_stkusage++;
 15.2177 -      } /* if */
 15.2178 -      assert(arglist[argpos]!=ARG_UNHANDLED);
 15.2179 -      nargs++;
 15.2180 -      if (matchparanthesis) {
 15.2181 -        close=matchtoken(')');
 15.2182 -        if (!close)               /* if not paranthese... */
 15.2183 -          if (!needtoken(','))    /* ...should be comma... */
 15.2184 -            break;                /* ...but abort loop if neither */
 15.2185 -      } else {
 15.2186 -        close=!matchtoken(',');
 15.2187 -        if (close) {              /* if not comma... */
 15.2188 -          if (needtoken(tTERM)==1)/* ...must be end of statement */
 15.2189 -            lexpush();            /* push again, because end of statement is analised later */
 15.2190 -        } /* if */
 15.2191 -      } /* if */
 15.2192 -    } while (!close && freading && !matchtoken(tENDEXPR)); /* do */
 15.2193 -  } /* if */
 15.2194 -  /* check remaining function arguments (they may have default values) */
 15.2195 -  for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
 15.2196 -    if (arglist[argidx]==ARG_DONE)
 15.2197 -      continue;                 /* already seen and handled this argument */
 15.2198 -    /* in this first stage, we also skip the arguments with uSIZEOF and uTAGOF;
 15.2199 -     * these are handled last
 15.2200 -     */
 15.2201 -    if ((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0) {
 15.2202 -      assert(arg[argidx].ident==iVARIABLE);
 15.2203 -      continue;
 15.2204 -    } /* if */
 15.2205 -    stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
 15.2206 -    if (arg[argidx].hasdefault) {
 15.2207 -      if (arg[argidx].ident==iREFARRAY) {
 15.2208 -        short level;
 15.2209 -        setdefarray(arg[argidx].defvalue.array.data,
 15.2210 -                    arg[argidx].defvalue.array.size,
 15.2211 -                    arg[argidx].defvalue.array.arraysize,
 15.2212 -                    &arg[argidx].defvalue.array.addr,
 15.2213 -                    (arg[argidx].usage & uCONST)!=0);
 15.2214 -        if ((arg[argidx].usage & uCONST)==0) {
 15.2215 -          heapalloc+=arg[argidx].defvalue.array.arraysize;
 15.2216 -          nest_stkusage+=arg[argidx].defvalue.array.arraysize;
 15.2217 -        } /* if */
 15.2218 -        /* keep the lengths of all dimensions of a multi-dimensional default array */
 15.2219 -        assert(arg[argidx].numdim>0);
 15.2220 -        if (arg[argidx].numdim==1) {
 15.2221 -          append_constval(&arrayszlst,arg[argidx].name,arg[argidx].defvalue.array.arraysize,0);
 15.2222 -        } else {
 15.2223 -          for (level=0; level<arg[argidx].numdim; level++) {
 15.2224 -            assert(level<sDIMEN_MAX);
 15.2225 -            append_constval(&arrayszlst,arg[argidx].name,arg[argidx].dim[level],level);
 15.2226 -          } /* for */
 15.2227 -        } /* if */
 15.2228 -      } else if (arg[argidx].ident==iREFERENCE) {
 15.2229 -        setheap(arg[argidx].defvalue.val);
 15.2230 -        /* address of the value on the heap in PRI */
 15.2231 -        heapalloc++;
 15.2232 -        nest_stkusage++;
 15.2233 -      } else {
 15.2234 -        int dummytag=arg[argidx].tags[0];
 15.2235 -        ldconst(arg[argidx].defvalue.val,sPRI);
 15.2236 -        assert(arg[argidx].numtags>0);
 15.2237 -        check_userop(NULL,arg[argidx].defvalue_tag,arg[argidx].tags[0],2,NULL,&dummytag);
 15.2238 -        assert(dummytag==arg[argidx].tags[0]);
 15.2239 -      } /* if */
 15.2240 -      pushreg(sPRI);            /* store the function argument on the stack */
 15.2241 -      markexpr(sPARM,NULL,0);   /* mark the end of a sub-expression */
 15.2242 -      nest_stkusage++;
 15.2243 -    } else {
 15.2244 -      error(202,argidx);        /* argument count mismatch */
 15.2245 -    } /* if */
 15.2246 -    if (arglist[argidx]==ARG_UNHANDLED)
 15.2247 -      nargs++;
 15.2248 -    arglist[argidx]=ARG_DONE;
 15.2249 -  } /* for */
 15.2250 -  /* now a second loop to catch the arguments with default values that are
 15.2251 -   * the "sizeof" or "tagof" of other arguments
 15.2252 -   */
 15.2253 -  for (argidx=0; arg[argidx].ident!=0 && arg[argidx].ident!=iVARARGS; argidx++) {
 15.2254 -    constvalue *asz;
 15.2255 -    cell array_sz;
 15.2256 -    if (arglist[argidx]==ARG_DONE)
 15.2257 -      continue;                 /* already seen and handled this argument */
 15.2258 -    stgmark((char)(sEXPRSTART+argidx));/* mark beginning of new expression in stage */
 15.2259 -    assert(arg[argidx].ident==iVARIABLE);           /* if "sizeof", must be single cell */
 15.2260 -    /* if unseen, must be "sizeof" or "tagof" */
 15.2261 -    assert((arg[argidx].hasdefault & uSIZEOF)!=0 || (arg[argidx].hasdefault & uTAGOF)!=0);
 15.2262 -    if ((arg[argidx].hasdefault & uSIZEOF)!=0) {
 15.2263 -      /* find the argument; if it isn't found, the argument's default value
 15.2264 -       * was a "sizeof" of a non-array (a warning for this was already given
 15.2265 -       * when declaring the function)
 15.2266 -       */
 15.2267 -      asz=find_constval(&arrayszlst,arg[argidx].defvalue.size.symname,
 15.2268 -                        arg[argidx].defvalue.size.level);
 15.2269 -      if (asz!=NULL) {
 15.2270 -        array_sz=asz->value;
 15.2271 -        if (array_sz==0)
 15.2272 -          error(224,arg[argidx].name);    /* indeterminate array size in "sizeof" expression */
 15.2273 -      } else {
 15.2274 -        array_sz=1;
 15.2275 -      } /* if */
 15.2276 -    } else {
 15.2277 -      asz=find_constval(&taglst,arg[argidx].defvalue.size.symname,
 15.2278 -                        arg[argidx].defvalue.size.level);
 15.2279 -      if (asz != NULL) {
 15.2280 -        exporttag(asz->value);
 15.2281 -        array_sz=asz->value | PUBLICTAG;  /* must be set, because it just was exported */
 15.2282 -      } else {
 15.2283 -        array_sz=0;
 15.2284 -      } /* if */
 15.2285 -    } /* if */
 15.2286 -    ldconst(array_sz,sPRI);
 15.2287 -    pushreg(sPRI);              /* store the function argument on the stack */
 15.2288 -    markexpr(sPARM,NULL,0);
 15.2289 -    nest_stkusage++;
 15.2290 -    if (arglist[argidx]==ARG_UNHANDLED)
 15.2291 -      nargs++;
 15.2292 -    arglist[argidx]=ARG_DONE;
 15.2293 -  } /* for */
 15.2294 -  stgmark(sENDREORDER);         /* mark end of reversed evaluation */
 15.2295 -  pushval((cell)nargs*sizeof(cell));
 15.2296 -  nest_stkusage++;
 15.2297 -  ffcall(sym,NULL,nargs);
 15.2298 -  if (sc_status!=statSKIP)
 15.2299 -    markusage(sym,uREAD);       /* do not mark as "used" when this call itself is skipped */
 15.2300 -  if ((sym->usage & uNATIVE)!=0 &&sym->x.lib!=NULL)
 15.2301 -    sym->x.lib->value += 1;     /* increment "usage count" of the library */
 15.2302 -  modheap(-heapalloc*sizeof(cell));
 15.2303 -  if (symret!=NULL)
 15.2304 -    popreg(sPRI);               /* pop hidden parameter as function result */
 15.2305 -  sideeffect=TRUE;              /* assume functions carry out a side-effect */
 15.2306 -  delete_consttable(&arrayszlst);     /* clear list of array sizes */
 15.2307 -  delete_consttable(&taglst);   /* clear list of parameter tags */
 15.2308 -
 15.2309 -  /* maintain max. amount of memory used */
 15.2310 -  {
 15.2311 -    long totalsize;
 15.2312 -    totalsize=declared+decl_heap+1;   /* local variables & return value size,
 15.2313 -                                       * +1 for PROC opcode */
 15.2314 -    if (lval_result->ident==iREFARRAY)
 15.2315 -      totalsize++;                    /* add hidden parameter (on the stack) */
 15.2316 -    if ((sym->usage & uNATIVE)==0)
 15.2317 -      totalsize++;                    /* add "call" opcode */
 15.2318 -    totalsize+=nest_stkusage;
 15.2319 -    assert(curfunc!=NULL);
 15.2320 -    if (curfunc->x.stacksize<totalsize)
 15.2321 -      curfunc->x.stacksize=totalsize;
 15.2322 -    nest_stkusage-=nargs+heapalloc+1; /* stack/heap space, +1 for argcount param */
 15.2323 -    /* if there is a syntax error in the script, the stack calculation is
 15.2324 -     * probably incorrect; but we may not allow it to drop below zero
 15.2325 -     */
 15.2326 -    if (nest_stkusage<0)
 15.2327 -      nest_stkusage=0;
 15.2328 -  }
 15.2329 -
 15.2330 -  /* scrap any arrays left on the heap, with the exception of the array that
 15.2331 -   * this function has as a result (in other words, scrap all arrays on the
 15.2332 -   * heap that caused by expressions in the function arguments)
 15.2333 -   */
 15.2334 -  assert(decl_heap>=locheap);
 15.2335 -  modheap((locheap-decl_heap)*sizeof(cell));  /* remove heap space, so negative delta */
 15.2336 -  decl_heap=locheap;
 15.2337 -  nesting--;
 15.2338 -}
 15.2339 -
 15.2340 -/*  dbltest
 15.2341 - *
 15.2342 - *  Returns a non-zero value if lval1 an array and lval2 is not an array and
 15.2343 - *  the operation is addition or subtraction.
 15.2344 - *
 15.2345 - *  Returns the "shift" count (1 for 16-bit, 2 for 32-bit) to align a cell
 15.2346 - *  to an array offset.
 15.2347 - */
 15.2348 -static int dbltest(void (*oper)(),value *lval1,value *lval2)
 15.2349 -{
 15.2350 -  if ((oper!=ob_add) && (oper!=ob_sub))
 15.2351 -    return 0;
 15.2352 -  if (lval1->ident!=iARRAY)
 15.2353 -    return 0;
 15.2354 -  if (lval2->ident==iARRAY)
 15.2355 -    return 0;
 15.2356 -  return sizeof(cell)/2;        /* 1 for 16-bit, 2 for 32-bit */
 15.2357 -}
 15.2358 -
 15.2359 -/*  commutative
 15.2360 - *
 15.2361 - *  Test whether an operator is commutative, i.e. x oper y == y oper x.
 15.2362 - *  Commutative operators are: +  (addition)
 15.2363 - *                             *  (multiplication)
 15.2364 - *                             == (equality)
 15.2365 - *                             != (inequality)
 15.2366 - *                             &  (bitwise and)
 15.2367 - *                             ^  (bitwise xor)
 15.2368 - *                             |  (bitwise or)
 15.2369 - *
 15.2370 - *  If in an expression, code for the left operand has been generated and
 15.2371 - *  the right operand is a constant and the operator is commutative, the
 15.2372 - *  precautionary "push" of the primary register is scrapped and the constant
 15.2373 - *  is read into the secondary register immediately.
 15.2374 - */
 15.2375 -static int commutative(void (*oper)())
 15.2376 -{
 15.2377 -  return oper==ob_add || oper==os_mult
 15.2378 -         || oper==ob_eq || oper==ob_ne
 15.2379 -         || oper==ob_and || oper==ob_xor || oper==ob_or;
 15.2380 -}
 15.2381 -
 15.2382 -/*  constant
 15.2383 - *
 15.2384 - *  Generates code to fetch a number, a literal character (which is returned
 15.2385 - *  by lex() as a number as well) or a literal string (lex() stores the
 15.2386 - *  strings in the literal queue). If the operand was a number, it is stored
 15.2387 - *  in lval->constval.
 15.2388 - *
 15.2389 - *  The function returns 1 if the token was a constant or a string, 0
 15.2390 - *  otherwise.
 15.2391 - */
 15.2392 -static int constant(value *lval)
 15.2393 -{
 15.2394 -  int tok,index,ident;
 15.2395 -  cell val,item,cidx;
 15.2396 -  char *st;
 15.2397 -  symbol *sym;
 15.2398 -  int cmptag=lval->cmptag;
 15.2399 -
 15.2400 -  tok=lex(&val,&st);
 15.2401 -  if (tok==tSYMBOL && (sym=findconst(st,&cmptag))!=0) {
 15.2402 -    if (cmptag>1)
 15.2403 -      error(91,sym->name);  /* ambiguity: multiple matching constants (different tags) */
 15.2404 -    lval->constval=sym->addr;
 15.2405 -    ldconst(lval->constval,sPRI);
 15.2406 -    lval->ident=iCONSTEXPR;
 15.2407 -    lval->tag=sym->tag;
 15.2408 -    lval->sym=sym;
 15.2409 -    markusage(sym,uREAD);
 15.2410 -  } else if (tok==tNUMBER) {
 15.2411 -    lval->constval=val;
 15.2412 -    ldconst(lval->constval,sPRI);
 15.2413 -    lval->ident=iCONSTEXPR;
 15.2414 -  } else if (tok==tRATIONAL) {
 15.2415 -    lval->constval=val;
 15.2416 -    ldconst(lval->constval,sPRI);
 15.2417 -    lval->ident=iCONSTEXPR;
 15.2418 -    lval->tag=sc_rationaltag;
 15.2419 -  } else if (tok==tSTRING) {
 15.2420 -    /* lex() stores starting index of string in the literal table in 'val' */
 15.2421 -    ldconst((val+glb_declared)*sizeof(cell),sPRI);
 15.2422 -    lval->ident=iARRAY;         /* pretend this is a global array */
 15.2423 -    lval->constval=val-litidx;  /* constval == the negative value of the
 15.2424 -                                 * size of the literal array; using a negative
 15.2425 -                                 * value distinguishes between literal arrays
 15.2426 -                                 * and literal strings (this was done for
 15.2427 -                                 * array assignment). */
 15.2428 -  } else if (tok=='{') {
 15.2429 -    int tag,lasttag=-1;
 15.2430 -    val=litidx;
 15.2431 -    do {
 15.2432 -      /* cannot call constexpr() here, because "staging" is already turned
 15.2433 -       * on at this point */
 15.2434 -      assert(staging);
 15.2435 -      stgget(&index,&cidx);     /* mark position in code generator */
 15.2436 -      ident=expression(&item,&tag,NULL,FALSE);
 15.2437 -      stgdel(index,cidx);       /* scratch generated code */
 15.2438 -      if (ident!=iCONSTEXPR)
 15.2439 -        error(8);               /* must be constant expression */
 15.2440 -      if (lasttag<0)
 15.2441 -        lasttag=tag;
 15.2442 -      else if (!matchtag(lasttag,tag,FALSE))
 15.2443 -        error(213);             /* tagname mismatch */
 15.2444 -      litadd(item);             /* store expression result in literal table */
 15.2445 -    } while (matchtoken(','));
 15.2446 -    if (!needtoken('}'))
 15.2447 -      lexclr(FALSE);
 15.2448 -    ldconst((val+glb_declared)*sizeof(cell),sPRI);
 15.2449 -    lval->ident=iARRAY;         /* pretend this is a global array */
 15.2450 -    lval->constval=litidx-val;  /* constval == the size of the literal array */
 15.2451 -  } else {
 15.2452 -    return FALSE;               /* no, it cannot be interpreted as a constant */
 15.2453 -  } /* if */
 15.2454 -  return TRUE;                  /* yes, it was a constant value */
 15.2455 -}
 15.2456 -
    16.1 --- a/compiler-init/sc4.c	Sat Jul 15 01:36:48 2006 +0000
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,1331 +0,0 @@
    16.4 -/*  Pawn compiler - code generation (unoptimized "assembler" code)
    16.5 - *
    16.6 - *  Copyright (c) ITB CompuPhase, 1997-2006
    16.7 - *
    16.8 - *  This software is provided "as-is", without any express or implied warranty.
    16.9 - *  In no event will the authors be held liable for any damages arising from
   16.10 - *  the use of this software.
   16.11 - *
   16.12 - *  Permission is granted to anyone to use this software for any purpose,
   16.13 - *  including commercial applications, and to alter it and redistribute it
   16.14 - *  freely, subject to the following restrictions:
   16.15 - *
   16.16 - *  1.  The origin of this software must not be misrepresented; you must not
   16.17 - *      claim that you wrote the original software. If you use this software in
   16.18 - *      a product, an acknowledgment in the product documentation would be
   16.19 - *      appreciated but is not required.
   16.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
   16.21 - *      misrepresented as being the original software.
   16.22 - *  3.  This notice may not be removed or altered from any source distribution.
   16.23 - *
   16.24 - *  Version: $Id: sc4.c 3579 2006-06-06 13:35:29Z thiadmer $
   16.25 - */
   16.26 -#include <assert.h>
   16.27 -#include <ctype.h>
   16.28 -#include <stdio.h>
   16.29 -#include <stdlib.h>     /* for _MAX_PATH */
   16.30 -#include <string.h>
   16.31 -#if defined FORTIFY
   16.32 -  #include <alloc/fortify.h>
   16.33 -#endif
   16.34 -#include "sc.h"
   16.35 -
   16.36 -static int fcurseg;     /* the file number (fcurrent) for the active segment */
   16.37 -
   16.38 -
   16.39 -/* When a subroutine returns to address 0, the AMX must halt. In earlier
   16.40 - * releases, the RET and RETN opcodes checked for the special case 0 address.
   16.41 - * Today, the compiler simply generates a HALT instruction at address 0. So
   16.42 - * a subroutine can savely return to 0, and then encounter a HALT.
   16.43 - */
   16.44 -SC_FUNC void writeleader(symbol *root)
   16.45 -{
   16.46 -  int lbl_nostate,lbl_table;
   16.47 -  int statecount;
   16.48 -  symbol *sym;
   16.49 -  constvalue *fsa, *state, *stlist;
   16.50 -  int fsa_id,listid;
   16.51 -  char lbl_default[sNAMEMAX+1];
   16.52 -
   16.53 -  assert(code_idx==0);
   16.54 -
   16.55 -  begcseg();
   16.56 -  stgwrite(";program exit point\n");
   16.57 -  stgwrite("\thalt 0\n\n");
   16.58 -  code_idx+=opcodes(1)+opargs(1);       /* calculate code length */
   16.59 -
   16.60 -  /* check whether there are any functions that have states */
   16.61 -  for (sym=root->next; sym!=NULL; sym=sym->next)
   16.62 -    if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL)
   16.63 -      break;
   16.64 -  if (sym==NULL)
   16.65 -    return;             /* no function has states, nothing to do next */
   16.66 -
   16.67 -  /* generate an error function that is called for an undefined state */
   16.68 -  stgwrite("\n;exit point for functions called from the wrong state\n");
   16.69 -  lbl_nostate=getlabel();
   16.70 -  setlabel(lbl_nostate);
   16.71 -  stgwrite("\thalt ");
   16.72 -  outval(AMX_ERR_INVSTATE,TRUE);
   16.73 -  code_idx+=opcodes(1)+opargs(1);       /* calculate code length */
   16.74 -
   16.75 -  /* write the "state-selectors" table with all automatons (update the
   16.76 -   * automatons structure too, as we are now assigning the address to
   16.77 -   * each automaton state-selector variable)
   16.78 -   */
   16.79 -  assert(glb_declared==0);
   16.80 -  begdseg();
   16.81 -  for (fsa=sc_automaton_tab.next; fsa!=NULL; fsa=fsa->next) {
   16.82 -    defstorage();
   16.83 -    stgwrite("0\t; automaton ");
   16.84 -    if (strlen(fsa->name)==0)
   16.85 -      stgwrite("(anonymous)");
   16.86 -    else
   16.87 -      stgwrite(fsa->name);
   16.88 -    stgwrite("\n");
   16.89 -    fsa->value=glb_declared*sizeof(cell);
   16.90 -    glb_declared++;
   16.91 -  } /* for */
   16.92 -
   16.93 -  /* write stubs and jump tables for all state functions */
   16.94 -  begcseg();
   16.95 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
   16.96 -    if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) {
   16.97 -      stlist=sym->states->next;
   16.98 -      assert(stlist!=NULL);     /* there should be at least one state item */
   16.99 -      listid=stlist->index;
  16.100 -      assert(listid==-1 || listid>0);
  16.101 -      if (listid==-1 && stlist->next!=NULL) {
  16.102 -        /* first index is the "fallback", take the next one (if available) */
  16.103 -        stlist=stlist->next;
  16.104 -        listid=stlist->index;
  16.105 -      } /* if */
  16.106 -      if (listid==-1) {
  16.107 -        /* first index is the fallback, there is no second... */
  16.108 -        strcpy(stlist->name,"0"); /* insert dummy label number */
  16.109 -        /* this is an error, but we postpone adding the error message until the
  16.110 -         * function definition
  16.111 -         */
  16.112 -        continue;
  16.113 -      } /* if */
  16.114 -      /* generate label numbers for all statelist ids */
  16.115 -      for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) {
  16.116 -        assert(strlen(stlist->name)==0);
  16.117 -        strcpy(stlist->name,itoh(getlabel()));
  16.118 -      } /* for */
  16.119 -      if (strcmp(sym->name,uENTRYFUNC)==0)
  16.120 -        continue;               /* do not generate stubs for this special function */
  16.121 -      sym->addr=code_idx;       /* fix the function address now */
  16.122 -      /* get automaton id for this function */
  16.123 -      assert(listid>0);
  16.124 -      fsa_id=state_getfsa(listid);
  16.125 -      assert(fsa_id>=0);        /* automaton 0 exists */
  16.126 -      fsa=automaton_findid(fsa_id);
  16.127 -      /* count the number of states actually used; at the sane time, check
  16.128 -       * whether there is a default state function
  16.129 -       */
  16.130 -      statecount=0;
  16.131 -      strcpy(lbl_default,itoh(lbl_nostate));
  16.132 -      for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) {
  16.133 -        if (stlist->index==-1) {
  16.134 -          assert(strlen(stlist->name)<sizeof lbl_default);
  16.135 -          strcpy(lbl_default,stlist->name);
  16.136 -        } else {
  16.137 -          statecount+=state_count(stlist->index);
  16.138 -        } /* if */
  16.139 -      } /* for */
  16.140 -      /* generate a stub entry for the functions */
  16.141 -      stgwrite("\tload.pri ");
  16.142 -      outval(fsa->value,FALSE);
  16.143 -      stgwrite("\t; ");
  16.144 -      stgwrite(sym->name);
  16.145 -      stgwrite("\n");
  16.146 -      code_idx+=opcodes(1)+opargs(1);   /* calculate code length */
  16.147 -      lbl_table=getlabel();
  16.148 -      ffswitch(lbl_table);
  16.149 -      /* generate the jump table */
  16.150 -      setlabel(lbl_table);
  16.151 -      ffcase(statecount,lbl_default,TRUE);
  16.152 -      for (state=sc_state_tab.next; state!=NULL; state=state->next) {
  16.153 -        if (state->index==fsa_id) {
  16.154 -          /* find the label for this list id */
  16.155 -          for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) {
  16.156 -            if (stlist->index!=-1 && state_inlist(stlist->index,(int)state->value)) {
  16.157 -              ffcase(state->value,stlist->name,FALSE);
  16.158 -              break;
  16.159 -            } /* if */
  16.160 -          } /* for */
  16.161 -          if (stlist==NULL && strtol(lbl_default,NULL,16)==lbl_nostate)
  16.162 -            error(230,state->name,sym->name);  /* unimplemented state, no fallback */
  16.163 -        } /* if (state belongs to automaton of function) */
  16.164 -      } /* for (state) */
  16.165 -      stgwrite("\n");
  16.166 -    } /* if (is function, used & having states) */
  16.167 -  } /* for (sym) */
  16.168 -}
  16.169 -
  16.170 -/*  writetrailer
  16.171 - *  Not much left of this once important function.
  16.172 - *
  16.173 - *  Global references: pc_stksize       (referred to only)
  16.174 - *                     sc_dataalign     (referred to only)
  16.175 - *                     code_idx         (altered)
  16.176 - *                     glb_declared     (altered)
  16.177 - */
  16.178 -SC_FUNC void writetrailer(void)
  16.179 -{
  16.180 -  assert(sc_dataalign % opcodes(1) == 0);   /* alignment must be a multiple of
  16.181 -                                             * the opcode size */
  16.182 -  assert(sc_dataalign!=0);
  16.183 -
  16.184 -  /* pad code to align data segment */
  16.185 -  if ((code_idx % sc_dataalign)!=0) {
  16.186 -    begcseg();
  16.187 -    while ((code_idx % sc_dataalign)!=0)
  16.188 -      nooperation();
  16.189 -  } /* if */
  16.190 -
  16.191 -  /* pad data segment to align the stack and the heap */
  16.192 -  assert(litidx==0);            /* literal queue should have been emptied */
  16.193 -  assert(sc_dataalign % sizeof(cell) == 0);
  16.194 -  if (((glb_declared*sizeof(cell)) % sc_dataalign)!=0) {
  16.195 -    begdseg();
  16.196 -    defstorage();
  16.197 -    while (((glb_declared*sizeof(cell)) % sc_dataalign)!=0) {
  16.198 -      stgwrite("0 ");
  16.199 -      glb_declared++;
  16.200 -    } /* while */
  16.201 -  } /* if */
  16.202 -
  16.203 -  stgwrite("\nSTKSIZE ");       /* write stack size (align stack top) */
  16.204 -  outval(pc_stksize - (pc_stksize % sc_dataalign), TRUE);
  16.205 -}
  16.206 -
  16.207 -/*
  16.208 - *  Start (or restart) the CODE segment.
  16.209 - *
  16.210 - *  In fact, the code and data segment specifiers are purely informational;
  16.211 - *  the "DUMP" instruction itself already specifies that the following values
  16.212 - *  should go to the data segment. All other instructions go to the code
  16.213 - *  segment.
  16.214 - *
  16.215 - *  Global references: curseg
  16.216 - *                     fcurrent
  16.217 - */
  16.218 -SC_FUNC void begcseg(void)
  16.219 -{
  16.220 -  if (curseg!=sIN_CSEG || fcurrent!=fcurseg) {
  16.221 -    stgwrite("\n");
  16.222 -    stgwrite("CODE ");
  16.223 -    outval(fcurrent,FALSE);
  16.224 -    stgwrite("\t; ");
  16.225 -    outval(code_idx,TRUE);
  16.226 -    curseg=sIN_CSEG;
  16.227 -    fcurseg=fcurrent;
  16.228 -  } /* endif */
  16.229 -}
  16.230 -
  16.231 -/*
  16.232 - *  Start (or restart) the DATA segment.
  16.233 - *
  16.234 - *  Global references: curseg
  16.235 - */
  16.236 -SC_FUNC void begdseg(void)
  16.237 -{
  16.238 -  if (curseg!=sIN_DSEG || fcurrent!=fcurseg) {
  16.239 -    stgwrite("\n");
  16.240 -    stgwrite("DATA ");
  16.241 -    outval(fcurrent,FALSE);
  16.242 -    stgwrite("\t; ");
  16.243 -    outval((glb_declared-litidx)*sizeof(cell),TRUE);
  16.244 -    curseg=sIN_DSEG;
  16.245 -    fcurseg=fcurrent;
  16.246 -  } /* if */
  16.247 -}
  16.248 -
  16.249 -SC_FUNC void setline(int chkbounds)
  16.250 -{
  16.251 -  if ((sc_debug & sSYMBOLIC)!=0 || chkbounds && (sc_debug & sCHKBOUNDS)!=0) {
  16.252 -    /* generate a "break" (start statement) opcode rather than a "line" opcode
  16.253 -     * because earlier versions of Small/Pawn have an incompatible version of the
  16.254 -     * line opcode
  16.255 -     */
  16.256 -    stgwrite("\tbreak\t; ");
  16.257 -    outval(code_idx,TRUE);
  16.258 -    code_idx+=opcodes(1);
  16.259 -  } /* if */
  16.260 -}
  16.261 -
  16.262 -SC_FUNC void setfiledirect(char *name)
  16.263 -{
  16.264 -  if (sc_status==statFIRST && sc_listing) {
  16.265 -    assert(name!=NULL);
  16.266 -    pc_writeasm(outf,"#file ");
  16.267 -    pc_writeasm(outf,name);
  16.268 -    pc_writeasm(outf,"\n");
  16.269 -  } /* if */
  16.270 -}
  16.271 -
  16.272 -SC_FUNC void setlinedirect(int line)
  16.273 -{
  16.274 -  if (sc_status==statFIRST && sc_listing) {
  16.275 -    char string[40];
  16.276 -    sprintf(string,"#line %d\n",line);
  16.277 -    pc_writeasm(outf,string);
  16.278 -  } /* if */
  16.279 -}
  16.280 -
  16.281 -/*  setlabel
  16.282 - *
  16.283 - *  Post a code label (specified as a number), on a new line.
  16.284 - */
  16.285 -SC_FUNC void setlabel(int number)
  16.286 -{
  16.287 -  assert(number>=0);
  16.288 -  stgwrite("l.");
  16.289 -  stgwrite((char *)itoh(number));
  16.290 -  /* To assist verification of the assembled code, put the address of the
  16.291 -   * label as a comment. However, labels that occur inside an expression
  16.292 -   * may move (through optimization or through re-ordering). So write the
  16.293 -   * address only if it is known to accurate.
  16.294 -   */
  16.295 -  if (!staging) {
  16.296 -    stgwrite("\t\t; ");
  16.297 -    outval(code_idx,FALSE);
  16.298 -  } /* if */
  16.299 -  stgwrite("\n");
  16.300 -}
  16.301 -
  16.302 -/* Write a token that signifies the start or end of an expression or special
  16.303 - * statement. This allows several simple optimizations by the peephole
  16.304 - * optimizer.
  16.305 - */
  16.306 -SC_FUNC void markexpr(optmark type,const char *name,cell offset)
  16.307 -{
  16.308 -  switch (type) {
  16.309 -  case sEXPR:
  16.310 -    stgwrite("\t;$exp\n");
  16.311 -    break;
  16.312 -  case sPARM:
  16.313 -    stgwrite("\t;$par\n");
  16.314 -    break;
  16.315 -  case sLDECL:
  16.316 -    assert(name!=NULL);
  16.317 -    stgwrite("\t;$lcl ");
  16.318 -    stgwrite(name);
  16.319 -    stgwrite(" ");
  16.320 -    outval(offset,TRUE);
  16.321 -    break;
  16.322 -  default:
  16.323 -    assert(0);
  16.324 -  } /* switch */
  16.325 -}
  16.326 -
  16.327 -/*  startfunc   - declare a CODE entry point (function start)
  16.328 - *
  16.329 - *  Global references: funcstatus  (referred to only)
  16.330 - */
  16.331 -SC_FUNC void startfunc(char *fname)
  16.332 -{
  16.333 -  stgwrite("\tproc");
  16.334 -  if (sc_asmfile) {
  16.335 -    char symname[2*sNAMEMAX+16];
  16.336 -    funcdisplayname(symname,fname);
  16.337 -    stgwrite("\t; ");
  16.338 -    stgwrite(symname);
  16.339 -  } /* if */
  16.340 -  stgwrite("\n");
  16.341 -  code_idx+=opcodes(1);
  16.342 -}
  16.343 -
  16.344 -/*  endfunc
  16.345 - *
  16.346 - *  Declare a CODE ending point (function end)
  16.347 - */
  16.348 -SC_FUNC void endfunc(void)
  16.349 -{
  16.350 -  stgwrite("\n");       /* skip a line */
  16.351 -}
  16.352 -
  16.353 -/*  alignframe
  16.354 - *
  16.355 - *  Aligns the frame (and the stack) of the current function to a multiple
  16.356 - *  of the specified byte count. Two caveats: the alignment ("numbytes") should
  16.357 - *  be a power of 2, and this alignment must be done right after the frame
  16.358 - *  is set up (before the first variable is declared)
  16.359 - */
  16.360 -SC_FUNC void alignframe(int numbytes)
  16.361 -{
  16.362 -  #if !defined NDEBUG
  16.363 -    /* "numbytes" should be a power of 2 for this code to work */
  16.364 -    int i,count=0;
  16.365 -    for (i=0; i<sizeof numbytes*8; i++)
  16.366 -      if (numbytes & (1 << i))
  16.367 -        count++;
  16.368 -    assert(count==1);
  16.369 -  #endif
  16.370 -
  16.371 -  stgwrite("\tlctrl 4\n");      /* get STK in PRI */
  16.372 -  stgwrite("\tconst.alt ");     /* get ~(numbytes-1) in ALT */
  16.373 -  outval(~(numbytes-1),TRUE);
  16.374 -  stgwrite("\tand\n");          /* PRI = STK "and" ~(numbytes-1) */
  16.375 -  stgwrite("\tsctrl 4\n");      /* set the new value of STK ... */
  16.376 -  stgwrite("\tsctrl 5\n");      /* ... and FRM */
  16.377 -  code_idx+=opcodes(5)+opargs(4);
  16.378 -}
  16.379 -
  16.380 -/*  rvalue
  16.381 - *
  16.382 - *  Generate code to get the value of a symbol into "primary".
  16.383 - */
  16.384 -SC_FUNC void rvalue(value *lval)
  16.385 -{
  16.386 -  symbol *sym;
  16.387 -
  16.388 -  sym=lval->sym;
  16.389 -  if (lval->ident==iARRAYCELL) {
  16.390 -    /* indirect fetch, address already in PRI */
  16.391 -    stgwrite("\tload.i\n");
  16.392 -    code_idx+=opcodes(1);
  16.393 -  } else if (lval->ident==iARRAYCHAR) {
  16.394 -    /* indirect fetch of a character from a pack, address already in PRI */
  16.395 -    stgwrite("\tlodb.i ");
  16.396 -    outval(sCHARBITS/8,TRUE);   /* read one or two bytes */
  16.397 -    code_idx+=opcodes(1)+opargs(1);
  16.398 -  } else if (lval->ident==iREFERENCE) {
  16.399 -    /* indirect fetch, but address not yet in PRI */
  16.400 -    assert(sym!=NULL);
  16.401 -    assert(sym->vclass==sLOCAL);/* global references don't exist in Pawn */
  16.402 -    if (sym->vclass==sLOCAL)
  16.403 -      stgwrite("\tlref.s.pri ");
  16.404 -    else
  16.405 -      stgwrite("\tlref.pri ");
  16.406 -    outval(sym->addr,TRUE);
  16.407 -    markusage(sym,uREAD);
  16.408 -    code_idx+=opcodes(1)+opargs(1);
  16.409 -  } else {
  16.410 -    /* direct or stack relative fetch */
  16.411 -    assert(sym!=NULL);
  16.412 -    if (sym->vclass==sLOCAL)
  16.413 -      stgwrite("\tload.s.pri ");
  16.414 -    else
  16.415 -      stgwrite("\tload.pri ");
  16.416 -    outval(sym->addr,TRUE);
  16.417 -    markusage(sym,uREAD);
  16.418 -    code_idx+=opcodes(1)+opargs(1);
  16.419 -  } /* if */
  16.420 -}
  16.421 -
  16.422 -/* Get the address of a symbol into the primary or alternate register (used
  16.423 - * for arrays, and for passing arguments by reference).
  16.424 - */
  16.425 -SC_FUNC void address(symbol *sym,regid reg)
  16.426 -{
  16.427 -  assert(sym!=NULL);
  16.428 -  assert(reg==sPRI || reg==sALT);
  16.429 -  /* the symbol can be a local array, a global array, or an array
  16.430 -   * that is passed by reference.
  16.431 -   */
  16.432 -  if (sym->ident==iREFARRAY || sym->ident==iREFERENCE) {
  16.433 -    /* reference to a variable or to an array; currently this is
  16.434 -     * always a local variable */
  16.435 -    switch (reg) {
  16.436 -    case sPRI:
  16.437 -      stgwrite("\tload.s.pri ");
  16.438 -      break;
  16.439 -    case sALT:
  16.440 -      stgwrite("\tload.s.alt ");
  16.441 -      break;
  16.442 -    } /* switch */
  16.443 -  } else {
  16.444 -    /* a local array or local variable */
  16.445 -    switch (reg) {
  16.446 -    case sPRI:
  16.447 -      if (sym->vclass==sLOCAL)
  16.448 -        stgwrite("\taddr.pri ");
  16.449 -      else
  16.450 -        stgwrite("\tconst.pri ");
  16.451 -      break;
  16.452 -    case sALT:
  16.453 -      if (sym->vclass==sLOCAL)
  16.454 -        stgwrite("\taddr.alt ");
  16.455 -      else
  16.456 -        stgwrite("\tconst.alt ");
  16.457 -      break;
  16.458 -    } /* switch */
  16.459 -  } /* if */
  16.460 -  outval(sym->addr,TRUE);
  16.461 -  markusage(sym,uREAD);
  16.462 -  code_idx+=opcodes(1)+opargs(1);
  16.463 -}
  16.464 -
  16.465 -/*  store
  16.466 - *
  16.467 - *  Saves the contents of "primary" into a memory cell, either directly
  16.468 - *  or indirectly (at the address given in the alternate register).
  16.469 - */
  16.470 -SC_FUNC void store(value *lval)
  16.471 -{
  16.472 -  symbol *sym;
  16.473 -
  16.474 -  sym=lval->sym;
  16.475 -  if (lval->ident==iARRAYCELL) {
  16.476 -    /* store at address in ALT */
  16.477 -    stgwrite("\tstor.i\n");
  16.478 -    code_idx+=opcodes(1);
  16.479 -  } else if (lval->ident==iARRAYCHAR) {
  16.480 -    /* store at address in ALT */
  16.481 -    stgwrite("\tstrb.i ");
  16.482 -    outval(sCHARBITS/8,TRUE);   /* write one or two bytes */
  16.483 -    code_idx+=opcodes(1)+opargs(1);
  16.484 -  } else if (lval->ident==iREFERENCE) {
  16.485 -    assert(sym!=NULL);
  16.486 -    if (sym->vclass==sLOCAL)
  16.487 -      stgwrite("\tsref.s.pri ");
  16.488 -    else
  16.489 -      stgwrite("\tsref.pri ");
  16.490 -    outval(sym->addr,TRUE);
  16.491 -    code_idx+=opcodes(1)+opargs(1);
  16.492 -  } else {
  16.493 -    assert(sym!=NULL);
  16.494 -    markusage(sym,uWRITTEN);
  16.495 -    if (sym->vclass==sLOCAL)
  16.496 -      stgwrite("\tstor.s.pri ");
  16.497 -    else
  16.498 -      stgwrite("\tstor.pri ");
  16.499 -    outval(sym->addr,TRUE);
  16.500 -    code_idx+=opcodes(1)+opargs(1);
  16.501 -  } /* if */
  16.502 -}
  16.503 -
  16.504 -/* Get a cell from a fixed address in memory */
  16.505 -SC_FUNC void loadreg(cell address,regid reg)
  16.506 -{
  16.507 -  assert(reg==sPRI || reg==sALT);
  16.508 -  if (reg==sPRI)
  16.509 -    stgwrite("\tload.pri ");
  16.510 -  else
  16.511 -    stgwrite("\tload.alt ");
  16.512 -  outval(address,TRUE);
  16.513 -  code_idx+=opcodes(1)+opargs(1);
  16.514 -}
  16.515 -
  16.516 -/* Store a cell into a fixed address in memory */
  16.517 -SC_FUNC void storereg(cell address,regid reg)
  16.518 -{
  16.519 -  assert(reg==sPRI || reg==sALT);
  16.520 -  if (reg==sPRI)
  16.521 -    stgwrite("\tstor.pri ");
  16.522 -  else
  16.523 -    stgwrite("\tstor.alt ");
  16.524 -  outval(address,TRUE);
  16.525 -  code_idx+=opcodes(1)+opargs(1);
  16.526 -}
  16.527 -
  16.528 -/* source must in PRI, destination address in ALT. The "size"
  16.529 - * parameter is in bytes, not cells.
  16.530 - */
  16.531 -SC_FUNC void memcopy(cell size)
  16.532 -{
  16.533 -  stgwrite("\tmovs ");
  16.534 -  outval(size,TRUE);
  16.535 -
  16.536 -  code_idx+=opcodes(1)+opargs(1);
  16.537 -}
  16.538 -
  16.539 -/* Address of the source must already have been loaded in PRI
  16.540 - * "size" is the size in bytes (not cells).
  16.541 - */
  16.542 -SC_FUNC void copyarray(symbol *sym,cell size)
  16.543 -{
  16.544 -  assert(sym!=NULL);
  16.545 -  /* the symbol can be a local array, a global array, or an array
  16.546 -   * that is passed by reference.
  16.547 -   */
  16.548 -  if (sym->ident==iREFARRAY) {
  16.549 -    /* reference to an array; currently this is always a local variable */
  16.550 -    assert(sym->vclass==sLOCAL);        /* symbol must be stack relative */
  16.551 -    stgwrite("\tload.s.alt ");
  16.552 -  } else {
  16.553 -    /* a local or global array */
  16.554 -    if (sym->vclass==sLOCAL)
  16.555 -      stgwrite("\taddr.alt ");
  16.556 -    else
  16.557 -      stgwrite("\tconst.alt ");
  16.558 -  } /* if */
  16.559 -  outval(sym->addr,TRUE);
  16.560 -  markusage(sym,uWRITTEN);
  16.561 -
  16.562 -  code_idx+=opcodes(1)+opargs(1);
  16.563 -  memcopy(size);
  16.564 -}
  16.565 -
  16.566 -SC_FUNC void fillarray(symbol *sym,cell size,cell value)
  16.567 -{
  16.568 -  ldconst(value,sPRI);  /* load value in PRI */
  16.569 -
  16.570 -  assert(sym!=NULL);
  16.571 -  /* the symbol can be a local array, a global array, or an array
  16.572 -   * that is passed by reference.
  16.573 -   */
  16.574 -  if (sym->ident==iREFARRAY) {
  16.575 -    /* reference to an array; currently this is always a local variable */
  16.576 -    assert(sym->vclass==sLOCAL);        /* symbol must be stack relative */
  16.577 -    stgwrite("\tload.s.alt ");
  16.578 -  } else {
  16.579 -    /* a local or global array */
  16.580 -    if (sym->vclass==sLOCAL)
  16.581 -      stgwrite("\taddr.alt ");
  16.582 -    else
  16.583 -      stgwrite("\tconst.alt ");
  16.584 -  } /* if */
  16.585 -  outval(sym->addr,TRUE);
  16.586 -  markusage(sym,uWRITTEN);
  16.587 -
  16.588 -  assert(size>0);
  16.589 -  stgwrite("\tfill ");
  16.590 -  outval(size,TRUE);
  16.591 -
  16.592 -  code_idx+=opcodes(2)+opargs(2);
  16.593 -}
  16.594 -
  16.595 -/* Instruction to get an immediate value into the primary or the alternate
  16.596 - * register
  16.597 - */
  16.598 -SC_FUNC void ldconst(cell val,regid reg)
  16.599 -{
  16.600 -  assert(reg==sPRI || reg==sALT);
  16.601 -  switch (reg) {
  16.602 -  case sPRI:
  16.603 -    if (val==0) {
  16.604 -      stgwrite("\tzero.pri\n");
  16.605 -      code_idx+=opcodes(1);
  16.606 -    } else {
  16.607 -      stgwrite("\tconst.pri ");
  16.608 -      outval(val, TRUE);
  16.609 -      code_idx+=opcodes(1)+opargs(1);
  16.610 -    } /* if */
  16.611 -    break;
  16.612 -  case sALT:
  16.613 -    if (val==0) {
  16.614 -      stgwrite("\tzero.alt\n");
  16.615 -      code_idx+=opcodes(1);
  16.616 -    } else {
  16.617 -      stgwrite("\tconst.alt ");
  16.618 -      outval(val, TRUE);
  16.619 -      code_idx+=opcodes(1)+opargs(1);
  16.620 -    } /* if */
  16.621 -    break;
  16.622 -  } /* switch */
  16.623 -}
  16.624 -
  16.625 -/* Copy value in alternate register to the primary register */
  16.626 -SC_FUNC void moveto1(void)
  16.627 -{
  16.628 -  stgwrite("\tmove.pri\n");
  16.629 -  code_idx+=opcodes(1)+opargs(0);
  16.630 -}
  16.631 -
  16.632 -/* Push primary or the alternate register onto the stack
  16.633 - */
  16.634 -SC_FUNC void pushreg(regid reg)
  16.635 -{
  16.636 -  assert(reg==sPRI || reg==sALT);
  16.637 -  switch (reg) {
  16.638 -  case sPRI:
  16.639 -    stgwrite("\tpush.pri\n");
  16.640 -    break;
  16.641 -  case sALT:
  16.642 -    stgwrite("\tpush.alt\n");
  16.643 -    break;
  16.644 -  } /* switch */
  16.645 -  code_idx+=opcodes(1);
  16.646 -}
  16.647 -
  16.648 -/*
  16.649 - *  Push a constant value onto the stack
  16.650 - */
  16.651 -SC_FUNC void pushval(cell val)
  16.652 -{
  16.653 -  stgwrite("\tpush.c ");
  16.654 -  outval(val, TRUE);
  16.655 -  code_idx+=opcodes(1)+opargs(1);
  16.656 -}
  16.657 -
  16.658 -/* Pop stack into the primary or the alternate register
  16.659 - */
  16.660 -SC_FUNC void popreg(regid reg)
  16.661 -{
  16.662 -  assert(reg==sPRI || reg==sALT);
  16.663 -  switch (reg) {
  16.664 -  case sPRI:
  16.665 -    stgwrite("\tpop.pri\n");
  16.666 -    break;
  16.667 -  case sALT:
  16.668 -    stgwrite("\tpop.alt\n");
  16.669 -    break;
  16.670 -  } /* switch */
  16.671 -  code_idx+=opcodes(1);
  16.672 -}
  16.673 -
  16.674 -/*
  16.675 - *  swap the top-of-stack with the value in primary register
  16.676 - */
  16.677 -SC_FUNC void swap1(void)
  16.678 -{
  16.679 -  stgwrite("\tswap.pri\n");
  16.680 -  code_idx+=opcodes(1);
  16.681 -}
  16.682 -
  16.683 -/* Switch statements
  16.684 - * The "switch" statement generates a "case" table using the "CASE" opcode.
  16.685 - * The case table contains a list of records, each record holds a comparison
  16.686 - * value and a label to branch to on a match. The very first record is an
  16.687 - * exception: it holds the size of the table (excluding the first record) and
  16.688 - * the label to branch to when none of the values in the case table match.
  16.689 - * The case table is sorted on the comparison value. This allows more advanced
  16.690 - * abstract machines to sift the case table with a binary search.
  16.691 - */
  16.692 -SC_FUNC void ffswitch(int label)
  16.693 -{
  16.694 -  stgwrite("\tswitch ");
  16.695 -  outval(label,TRUE);           /* the label is the address of the case table */
  16.696 -  code_idx+=opcodes(1)+opargs(1);
  16.697 -}
  16.698 -
  16.699 -SC_FUNC void ffcase(cell value,char *labelname,int newtable)
  16.700 -{
  16.701 -  if (newtable) {
  16.702 -    stgwrite("\tcasetbl\n");
  16.703 -    code_idx+=opcodes(1);
  16.704 -  } /* if */
  16.705 -  stgwrite("\tcase ");
  16.706 -  outval(value,FALSE);
  16.707 -  stgwrite(" ");
  16.708 -  stgwrite(labelname);
  16.709 -  stgwrite("\n");
  16.710 -  code_idx+=opcodes(0)+opargs(2);
  16.711 -}
  16.712 -
  16.713 -/*
  16.714 - *  Call specified function
  16.715 - */
  16.716 -SC_FUNC void ffcall(symbol *sym,const char *label,int numargs)
  16.717 -{
  16.718 -  char symname[2*sNAMEMAX+16];
  16.719 -
  16.720 -  assert(sym!=NULL);
  16.721 -  assert(sym->ident==iFUNCTN);
  16.722 -  if (sc_asmfile)
  16.723 -    funcdisplayname(symname,sym->name);
  16.724 -  if ((sym->usage & uNATIVE)!=0) {
  16.725 -    /* reserve a SYSREQ id if called for the first time */
  16.726 -    assert(label==NULL);
  16.727 -    if (sc_status==statWRITE && (sym->usage & uREAD)==0 && sym->addr>=0)
  16.728 -      sym->addr=ntv_funcid++;
  16.729 -    stgwrite("\tsysreq.c ");
  16.730 -    outval(sym->addr,FALSE);
  16.731 -    if (sc_asmfile) {
  16.732 -      stgwrite("\t; ");
  16.733 -      stgwrite(symname);
  16.734 -    } /* if */
  16.735 -    stgwrite("\n"); /* write on a separate line, to mark a sequence point for the peephole optimizer */
  16.736 -    stgwrite("\tstack ");
  16.737 -    outval((numargs+1)*sizeof(cell), TRUE);
  16.738 -    code_idx+=opcodes(2)+opargs(2);
  16.739 -  } else {
  16.740 -    /* normal function */
  16.741 -    stgwrite("\tcall ");
  16.742 -    if (label!=NULL) {
  16.743 -      stgwrite("l.");
  16.744 -      stgwrite(label);
  16.745 -    } else {
  16.746 -      stgwrite(sym->name);
  16.747 -    } /* if */
  16.748 -    if (sc_asmfile
  16.749 -        && (label!=NULL || !isalpha(sym->name[0]) && sym->name[0]!='_'  && sym->name[0]!=sc_ctrlchar))
  16.750 -    {
  16.751 -      stgwrite("\t; ");
  16.752 -      stgwrite(symname);
  16.753 -    } /* if */
  16.754 -    stgwrite("\n");
  16.755 -    code_idx+=opcodes(1)+opargs(1);
  16.756 -  } /* if */
  16.757 -}
  16.758 -
  16.759 -/*  Return from function
  16.760 - *
  16.761 - *  Global references: funcstatus  (referred to only)
  16.762 - */
  16.763 -SC_FUNC void ffret(int remparams)
  16.764 -{
  16.765 -  if (remparams)
  16.766 -    stgwrite("\tretn\n");
  16.767 -  else
  16.768 -    stgwrite("\tret\n");
  16.769 -  code_idx+=opcodes(1);
  16.770 -}
  16.771 -
  16.772 -SC_FUNC void ffabort(int reason)
  16.773 -{
  16.774 -  stgwrite("\thalt ");
  16.775 -  outval(reason,TRUE);
  16.776 -  code_idx+=opcodes(1)+opargs(1);
  16.777 -}
  16.778 -
  16.779 -SC_FUNC void ffbounds(cell size)
  16.780 -{
  16.781 -  if ((sc_debug & sCHKBOUNDS)!=0) {
  16.782 -    stgwrite("\tbounds ");
  16.783 -    outval(size,TRUE);
  16.784 -    code_idx+=opcodes(1)+opargs(1);
  16.785 -  } /* if */
  16.786 -}
  16.787 -
  16.788 -/*
  16.789 - *  Jump to local label number (the number is converted to a name)
  16.790 - */
  16.791 -SC_FUNC void jumplabel(int number)
  16.792 -{
  16.793 -  stgwrite("\tjump ");
  16.794 -  outval(number,TRUE);
  16.795 -  code_idx+=opcodes(1)+opargs(1);
  16.796 -}
  16.797 -
  16.798 -/*
  16.799 - *   Define storage (global and static variables)
  16.800 - */
  16.801 -SC_FUNC void defstorage(void)
  16.802 -{
  16.803 -  stgwrite("dump ");
  16.804 -}
  16.805 -
  16.806 -/*
  16.807 - *  Inclrement/decrement stack pointer. Note that this routine does
  16.808 - *  nothing if the delta is zero.
  16.809 - */
  16.810 -SC_FUNC void modstk(int delta)
  16.811 -{
  16.812 -  if (delta) {
  16.813 -    stgwrite("\tstack ");
  16.814 -    outval(delta, TRUE);
  16.815 -    code_idx+=opcodes(1)+opargs(1);
  16.816 -  } /* if */
  16.817 -}
  16.818 -
  16.819 -/* set the stack to a hard offset from the frame */
  16.820 -SC_FUNC void setstk(cell value)
  16.821 -{
  16.822 -  stgwrite("\tlctrl 5\n");      /* get FRM in PRI */
  16.823 -  assert(value<=0);             /* STK should always become <= FRM */
  16.824 -  if (value<0) {
  16.825 -    stgwrite("\tadd.c ");
  16.826 -    outval(value, TRUE);        /* add (negative) offset */
  16.827 -    code_idx+=opcodes(1)+opargs(1);
  16.828 -    // ??? write zeros in the space between STK and the value in PRI (the new stk)
  16.829 -    //     get value of STK in ALT
  16.830 -    //     zero PRI
  16.831 -    //     need new FILL opcode that takes a variable size
  16.832 -  } /* if */
  16.833 -  stgwrite("\tsctrl 4\n");      /* store in STK */
  16.834 -  code_idx+=opcodes(2)+opargs(2);
  16.835 -}
  16.836 -
  16.837 -SC_FUNC void modheap(int delta)
  16.838 -{
  16.839 -  if (delta) {
  16.840 -    stgwrite("\theap ");
  16.841 -    outval(delta, TRUE);
  16.842 -    code_idx+=opcodes(1)+opargs(1);
  16.843 -  } /* if */
  16.844 -}
  16.845 -
  16.846 -SC_FUNC void setheap_pri(void)
  16.847 -{
  16.848 -  stgwrite("\theap ");          /* ALT = HEA++ */
  16.849 -  outval(sizeof(cell), TRUE);
  16.850 -  stgwrite("\tstor.i\n");       /* store PRI (default value) at address ALT */
  16.851 -  stgwrite("\tmove.pri\n");     /* move ALT to PRI: PRI contains the address */
  16.852 -  code_idx+=opcodes(3)+opargs(1);
  16.853 -}
  16.854 -
  16.855 -SC_FUNC void setheap(cell value)
  16.856 -{
  16.857 -  stgwrite("\tconst.pri ");     /* load default value in PRI */
  16.858 -  outval(value, TRUE);
  16.859 -  code_idx+=opcodes(1)+opargs(1);
  16.860 -  setheap_pri();
  16.861 -}
  16.862 -
  16.863 -/*
  16.864 - *  Convert a cell number to a "byte" address; i.e. double or quadruple
  16.865 - *  the primary register.
  16.866 - */
  16.867 -SC_FUNC void cell2addr(void)
  16.868 -{
  16.869 -  #if PAWN_CELL_SIZE==16
  16.870 -    stgwrite("\tshl.c.pri 1\n");
  16.871 -  #elif PAWN_CELL_SIZE==32
  16.872 -    stgwrite("\tshl.c.pri 2\n");
  16.873 -  #elif PAWN_CELL_SIZE==64
  16.874 -    stgwrite("\tshl.c.pri 3\n");
  16.875 -  #else
  16.876 -    #error Unsupported cell size
  16.877 -  #endif
  16.878 -  code_idx+=opcodes(1)+opargs(1);
  16.879 -}
  16.880 -
  16.881 -/*
  16.882 - *  Double or quadruple the alternate register.
  16.883 - */
  16.884 -SC_FUNC void cell2addr_alt(void)
  16.885 -{
  16.886 -  #if PAWN_CELL_SIZE==16
  16.887 -    stgwrite("\tshl.c.alt 1\n");
  16.888 -  #elif PAWN_CELL_SIZE==32
  16.889 -    stgwrite("\tshl.c.alt 2\n");
  16.890 -  #elif PAWN_CELL_SIZE==64
  16.891 -    stgwrite("\tshl.c.alt 3\n");
  16.892 -  #else
  16.893 -    #error Unsupported cell size
  16.894 -  #endif
  16.895 -  code_idx+=opcodes(1)+opargs(1);
  16.896 -}
  16.897 -
  16.898 -/*
  16.899 - *  Convert "distance of addresses" to "number of cells" in between.
  16.900 - *  Or convert a number of packed characters to the number of cells (with
  16.901 - *  truncation).
  16.902 - */
  16.903 -SC_FUNC void addr2cell(void)
  16.904 -{
  16.905 -  #if PAWN_CELL_SIZE==16
  16.906 -    stgwrite("\tshr.c.pri 1\n");
  16.907 -  #elif PAWN_CELL_SIZE==32
  16.908 -    stgwrite("\tshr.c.pri 2\n");
  16.909 -  #elif PAWN_CELL_SIZE==64
  16.910 -    stgwrite("\tshr.c.pri 3\n");
  16.911 -  #else
  16.912 -    #error Unsupported cell size
  16.913 -  #endif
  16.914 -  code_idx+=opcodes(1)+opargs(1);
  16.915 -}
  16.916 -
  16.917 -/* Convert from character index to byte address. This routine does
  16.918 - * nothing if a character has the size of a byte.
  16.919 - */
  16.920 -SC_FUNC void char2addr(void)
  16.921 -{
  16.922 -  #if sCHARBITS==16
  16.923 -    stgwrite("\tshl.c.pri 1\n");
  16.924 -    code_idx+=opcodes(1)+opargs(1);
  16.925 -  #endif
  16.926 -}
  16.927 -
  16.928 -/* Align PRI (which should hold a character index) to an address.
  16.929 - * The first character in a "pack" occupies the highest bits of
  16.930 - * the cell. This is at the lower memory address on Big Endian
  16.931 - * computers and on the higher address on Little Endian computers.
  16.932 - * The ALIGN.pri/alt instructions must solve this machine dependence;
  16.933 - * that is, on Big Endian computers, ALIGN.pri/alt shuold do nothing
  16.934 - * and on Little Endian computers they should toggle the address.
  16.935 - */
  16.936 -SC_FUNC void charalign(void)
  16.937 -{
  16.938 -  stgwrite("\talign.pri ");
  16.939 -  outval(sCHARBITS/8,TRUE);
  16.940 -  code_idx+=opcodes(1)+opargs(1);
  16.941 -}
  16.942 -
  16.943 -/*
  16.944 - *  Add a constant to the primary register.
  16.945 - */
  16.946 -SC_FUNC void addconst(cell value)
  16.947 -{
  16.948 -  if (value!=0) {
  16.949 -    stgwrite("\tadd.c ");
  16.950 -    outval(value,TRUE);
  16.951 -    code_idx+=opcodes(1)+opargs(1);
  16.952 -  } /* if */
  16.953 -}
  16.954 -
  16.955 -/*
  16.956 - *  signed multiply of primary and secundairy registers (result in primary)
  16.957 - */
  16.958 -SC_FUNC void os_mult(void)
  16.959 -{
  16.960 -  stgwrite("\tsmul\n");
  16.961 -  code_idx+=opcodes(1);
  16.962 -}
  16.963 -
  16.964 -/*
  16.965 - *  signed divide of alternate register by primary register (quotient in
  16.966 - *  primary; remainder in alternate)
  16.967 - */
  16.968 -SC_FUNC void os_div(void)
  16.969 -{
  16.970 -  stgwrite("\tsdiv.alt\n");
  16.971 -  code_idx+=opcodes(1);
  16.972 -}
  16.973 -
  16.974 -/*
  16.975 - *  modulus of (alternate % primary), result in primary (signed)
  16.976 - */
  16.977 -SC_FUNC void os_mod(void)
  16.978 -{
  16.979 -  stgwrite("\tsdiv.alt\n");
  16.980 -  stgwrite("\tmove.pri\n");     /* move ALT to PRI */
  16.981 -  code_idx+=opcodes(2);
  16.982 -}
  16.983 -
  16.984 -/*
  16.985 - *  Add primary and alternate registers (result in primary).
  16.986 - */
  16.987 -SC_FUNC void ob_add(void)
  16.988 -{
  16.989 -  stgwrite("\tadd\n");
  16.990 -  code_idx+=opcodes(1);
  16.991 -}
  16.992 -
  16.993 -/*
  16.994 - *  subtract primary register from alternate register (result in primary)
  16.995 - */
  16.996 -SC_FUNC void ob_sub(void)
  16.997 -{
  16.998 -  stgwrite("\tsub.alt\n");
  16.999 -  code_idx+=opcodes(1);
 16.1000 -}
 16.1001 -
 16.1002 -/*
 16.1003 - *  arithmic shift left alternate register the number of bits
 16.1004 - *  given in the primary register (result in primary).
 16.1005 - *  There is no need for a "logical shift left" routine, since
 16.1006 - *  logical shift left is identical to arithmic shift left.
 16.1007 - */
 16.1008 -SC_FUNC void ob_sal(void)
 16.1009 -{
 16.1010 -  stgwrite("\txchg\n");
 16.1011 -  stgwrite("\tshl\n");
 16.1012 -  code_idx+=opcodes(2);
 16.1013 -}
 16.1014 -
 16.1015 -/*
 16.1016 - *  arithmic shift right alternate register the number of bits
 16.1017 - *  given in the primary register (result in primary).
 16.1018 - */
 16.1019 -SC_FUNC void os_sar(void)
 16.1020 -{
 16.1021 -  stgwrite("\txchg\n");
 16.1022 -  stgwrite("\tsshr\n");
 16.1023 -  code_idx+=opcodes(2);
 16.1024 -}
 16.1025 -
 16.1026 -/*
 16.1027 - *  logical (unsigned) shift right of the alternate register by the
 16.1028 - *  number of bits given in the primary register (result in primary).
 16.1029 - */
 16.1030 -SC_FUNC void ou_sar(void)
 16.1031 -{
 16.1032 -  stgwrite("\txchg\n");
 16.1033 -  stgwrite("\tshr\n");
 16.1034 -  code_idx+=opcodes(2);
 16.1035 -}
 16.1036 -
 16.1037 -/*
 16.1038 - *  inclusive "or" of primary and alternate registers (result in primary)
 16.1039 - */
 16.1040 -SC_FUNC void ob_or(void)
 16.1041 -{
 16.1042 -  stgwrite("\tor\n");
 16.1043 -  code_idx+=opcodes(1);
 16.1044 -}
 16.1045 -
 16.1046 -/*
 16.1047 - *  "exclusive or" of primary and alternate registers (result in primary)
 16.1048 - */
 16.1049 -SC_FUNC void ob_xor(void)
 16.1050 -{
 16.1051 -  stgwrite("\txor\n");
 16.1052 -  code_idx+=opcodes(1);
 16.1053 -}
 16.1054 -
 16.1055 -/*
 16.1056 - *  "and" of primary and secundairy registers (result in primary)
 16.1057 - */
 16.1058 -SC_FUNC void ob_and(void)
 16.1059 -{
 16.1060 -  stgwrite("\tand\n");
 16.1061 -  code_idx+=opcodes(1);
 16.1062 -}
 16.1063 -
 16.1064 -/*
 16.1065 - *  test ALT==PRI; result in primary register (1 or 0).
 16.1066 - */
 16.1067 -SC_FUNC void ob_eq(void)
 16.1068 -{
 16.1069 -  stgwrite("\teq\n");
 16.1070 -  code_idx+=opcodes(1);
 16.1071 -}
 16.1072 -
 16.1073 -/*
 16.1074 - *  test ALT!=PRI
 16.1075 - */
 16.1076 -SC_FUNC void ob_ne(void)
 16.1077 -{
 16.1078 -  stgwrite("\tneq\n");
 16.1079 -  code_idx+=opcodes(1);
 16.1080 -}
 16.1081 -
 16.1082 -/* The abstract machine defines the relational instructions so that PRI is
 16.1083 - * on the left side and ALT on the right side of the operator. For example,
 16.1084 - * SLESS sets PRI to either 1 or 0 depending on whether the expression
 16.1085 - * "PRI < ALT" is true.
 16.1086 - *
 16.1087 - * The compiler generates comparisons with ALT on the left side of the
 16.1088 - * relational operator and PRI on the right side. The XCHG instruction
 16.1089 - * prefixing the relational operators resets this. We leave it to the
 16.1090 - * peephole optimizer to choose more compact instructions where possible.
 16.1091 - */
 16.1092 -
 16.1093 -/* Relational operator prefix for chained relational expressions. The
 16.1094 - * "suffix" code restores the stack.
 16.1095 - * For chained relational operators, the goal is to keep the comparison
 16.1096 - * result "so far" in PRI and the value of the most recent operand in
 16.1097 - * ALT, ready for a next comparison.
 16.1098 - * The "prefix" instruction pushed the comparison result (PRI) onto the
 16.1099 - * stack and moves the value of ALT into PRI. If there is a next comparison,
 16.1100 - * PRI can now serve as the "left" operand of the relational operator.
 16.1101 - */
 16.1102 -SC_FUNC void relop_prefix(void)
 16.1103 -{
 16.1104 -  stgwrite("\tpush.pri\n");
 16.1105 -  stgwrite("\tmove.pri\n");
 16.1106 -  code_idx+=opcodes(2);
 16.1107 -}
 16.1108 -
 16.1109 -SC_FUNC void relop_suffix(void)
 16.1110 -{
 16.1111 -  stgwrite("\tswap.alt\n");
 16.1112 -  stgwrite("\tand\n");
 16.1113 -  stgwrite("\tpop.alt\n");
 16.1114 -  code_idx+=opcodes(3);
 16.1115 -}
 16.1116 -
 16.1117 -/*
 16.1118 - *  test ALT<PRI (signed)
 16.1119 - */
 16.1120 -SC_FUNC void os_lt(void)
 16.1121 -{
 16.1122 -  stgwrite("\txchg\n");
 16.1123 -  stgwrite("\tsless\n");
 16.1124 -  code_idx+=opcodes(2);
 16.1125 -}
 16.1126 -
 16.1127 -/*
 16.1128 - *  test ALT<=PRI (signed)
 16.1129 - */
 16.1130 -SC_FUNC void os_le(void)
 16.1131 -{
 16.1132 -  stgwrite("\txchg\n");
 16.1133 -  stgwrite("\tsleq\n");
 16.1134 -  code_idx+=opcodes(2);
 16.1135 -}
 16.1136 -
 16.1137 -/*
 16.1138 - *  test ALT>PRI (signed)
 16.1139 - */
 16.1140 -SC_FUNC void os_gt(void)
 16.1141 -{
 16.1142 -  stgwrite("\txchg\n");
 16.1143 -  stgwrite("\tsgrtr\n");
 16.1144 -  code_idx+=opcodes(2);
 16.1145 -}
 16.1146 -
 16.1147 -/*
 16.1148 - *  test ALT>=PRI (signed)
 16.1149 - */
 16.1150 -SC_FUNC void os_ge(void)
 16.1151 -{
 16.1152 -  stgwrite("\txchg\n");
 16.1153 -  stgwrite("\tsgeq\n");
 16.1154 -  code_idx+=opcodes(2);
 16.1155 -}
 16.1156 -
 16.1157 -/*
 16.1158 - *  logical negation of primary register
 16.1159 - */
 16.1160 -SC_FUNC void lneg(void)
 16.1161 -{
 16.1162 -  stgwrite("\tnot\n");
 16.1163 -  code_idx+=opcodes(1);
 16.1164 -}
 16.1165 -
 16.1166 -/*
 16.1167 - *  two's complement primary register
 16.1168 - */
 16.1169 -SC_FUNC void neg(void)
 16.1170 -{
 16.1171 -  stgwrite("\tneg\n");
 16.1172 -  code_idx+=opcodes(1);
 16.1173 -}
 16.1174 -
 16.1175 -/*
 16.1176 - *  one's complement of primary register
 16.1177 - */
 16.1178 -SC_FUNC void invert(void)
 16.1179 -{
 16.1180 -  stgwrite("\tinvert\n");
 16.1181 -  code_idx+=opcodes(1);
 16.1182 -}
 16.1183 -
 16.1184 -/*
 16.1185 - *  nop
 16.1186 - */
 16.1187 -SC_FUNC void nooperation(void)
 16.1188 -{
 16.1189 -  stgwrite("\tnop\n");
 16.1190 -  code_idx+=opcodes(1);
 16.1191 -}
 16.1192 -
 16.1193 -
 16.1194 -/*  increment symbol
 16.1195 - */
 16.1196 -SC_FUNC void inc(value *lval)
 16.1197 -{
 16.1198 -  symbol *sym;
 16.1199 -
 16.1200 -  sym=lval->sym;
 16.1201 -  if (lval->ident==iARRAYCELL) {
 16.1202 -    /* indirect increment, address already in PRI */
 16.1203 -    stgwrite("\tinc.i\n");
 16.1204 -    code_idx+=opcodes(1);
 16.1205 -  } else if (lval->ident==iARRAYCHAR) {
 16.1206 -    /* indirect increment of single character, address already in PRI */
 16.1207 -    stgwrite("\tpush.pri\n");
 16.1208 -    stgwrite("\tpush.alt\n");
 16.1209 -    stgwrite("\tmove.alt\n");   /* copy address */
 16.1210 -    stgwrite("\tlodb.i ");      /* read from PRI into PRI */
 16.1211 -    outval(sCHARBITS/8,TRUE);   /* read one or two bytes */
 16.1212 -    stgwrite("\tinc.pri\n");
 16.1213 -    stgwrite("\tstrb.i ");      /* write PRI to ALT */
 16.1214 -    outval(sCHARBITS/8,TRUE);   /* write one or two bytes */
 16.1215 -    stgwrite("\tpop.alt\n");
 16.1216 -    stgwrite("\tpop.pri\n");
 16.1217 -    code_idx+=opcodes(8)+opargs(2);
 16.1218 -  } else if (lval->ident==iREFERENCE) {
 16.1219 -    assert(sym!=NULL);
 16.1220 -    stgwrite("\tpush.pri\n");
 16.1221 -    /* load dereferenced value */
 16.1222 -    assert(sym->vclass==sLOCAL);    /* global references don't exist in Pawn */
 16.1223 -    if (sym->vclass==sLOCAL)
 16.1224 -      stgwrite("\tlref.s.pri ");
 16.1225 -    else
 16.1226 -      stgwrite("\tlref.pri ");
 16.1227 -    outval(sym->addr,TRUE);
 16.1228 -    /* increment */
 16.1229 -    stgwrite("\tinc.pri\n");
 16.1230 -    /* store dereferenced value */
 16.1231 -    if (sym->vclass==sLOCAL)
 16.1232 -      stgwrite("\tsref.s.pri ");
 16.1233 -    else
 16.1234 -      stgwrite("\tsref.pri ");
 16.1235 -    outval(sym->addr,TRUE);
 16.1236 -    stgwrite("\tpop.pri\n");
 16.1237 -    code_idx+=opcodes(5)+opargs(2);
 16.1238 -  } else {
 16.1239 -    /* local or global variable */
 16.1240 -    assert(sym!=NULL);
 16.1241 -    if (sym->vclass==sLOCAL)
 16.1242 -      stgwrite("\tinc.s ");
 16.1243 -    else
 16.1244 -      stgwrite("\tinc ");
 16.1245 -    outval(sym->addr,TRUE);
 16.1246 -    code_idx+=opcodes(1)+opargs(1);
 16.1247 -  } /* if */
 16.1248 -}
 16.1249 -
 16.1250 -/*  decrement symbol
 16.1251 - *
 16.1252 - *  in case of an integer pointer, the symbol must be incremented by 2.
 16.1253 - */
 16.1254 -SC_FUNC void dec(value *lval)
 16.1255 -{
 16.1256 -  symbol *sym;
 16.1257 -
 16.1258 -  sym=lval->sym;
 16.1259 -  if (lval->ident==iARRAYCELL) {
 16.1260 -    /* indirect decrement, address already in PRI */
 16.1261 -    stgwrite("\tdec.i\n");
 16.1262 -    code_idx+=opcodes(1);
 16.1263 -  } else if (lval->ident==iARRAYCHAR) {
 16.1264 -    /* indirect decrement of single character, address already in PRI */
 16.1265 -    stgwrite("\tpush.pri\n");
 16.1266 -    stgwrite("\tpush.alt\n");
 16.1267 -    stgwrite("\tmove.alt\n");   /* copy address */
 16.1268 -    stgwrite("\tlodb.i ");      /* read from PRI into PRI */
 16.1269 -    outval(sCHARBITS/8,TRUE);   /* read one or two bytes */
 16.1270 -    stgwrite("\tdec.pri\n");
 16.1271 -    stgwrite("\tstrb.i ");      /* write PRI to ALT */
 16.1272 -    outval(sCHARBITS/8,TRUE);   /* write one or two bytes */
 16.1273 -    stgwrite("\tpop.alt\n");
 16.1274 -    stgwrite("\tpop.pri\n");
 16.1275 -    code_idx+=opcodes(8)+opargs(2);
 16.1276 -  } else if (lval->ident==iREFERENCE) {
 16.1277 -    assert(sym!=NULL);
 16.1278 -    stgwrite("\tpush.pri\n");
 16.1279 -    /* load dereferenced value */
 16.1280 -    assert(sym->vclass==sLOCAL);    /* global references don't exist in Pawn */
 16.1281 -    if (sym->vclass==sLOCAL)
 16.1282 -      stgwrite("\tlref.s.pri ");
 16.1283 -    else
 16.1284 -      stgwrite("\tlref.pri ");
 16.1285 -    outval(sym->addr,TRUE);
 16.1286 -    /* decrement */
 16.1287 -    stgwrite("\tdec.pri\n");
 16.1288 -    /* store dereferenced value */
 16.1289 -    if (sym->vclass==sLOCAL)
 16.1290 -      stgwrite("\tsref.s.pri ");
 16.1291 -    else
 16.1292 -      stgwrite("\tsref.pri ");
 16.1293 -    outval(sym->addr,TRUE);
 16.1294 -    stgwrite("\tpop.pri\n");
 16.1295 -    code_idx+=opcodes(5)+opargs(2);
 16.1296 -  } else {
 16.1297 -    /* local or global variable */
 16.1298 -    assert(sym!=NULL);
 16.1299 -    if (sym->vclass==sLOCAL)
 16.1300 -      stgwrite("\tdec.s ");
 16.1301 -    else
 16.1302 -      stgwrite("\tdec ");
 16.1303 -    outval(sym->addr,TRUE);
 16.1304 -    code_idx+=opcodes(1)+opargs(1);
 16.1305 -  } /* if */
 16.1306 -}
 16.1307 -
 16.1308 -/*
 16.1309 - *  Jumps to "label" if PRI != 0
 16.1310 - */
 16.1311 -SC_FUNC void jmp_ne0(int number)
 16.1312 -{
 16.1313 -  stgwrite("\tjnz ");
 16.1314 -  outval(number,TRUE);
 16.1315 -  code_idx+=opcodes(1)+opargs(1);
 16.1316 -}
 16.1317 -
 16.1318 -/*
 16.1319 - *  Jumps to "label" if PRI == 0
 16.1320 - */
 16.1321 -SC_FUNC void jmp_eq0(int number)
 16.1322 -{
 16.1323 -  stgwrite("\tjzer ");
 16.1324 -  outval(number,TRUE);
 16.1325 -  code_idx+=opcodes(1)+opargs(1);
 16.1326 -}
 16.1327 -
 16.1328 -/* write a value in hexadecimal; optionally adds a newline */
 16.1329 -SC_FUNC void outval(cell val,int newline)
 16.1330 -{
 16.1331 -  stgwrite(itoh(val));
 16.1332 -  if (newline)
 16.1333 -    stgwrite("\n");
 16.1334 -}
    17.1 --- a/compiler-init/sc5.c	Sat Jul 15 01:36:48 2006 +0000
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,228 +0,0 @@
    17.4 -/*  Pawn compiler - Error message system
    17.5 - *  In fact a very simple system, using only 'panic mode'.
    17.6 - *
    17.7 - *  Copyright (c) ITB CompuPhase, 1997-2006
    17.8 - *
    17.9 - *  This software is provided "as-is", without any express or implied warranty.
   17.10 - *  In no event will the authors be held liable for any damages arising from
   17.11 - *  the use of this software.
   17.12 - *
   17.13 - *  Permission is granted to anyone to use this software for any purpose,
   17.14 - *  including commercial applications, and to alter it and redistribute it
   17.15 - *  freely, subject to the following restrictions:
   17.16 - *
   17.17 - *  1.  The origin of this software must not be misrepresented; you must not
   17.18 - *      claim that you wrote the original software. If you use this software in
   17.19 - *      a product, an acknowledgment in the product documentation would be
   17.20 - *      appreciated but is not required.
   17.21 - *  2.  Altered source versions must be plainly marked as such, and must not be
   17.22 - *      misrepresented as being the original software.
   17.23 - *  3.  This notice may not be removed or altered from any source distribution.
   17.24 - *
   17.25 - *  Version: $Id: sc5.c 3579 2006-06-06 13:35:29Z thiadmer $
   17.26 - */
   17.27 -#include <assert.h>
   17.28 -#if defined	__WIN32__ || defined _WIN32 || defined __MSDOS__
   17.29 -  #include <io.h>
   17.30 -#endif
   17.31 -#if defined LINUX || defined __GNUC__
   17.32 -  #include <unistd.h>
   17.33 -#endif
   17.34 -#include <stdio.h>
   17.35 -#include <stdlib.h>
   17.36 -#include <stdarg.h>     /* ANSI standardized variable argument list functions */
   17.37 -#include <string.h>
   17.38 -#if defined FORTIFY
   17.39 -  #include <alloc/fortify.h>
   17.40 -#endif
   17.41 -#include "sc.h"
   17.42 -
   17.43 -#if defined _MSC_VER
   17.44 -  #pragma warning(push)
   17.45 -  #pragma warning(disable:4125)  /* decimal digit terminates octal escape sequence */
   17.46 -#endif
   17.47 -
   17.48 -#include "sc5.scp"
   17.49 -
   17.50 -#if defined _MSC_VER
   17.51 -  #pragma warning(pop)
   17.52 -#endif
   17.53 -
   17.54 -#define NUM_WARNINGS    (sizeof warnmsg / sizeof warnmsg[0])
   17.55 -static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
   17.56 -
   17.57 -static int errflag;
   17.58 -static int errstart;    /* line number at which the instruction started */
   17.59 -static int errline;     /* forced line number for the error message */
   17.60 -
   17.61 -/*  error
   17.62 - *
   17.63 - *  Outputs an error message (note: msg is passed optionally).
   17.64 - *  If an error is found, the variable "errflag" is set and subsequent
   17.65 - *  errors are ignored until lex() finds a semicolumn or a keyword
   17.66 - *  (lex() resets "errflag" in that case).
   17.67 - *
   17.68 - *  Global references: inpfname   (reffered to only)
   17.69 - *                     fline      (reffered to only)
   17.70 - *                     fcurrent   (reffered to only)
   17.71 - *                     errflag    (altered)
   17.72 - */
   17.73 -SC_FUNC int error(int number,...)
   17.74 -{
   17.75 -static char *prefix[3]={ "error", "fatal error", "warning" };
   17.76 -static int lastline,errorcount;
   17.77 -static short lastfile;
   17.78 -  char *msg,*pre;
   17.79 -  va_list argptr;
   17.80 -  char string[128];
   17.81 -
   17.82 -  /* errflag is reset on each semicolon.
   17.83 -   * In a two-pass compiler, an error should not be reported twice. Therefore
   17.84 -   * the error reporting is enabled only in the second pass (and only when
   17.85 -   * actually producing output). Fatal errors may never be ignored.
   17.86 -   */
   17.87 -  if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200))
   17.88 -    return 0;
   17.89 -
   17.90 -  /* also check for disabled warnings */
   17.91 -  if (number>=200) {
   17.92 -    int index=(number-200)/8;
   17.93 -    int mask=1 << ((number-200)%8);
   17.94 -    if ((warndisable[index] & mask)!=0)
   17.95 -      return 0;
   17.96 -  } /* if */
   17.97 -
   17.98 -  if (number<100){
   17.99 -    msg=errmsg[number-1];
  17.100 -    pre=prefix[0];
  17.101 -    errflag=TRUE;       /* set errflag (skip rest of erroneous expression) */
  17.102 -    errnum++;
  17.103 -  } else if (number<200){
  17.104 -    msg=fatalmsg[number-100];
  17.105 -    pre=prefix[1];
  17.106 -    errnum++;           /* a fatal error also counts as an error */
  17.107 -  } else {
  17.108 -    msg=warnmsg[number-200];
  17.109 -    pre=prefix[2];
  17.110 -    warnnum++;
  17.111 -  } /* if */
  17.112 -
  17.113 -  strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE);
  17.114 -
  17.115 -  assert(errstart<=fline);
  17.116 -  if (errline>0)
  17.117 -    errstart=errline;
  17.118 -  else
  17.119 -    errline=fline;
  17.120 -  assert(errstart<=errline);
  17.121 -  va_start(argptr,number);
  17.122 -  if (strlen(errfname)==0) {
  17.123 -    int start= (errstart==errline) ? -1 : errstart;
  17.124 -    if (pc_error(number,string,inpfname,start,errline,argptr)) {
  17.125 -      if (outf!=NULL) {
  17.126 -        pc_closeasm(outf,TRUE);
  17.127 -        outf=NULL;
  17.128 -      } /* if */
  17.129 -      longjmp(errbuf,3);        /* user abort */
  17.130 -    } /* if */
  17.131 -  } else {
  17.132 -    FILE *fp=fopen(errfname,"a");
  17.133 -    if (fp!=NULL) {
  17.134 -      if (errstart>=0 && errstart!=errline)
  17.135 -        fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number);
  17.136 -      else
  17.137 -        fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number);
  17.138 -      vfprintf(fp,string,argptr);
  17.139 -      fclose(fp);
  17.140 -    } /* if */
  17.141 -  } /* if */
  17.142 -  va_end(argptr);
  17.143 -
  17.144 -  if (number>=100 && number<200 || errnum>25){
  17.145 -    if (strlen(errfname)==0) {
  17.146 -      va_start(argptr,number);
  17.147 -      pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
  17.148 -      va_end(argptr);
  17.149 -    } /* if */
  17.150 -    if (outf!=NULL) {
  17.151 -      pc_closeasm(outf,TRUE);
  17.152 -      outf=NULL;
  17.153 -    } /* if */
  17.154 -    longjmp(errbuf,2);          /* fatal error, quit */
  17.155 -  } /* if */
  17.156 -
  17.157 -  errline=-1;
  17.158 -  /* check whether we are seeing many errors on the same line */
  17.159 -  if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
  17.160 -    errorcount=0;
  17.161 -  lastline=fline;
  17.162 -  lastfile=fcurrent;
  17.163 -  if (number<200)
  17.164 -    errorcount++;
  17.165 -  if (errorcount>=3)
  17.166 -    error(107);         /* too many error/warning messages on one line */
  17.167 -
  17.168 -  return 0;
  17.169 -}
  17.170 -
  17.171 -SC_FUNC void errorset(int code,int line)
  17.172 -{
  17.173 -  switch (code) {
  17.174 -  case sRESET:
  17.175 -    errflag=FALSE;      /* start reporting errors */
  17.176 -    break;
  17.177 -  case sFORCESET:
  17.178 -    errflag=TRUE;       /* stop reporting errors */
  17.179 -    break;
  17.180 -  case sEXPRMARK:
  17.181 -    errstart=fline;     /* save start line number */
  17.182 -    break;
  17.183 -  case sEXPRRELEASE:
  17.184 -    errstart=-1;        /* forget start line number */
  17.185 -    errline=-1;
  17.186 -    break;
  17.187 -  case sSETPOS:
  17.188 -    errline=line;
  17.189 -    break;
  17.190 -  } /* switch */
  17.191 -}
  17.192 -
  17.193 -/* sc_enablewarning()
  17.194 - * Enables or disables a warning (errors cannot be disabled).
  17.195 - * Initially all warnings are enabled. The compiler does this by setting bits
  17.196 - * for the *disabled* warnings and relying on the array to be zero-initialized.
  17.197 - *
  17.198 - * Parameter enable can be:
  17.199 - *  o  0 for disable
  17.200 - *  o  1 for enable
  17.201 - *  o  2 for toggle
  17.202 - */
  17.203 -int pc_enablewarning(int number,int enable)
  17.204 -{
  17.205 -  int index;
  17.206 -  unsigned char mask;
  17.207 -
  17.208 -  if (number<200)
  17.209 -    return FALSE;       /* errors and fatal errors cannot be disabled */
  17.210 -  number -= 200;
  17.211 -  if (number>=NUM_WARNINGS)
  17.212 -    return FALSE;
  17.213 -
  17.214 -  index=number/8;
  17.215 -  mask=(unsigned char)(1 << (number%8));
  17.216 -  switch (enable) {
  17.217 -  case 0:
  17.218 -    warndisable[index] |= mask;
  17.219 -    break;
  17.220 -  case 1:
  17.221 -    warndisable[index] &= (unsigned char)~mask;
  17.222 -    break;
  17.223 -  case 2:
  17.224 -    warndisable[index] ^= mask;
  17.225 -    break;
  17.226 -  } /* switch */
  17.227 -
  17.228 -  return TRUE;
  17.229 -}
  17.230 -
  17.231 -#undef SCPACK_TABLE
    18.1 --- a/compiler-init/sc5.scp	Sat Jul 15 01:36:48 2006 +0000
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,342 +0,0 @@
    18.4 -/*  Pawn compiler - Error message strings (plain and compressed formats)
    18.5 - *
    18.6 - *  Copyright (c) ITB CompuPhase, 2000-2006
    18.7 - *
    18.8 - *  This software is provided "as-is", without any express or implied warranty.
    18.9 - *  In no event will the authors be held liable for any damages arising from
   18.10 - *  the use of this software.
   18.11 - *
   18.12 - *  Permission is granted to anyone to use this software for any purpose,
   18.13 - *  including commercial applications, and to alter it and redistribute it
   18.14 - *  freely, subject to the following restrictions:
   18.15 - *
   18.16 - *  1.  The origin of this software must not be misrepresented; you must not
   18.17 - *      claim that you wrote the original software. If you use this software in
   18.18 - *      a product, an acknowledgment in the product documentation would be
   18.19 - *      appreciated but is not required.
   18.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
   18.21 - *      misrepresented as being the original software.
   18.22 - *  3.  This notice may not be removed or altered from any source distribution.
   18.23 - *
   18.24 - *  Version: $Id: sc5.sch 3590 2006-06-24 14:16:39Z thiadmer $
   18.25 - */
   18.26 -
   18.27 -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
   18.28 -
   18.29 -#define SCPACK_TABLE errstr_table
   18.30 -/*-*SCPACK start of pair table, do not change or remove this line */
   18.31 -unsigned char errstr_table[][2] = {
   18.32 -  {101,32}, {111,110}, {116,32}, {105,110}, {97,114}, {116,105}, {100,32}, {115,32}, {101,114}, {97,108}, {101,110}, {37,115}, {133,129}, {34,139}, {141,34}, {117,110},
   18.33 -  {110,111}, {114,101}, {115,105}, {121,32}, {97,116}, {111,114}, {97,110}, {32,142}, {109,98}, {115,116}, {41,10}, {100,101}, {109,138}, {101,134}, {98,108}, {140,32},
   18.34 -  {111,108}, {114,97}, {144,130}, {118,137}, {143,99}, {102,164}, {115,121}, {166,152}, {167,160}, {117,115}, {97,32}, {115,146}, {97,158}, {149,32}, {132,161}, {105,134},
   18.35 -  {103,32}, {163,175}, {103,117}, {178,156}, {136,32}, {132,179}, {131,177}, {111,102}, {116,104}, {101,120}, {105,135}, {165,159}, {101,100}, {99,104}, {118,132}, {168,151},
   18.36 -  {105,172}, {190,192}, {155,102}, {174,147}, {183,32}, {109,97}, {116,111}, {99,129}, {101,135}, {181,130}, {98,128}, {115,10}, {112,145}, {153,148}, {44,32}, {40,191},
   18.37 -  {169,130}, {151,10}, {101,10}, {207,154}, {109,208}, {116,97}, {105,99}, {194,131}, {193,128}, {34,32}, {129,32}, {132,97}, {100,105}, {146,122}, {110,32}, {137,32},
   18.38 -  {104,97}, {101,108}, {117,108}, {99,111}, {108,111}, {109,148}, {199,153}, {58,209}, {111,112}, {97,115}, {108,128}, {232,136}, {230,150}, {150,32}, {204,171}, {131,176},
   18.39 -  {212,202}, {102,105}, {119,105}, {185,238}, {109,112}, {116,136}, {165,140}, {197,147}, {102,149}, {111,32}, {131,32}, {213,176}, {110,117}, {115,117}, {118,128}
   18.40 -};
   18.41 -/*-*SCPACK end of pair table, do not change or remove this line */
   18.42 -
   18.43 -static char *errmsg[] = {
   18.44 -#ifdef SCPACK
   18.45 -/*001*/  "expected token: \"%s\", but found \"%s\"\n",
   18.46 -/*002*/  "only a single statement (or expression) can follow each \"case\"\n",
   18.47 -/*003*/  "declaration of a local variable must appear in a compound block\n",
   18.48 -/*004*/  "function \"%s\" is not implemented\n",
   18.49 -/*005*/  "function may not have arguments\n",
   18.50 -/*006*/  "must be assigned to an array\n",
   18.51 -/*007*/  "operator cannot be redefined\n",
   18.52 -/*008*/  "must be a constant expression; assumed zero\n",
   18.53 -/*009*/  "invalid array size (negative, zero or out of bounds)\n",
   18.54 -/*010*/  "invalid function or declaration\n",
   18.55 -/*011*/  "invalid outside functions\n",
   18.56 -/*012*/  "invalid function call, not a valid address\n",
   18.57 -/*013*/  "no entry point (no public functions)\n",
   18.58 -/*014*/  "invalid statement; not in switch\n",
   18.59 -/*015*/  "\"default\" case must be the last case in switch statement\n",
   18.60 -/*016*/  "multiple defaults in \"switch\"\n",
   18.61 -/*017*/  "undefined symbol \"%s\"\n",
   18.62 -/*018*/  "initialization data exceeds declared size\n",
   18.63 -/*019*/  "not a label: \"%s\"\n",
   18.64 -/*020*/  "invalid symbol name \"%s\"\n",
   18.65 -/*021*/  "symbol already defined: \"%s\"\n",
   18.66 -/*022*/  "must be lvalue (non-constant)\n",
   18.67 -/*023*/  "array assignment must be simple assignment\n",
   18.68 -/*024*/  "\"break\" or \"continue\" is out of context\n",
   18.69 -/*025*/  "function heading differs from prototype\n",
   18.70 -/*026*/  "no matching \"#if...\"\n",
   18.71 -/*027*/  "invalid character constant\n",
   18.72 -/*028*/  "invalid subscript (not an array or too many subscripts): \"%s\"\n",
   18.73 -/*029*/  "invalid expression, assumed zero\n",
   18.74 -/*030*/  "compound statement not closed at the end of file (started at line %d)\n",
   18.75 -/*031*/  "unknown directive\n",
   18.76 -/*032*/  "array index out of bounds (variable \"%s\")\n",
   18.77 -/*033*/  "array must be indexed (variable \"%s\")\n",
   18.78 -/*034*/  "argument does not have a default value (argument %d)\n",
   18.79 -/*035*/  "argument type mismatch (argument %d)\n",
   18.80 -/*036*/  "empty statement\n",
   18.81 -/*037*/  "invalid string (possibly non-terminated string)\n",
   18.82 -/*038*/  "extra characters on line\n",
   18.83 -/*039*/  "constant symbol has no size\n",
   18.84 -/*040*/  "duplicate \"case\" label (value %d)\n",
   18.85 -/*041*/  "invalid ellipsis, array size is not known\n",
   18.86 -/*042*/  "invalid combination of class specifiers\n",
   18.87 -/*043*/  "character constant exceeds range for packed string\n",
   18.88 -/*044*/  "positional parameters must precede all named parameters\n",
   18.89 -/*045*/  "too many function arguments\n",
   18.90 -/*046*/  "unknown array size (variable \"%s\")\n",
   18.91 -/*047*/  "array sizes do not match, or destination array is too small\n",
   18.92 -/*048*/  "array dimensions do not match\n",
   18.93 -/*049*/  "invalid line continuation\n",
   18.94 -/*050*/  "invalid range\n",
   18.95 -/*051*/  "invalid subscript, use \"[ ]\" operators on major dimensions\n",
   18.96 -/*052*/  "multi-dimensional arrays must be fully initialized\n",
   18.97 -/*053*/  "exceeding maximum number of dimensions\n",
   18.98 -/*054*/  "unmatched closing brace (\"}\")\n",
   18.99 -/*055*/  "start of function body without function header\n",
  18.100 -/*056*/  "arrays, local variables and function arguments cannot be public (variable \"%s\")\n",
  18.101 -/*057*/  "unfinished expression before compiler directive\n",
  18.102 -/*058*/  "duplicate argument; same argument is passed twice\n",
  18.103 -/*059*/  "function argument may not have a default value (variable \"%s\")\n",
  18.104 -/*060*/  "multiple \"#else\" directives between \"#if ... #endif\"\n",
  18.105 -/*061*/  "\"#elseif\" directive follows an \"#else\" directive\n",
  18.106 -/*062*/  "number of operands does not fit the operator\n",
  18.107 -/*063*/  "function result tag of operator \"%s\" must be \"%s\"\n",
  18.108 -/*064*/  "cannot change predefined operators\n",
  18.109 -/*065*/  "function argument may only have a single tag (argument %d)\n",
  18.110 -/*066*/  "function argument may not be a reference argument or an array (argument \"%s\")\n",
  18.111 -/*067*/  "variable cannot be both a reference and an array (variable \"%s\")\n",
  18.112 -/*068*/  "invalid rational number precision in #pragma\n",
  18.113 -/*069*/  "rational number format already defined\n",
  18.114 -/*070*/  "rational number support was not enabled\n",
  18.115 -/*071*/  "user-defined operator must be declared before use (function \"%s\")\n",
  18.116 -/*072*/  "\"sizeof\" operator is invalid on \"function\" symbols\n",
  18.117 -/*073*/  "function argument must be an array (argument \"%s\")\n",
  18.118 -/*074*/  "#define pattern must start with an alphabetic character\n",
  18.119 -/*075*/  "input line too long (after substitutions)\n",
  18.120 -/*076*/  "syntax error in the expression, or invalid function call\n",
  18.121 -/*077*/  "malformed UTF-8 encoding, or corrupted file: %s\n",
  18.122 -/*078*/  "function uses both \"return\" and \"return <value>\"\n",
  18.123 -/*079*/  "inconsistent return types (array & non-array)\n",
  18.124 -/*080*/  "unknown symbol, or not a constant symbol (symbol \"%s\")\n",
  18.125 -/*081*/  "cannot take a tag as a default value for an indexed array parameter (symbol \"%s\")\n",
  18.126 -/*082*/  "user-defined operators and native functions may not have states\n",
  18.127 -/*083*/  "a function or variable may only belong to a single automaton (symbol \"%s\")\n",
  18.128 -/*084*/  "state conflict: one of the states is already assigned to another implementation (symbol \"%s\")\n",
  18.129 -/*085*/  "no states are defined for symbol \"%s\"\n",
  18.130 -/*086*/  "unknown automaton \"%s\"\n",
  18.131 -/*087*/  "unknown state \"%s\" for automaton \"%s\"\n",
  18.132 -/*088*/  "public variables and local variables may not have states (symbol \"%s\")\n",
  18.133 -/*089*/  "state variables may not be initialized (symbol \"%s\")\n",
  18.134 -/*090*/  "public functions may not return arrays (symbol \"%s\")\n",
  18.135 -/*091*/  "ambiguous constant; tag override is required (symbol \"%s\")\n"
  18.136 -#else
  18.137 -  "\271pect\235\306k\212:\227\316bu\202fo\217\206\216\012",
  18.138 -  "\201l\223\252s\203g\352\315e\234\202(\255\363\201) c\355f\240\344w ea\275 \042c\351e\042\012",
  18.139 -  "\233cl\333\237\304\252\344c\337\330\324appe\204 \372\252\343\364o\217\206\236ock\012",
  18.140 -  "\366\227 \272\242i\364le\234t\274\012",
  18.141 -  "\273\367\242\340\376\265t\313",
  18.142 -  "\360a\253gn\235\306 \355\256y\012",
  18.143 -  "\353\224\255c\226\242\312\221\327\274\012",
  18.144 -  "\360\252\354\202\363\201; \351\375m\235z\210o\012",
  18.145 -  "\266\303\335\200(nega\205ve\316z\210\371\255ou\202\304bo\217ds\232",
  18.146 -  "\266\273\255\233cl\333\214\012",
  18.147 -  "\266out\222d\200\366\313",
  18.148 -  "\266\273c\211l\316\242\252\261add\221s\313",
  18.149 -  "\220 \212tr\223po\203\202(\220 pu\236\326 \366s\232",
  18.150 -  "\266\315e\234t; \242\372s\362t\275\012",
  18.151 -  "\042\302a\342t\331c\351\200\360\270\200l\351\202c\351\200\372s\362t\275 \315e\234t\012",
  18.152 -  "m\342\205p\352\302a\342t\207\372\042s\362t\275\042\012",
  18.153 -  "\217\327\235\277\012",
  18.154 -  "\203i\205\211iza\237d\224\252\271ce\274\207\233cl\204\235\335\322",
  18.155 -  "\242\252lab\341\347",
  18.156 -  "\266\250 nam\200\216\012",
  18.157 -  "\250 \211\221ad\223\327\274\347",
  18.158 -  "\360l\243u\200(n\201-\354t\232",
  18.159 -  "\303a\253gn\234\202\360\222\364\352a\253gn\234t\012",
  18.160 -  "\042b\221ak\331\255\042\307t\203ue\331\272ou\202\304\307t\271t\012",
  18.161 -  "\273head\357\334ff\210\207from pro\306typ\322",
  18.162 -  "\220 \345\275\357\042#if...\042\012",
  18.163 -  "\266\275\333ct\264\354t\012",
  18.164 -  "\266\375bscrip\202(\242\355\303\255\306\371m\226\223\375bscripts)\347",
  18.165 -  "\266\363\201\316\351\375m\235z\210o\012",
  18.166 -  "\343\364o\217\206\315e\234\202\242c\344s\235a\202\270\200\212\206\304\361\352(\231\204t\235a\202l\203\200%d\232",
  18.167 -  "\217k\220w\336\334\221c\205v\322",
  18.168 -  "\303\203\233x ou\202\304bo\217d\207(\330\216\232",
  18.169 -  "\303\360\203\233x\235(\330\216\232",
  18.170 -  "\311do\310\242\340\376\252\302a\342\202\243u\200(\311%d\232",
  18.171 -  "\311typ\200mis\345\275 (\311%d\232",
  18.172 -  "e\364t\223\315e\234t\012",
  18.173 -  "\266\231r\357(po\253\236\223n\201-\365m\203\224\235\231r\203g\232",
  18.174 -  "\271t\241 \275\333c\365\207\332l\203\322",
  18.175 -  "\354\202\250 \340\207\220 \335\322",
  18.176 -  "dupl\326\224\200\042c\351e\331lab\341 (\243u\200%d\232",
  18.177 -  "\266\341lip\222s\316\303\335\200\272\242k\220wn\012",
  18.178 -  "\266\343\230\203a\237\304cl\351\207speci\361\210\313",
  18.179 -  "\275\333ct\264\354\202\271ce\274\207r\226g\200f\255pack\235\231r\203g\012",
  18.180 -  "po\222\214\337p\333me\365\207\324\314c\274\200\211l nam\235p\333me\365\313",
  18.181 -  "\306\371m\226\223\273\265t\313",
  18.182 -  "\217k\220w\336\303\335\200(\330\216\232",
  18.183 -  "\303\335\310d\371\242\345\275\316\255\233\231\203a\237\303\272\306\371sm\211l\012",
  18.184 -  "\303\334\234\222\201\207d\371\242\345\275\012",
  18.185 -  "\266l\203\200\307t\203ua\214\012",
  18.186 -  "\266r\226g\322",
  18.187 -  "\266\375bscript\316\251\200\042[ ]\331\353\224\225\207\332\305j\255\334\234\222\201\313",
  18.188 -  "m\342\205-\334\234\222\201\337\256y\207\360f\342l\223\203i\205\211iz\274\012",
  18.189 -  "\271ce\274\357\305ximum \374\230\264\304\334\234\222\201\313",
  18.190 -  "\217\345\275\235c\344s\357b\241c\200(\042}\042\232",
  18.191 -  "\231\204\202\304\273bod\223\362\270ou\202\273head\210\012",
  18.192 -  "\256ys\316\344c\337\301\310\226\206\273\265t\207c\226\242\312pu\236\326 (\330\216\232",
  18.193 -  "\217f\203ish\235\363\332be\370\200\343\364il\264\334\221c\205v\322",
  18.194 -  "dupl\326\224\200\265t; sam\200\311\272p\351s\235tw\326\322",
  18.195 -  "\273\311\367\242\340\376\252\302a\342\202\243u\200(\330\216\232",
  18.196 -  "m\342\205p\352\042#\341se\331\334\221c\205v\310betwe\212 \042#if ... #\212\334f\042\012",
  18.197 -  "\042#\341seif\331\334\221c\205\376f\240\344w\207\355\042#\341se\331\334\221c\205v\322",
  18.198 -  "\374\230\264\304\353\226d\207do\310\242\361\202\270\200\353\224\225\012",
  18.199 -  "\273\221s\342\202\373\304\353\224\225\227 \360\216\012",
  18.200 -  "c\226\242\275\226g\200\314\327\235\353\224\225\313",
  18.201 -  "\273\311\367\201l\223\340\376\252s\203g\352\373(\311%d\232",
  18.202 -  "\273\311\367\242\312\252\221f\210\212c\200\311\255\355\303(\311\216\232",
  18.203 -  "\330c\226\242\312bo\270 \252\221f\210\212c\200\226\206\355\303(\330\216\232",
  18.204 -  "\266\241\214\337\374\230\264\314ci\222\332\372#p\241g\305\012",
  18.205 -  "\241\214\337\374\230\264\370\305\202\211\221ad\223\327\274\012",
  18.206 -  "\241\214\337\374\230\264\375pp\225\202wa\207\242\212\254\274\012",
  18.207 -  "\251\210-\327\235\353\224\255\360\233cl\204\235be\370\200\251\200(\366\227\232",
  18.208 -  "\042\335e\267\331\353\224\255\272\266\332\042\366\331\250\313",
  18.209 -  "\273\311\360\355\303(\311\216\232",
  18.210 -  "#\327\200p\224\365\336\324\231\204\202\362\270 \355\211p\340be\205c \275\333c\365\012",
  18.211 -  "\203pu\202l\203\200\306\371l\201\260(aft\264\375bs\205tu\214s\232",
  18.212 -  "\246n\325x \210r\255\372\270\200\363\201\316\255\266\273c\211l\012",
  18.213 -  "m\211\370m\235UTF-8 \212\343d\203g\316\255c\225rupt\235\361le: \213\012",
  18.214 -  "\273\251\310bo\270 \042\221turn\331\226\206\042\221tur\336<\243ue>\042\012",
  18.215 -  "\203\307\222\231\212\202\221tur\336typ\310(\303& n\201-\256y\232",
  18.216 -  "\217k\220w\336\250\316\255\242\252\354\202\250 \323",
  18.217 -  "c\226\242\325k\200\252\373a\207\252\302a\342\202\243u\200f\255\355\203\233x\235\303p\333met\264\323",
  18.218 -  "\251\210-\327\235\353\224\225\207\226\206na\205\376\366\207\367\242\340\376\315e\313",
  18.219 -  "\252\273\255\330\367\201l\223b\341\201\260\306 \252s\203g\352au\306\345\332\323",
  18.220 -  "\315\200\307fl\326t: \201\200\304\270\200\315\310\272\211\221ad\223a\253gn\235\306 a\220\270\264i\364le\234\325\237\323",
  18.221 -  "\220 \315\310\204\200\327\235f\255\277\012",
  18.222 -  "\217k\220w\336au\306\345\201\321",
  18.223 -  "\217k\220w\336\315\200\216 f\255au\306\345\201\321",
  18.224 -  "pu\236\326 \301\310\226\206\344c\337\301\310\367\242\340\376\315\310\323",
  18.225 -  "\315\200\301\310\367\242\312\203i\205\211iz\235\323",
  18.226 -  "pu\236\326 \366\207\367\242\221tur\336\256y\207\323",
  18.227 -  "a\230i\262ou\207\354t; \373ov\210rid\200\272\221qui\221\206\323"
  18.228 -#endif
  18.229 -       };
  18.230 -
  18.231 -static char *fatalmsg[] = {
  18.232 -#ifdef SCPACK
  18.233 -/*100*/  "cannot read from file: \"%s\"\n",
  18.234 -/*101*/  "cannot write to file: \"%s\"\n",
  18.235 -/*102*/  "table overflow: \"%s\"\n",
  18.236 -          /* table can be: loop table
  18.237 -           *               literal table
  18.238 -           *               staging buffer
  18.239 -           *               option table (response file)
  18.240 -           *               peephole optimizer table
  18.241 -           */
  18.242 -/*103*/  "insufficient memory\n",
  18.243 -/*104*/  "invalid assembler instruction \"%s\"\n",
  18.244 -/*105*/  "numeric overflow, exceeding capacity\n",
  18.245 -/*106*/  "compiled script exceeds the maximum memory size (%ld bytes)\n",
  18.246 -/*107*/  "too many error messages on one line\n",
  18.247 -/*108*/  "codepage mapping file not found\n",
  18.248 -/*109*/  "invalid path: \"%s\"\n",
  18.249 -/*110*/  "assertion failed: %s\n",
  18.250 -/*111*/  "user error: %s\n",
  18.251 -#else
  18.252 -  "c\226\242\221a\206from \361le\347",
  18.253 -  "c\226\242writ\200\306 \361le\347",
  18.254 -  "t\254\200ov\210f\344w\347",
  18.255 -  "\203\375ff\326i\212\202mem\225y\012",
  18.256 -  "\266\351se\230l\264\203\231ruc\214\321",
  18.257 -  "\374m\210\326 ov\210f\344w\316\271ce\274\357capacity\012",
  18.258 -  "\343\364il\235scrip\202\271ce\274\207\270\200\305ximum mem\225\223\335\200(%l\206bytes\232",
  18.259 -  "\306\371m\226\223\210r\255messag\310\332\201\200l\203\322",
  18.260 -  "\343\233pag\200\305pp\357\361\352\242fo\217d\012",
  18.261 -  "\266p\224h\347",
  18.262 -  "\351s\210\237fail\274: \213\012",
  18.263 -  "\251\264\210r\225: \213\012"
  18.264 -#endif
  18.265 -       };
  18.266 -
  18.267 -static char *warnmsg[] = {
  18.268 -#ifdef SCPACK
  18.269 -/*200*/  "symbol \"%s\" is truncated to %d characters\n",
  18.270 -/*201*/  "redefinition of constant/macro (symbol \"%s\")\n",
  18.271 -/*202*/  "number of arguments does not match definition\n",
  18.272 -/*203*/  "symbol is never used: \"%s\"\n",
  18.273 -/*204*/  "symbol is assigned a value that is never used: \"%s\"\n",
  18.274 -/*205*/  "redundant code: constant expression is zero\n",
  18.275 -/*206*/  "redundant test: constant expression is non-zero\n",
  18.276 -/*207*/  "unknown #pragma\n",
  18.277 -/*208*/  "function with tag result used before definition, forcing reparse\n",
  18.278 -/*209*/  "function \"%s\" should return a value\n",
  18.279 -/*210*/  "possible use of symbol before initialization: \"%s\"\n",
  18.280 -/*211*/  "possibly unintended assignment\n",
  18.281 -/*212*/  "possibly unintended bitwise operation\n",
  18.282 -/*213*/  "tag mismatch\n",
  18.283 -/*214*/  "possibly a \"const\" array argument was intended: \"%s\"\n",
  18.284 -/*215*/  "expression has no effect\n",
  18.285 -/*216*/  "nested comment\n",
  18.286 -/*217*/  "loose indentation\n",
  18.287 -/*218*/  "old style prototypes used with optional semicolumns\n",
  18.288 -/*219*/  "local variable \"%s\" shadows a variable at a preceding level\n",
  18.289 -/*220*/  "expression with tag override must appear between parentheses\n",
  18.290 -/*221*/  "label name \"%s\" shadows tag name\n",
  18.291 -/*222*/  "number of digits exceeds rational number precision\n",
  18.292 -/*223*/  "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n",
  18.293 -/*224*/  "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n",
  18.294 -/*225*/  "unreachable code\n",
  18.295 -/*226*/  "a variable is assigned to itself (symbol \"%s\")\n",
  18.296 -/*227*/  "more initiallers than enum fields\n",
  18.297 -/*228*/  "length of initialler exceeds size of the enum field\n",
  18.298 -/*229*/  "index tag mismatch (symbol \"%s\")\n",
  18.299 -/*230*/  "no implementation for state \"%s\" in function \"%s\", no fall-back\n",
  18.300 -/*231*/  "state specification on forward declaration is ignored\n",
  18.301 -/*232*/  "output file is written, but with compact encoding disabled\n",
  18.302 -/*233*/  "state variable \"%s\" shadows a global variable\n",
  18.303 -/*234*/  "function is depricated (symbol \"%s\") %s\n",
  18.304 -/*235*/  "public function lacks forward declaration (symbol \"%s\")\n",
  18.305 -/*236*/  "unknown parameter in substitution (incorrect #define pattern)\n"
  18.306 -#else
  18.307 -  "\277 \272tr\244\224\235\306 %\206\275\333c\365\313",
  18.308 -  "\221\327i\237\304\354t/\305cr\371\323",
  18.309 -  "\374\230\264\304\265t\207do\310\242\345\275 \327i\214\012",
  18.310 -  "\250 \272nev\264\251\274\347",
  18.311 -  "\250 \272a\253gn\235\252\243u\200\270a\202\272nev\264\251\274\347",
  18.312 -  "\221d\217d\226\202\343\233: \354\202\363\332\272z\210o\012",
  18.313 -  "\221d\217d\226\202te\231: \354\202\363\332\272n\201-z\210o\012",
  18.314 -  "\217k\220w\336#p\241g\305\012",
  18.315 -  "\273\362\270 \373\221s\342\202\251\235be\370\200\327i\214\316\370c\357\221p\204s\322",
  18.316 -  "\366\227 sho\342\206\221tur\336\252\243u\322",
  18.317 -  "po\253\236\200\251\200\304\250 be\370\200\203i\205\211iza\214\347",
  18.318 -  "po\253\236\223\217\203t\212\233\206a\253gn\234t\012",
  18.319 -  "po\253\236\223\217\203t\212\233\206bit\362s\200\353a\214\012",
  18.320 -  "\373mis\345\275\012",
  18.321 -  "po\253\236\223\252\042\346\331\303\311wa\207\203t\212\233d\347",
  18.322 -  "\363\332\340\207\220 effect\012",
  18.323 -  "ne\231\235\343m\234t\012",
  18.324 -  "\344os\200\203d\212\325\214\012",
  18.325 -  "\240\206\231y\352pro\306typ\310\251\235\362\270 \350\214\337sem\326\240umn\313",
  18.326 -  "\344c\337\330\216 s\340dow\207\252\330a\202\252\314c\274\357lev\341\012",
  18.327 -  "\363\332\362\270 \373ov\210rid\200\324appe\204 betwe\212 p\204\212\270ese\313",
  18.328 -  "lab\341 nam\200\216 s\340dow\207\373nam\322",
  18.329 -  "\374\230\264\304\334git\207\271ce\274\207\241\214\337\374\230\264\314ci\222\201\012",
  18.330 -  "\221d\217d\226\202\042\335e\267\042: \311\335\200\272\211way\2071 \323",
  18.331 -  "\203\233\365m\203\224\200\303\335\200\372\042\335e\267\331\363\332\323",
  18.332 -  "\217\221a\275\254\200\343\233\012",
  18.333 -  "\252\330\272a\253gn\235\306 its\341f \323",
  18.334 -  "m\225\200\203i\205\211l\210\207\270\355\212um \361\341d\313",
  18.335 -  "l\212g\270 \304\203i\205\211l\264\271ce\274\207\335\200\304\270\200\212um \361\341d\012",
  18.336 -  "\203\233x \373mis\345\275 \323",
  18.337 -  "\220 i\364le\234\325\237f\255\315\200\216 \372\366\227\316\220 f\211l-back\012",
  18.338 -  "\315\200specif\326a\237\332\370w\204\206\233cl\333\237\272ig\220\221d\012",
  18.339 -  "outpu\202\361\352\272writt\212\316bu\202\362\270 \343\364ac\202\212\343d\357\334s\254\274\012",
  18.340 -  "\315\200\330\216 s\340dow\207\252g\344b\337\301\322",
  18.341 -  "\273\272\233pr\326\224\235\317) \213\012",
  18.342 -  "pu\236\326 \273lack\207\370w\204\206\233cl\333\237\323",
  18.343 -  "\217k\220w\336p\333met\264\372\375bs\205tu\237(\203c\225\221c\202#\327\200p\224\365n\232"
  18.344 -#endif
  18.345 -       };
    19.1 --- a/compiler-init/sc6.c	Sat Jul 15 01:36:48 2006 +0000
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,1298 +0,0 @@
    19.4 -/*  Pawn compiler - Binary code generation (the "assembler")
    19.5 - *
    19.6 - *  Copyright (c) ITB CompuPhase, 1997-2006
    19.7 - *
    19.8 - *  This software is provided "as-is", without any express or implied warranty.
    19.9 - *  In no event will the authors be held liable for any damages arising from
   19.10 - *  the use of this software.
   19.11 - *
   19.12 - *  Permission is granted to anyone to use this software for any purpose,
   19.13 - *  including commercial applications, and to alter it and redistribute it
   19.14 - *  freely, subject to the following restrictions:
   19.15 - *
   19.16 - *  1.  The origin of this software must not be misrepresented; you must not
   19.17 - *      claim that you wrote the original software. If you use this software in
   19.18 - *      a product, an acknowledgment in the product documentation would be
   19.19 - *      appreciated but is not required.
   19.20 - *  2.  Altered source versions must be plainly marked as such, and must not be
   19.21 - *      misrepresented as being the original software.
   19.22 - *  3.  This notice may not be removed or altered from any source distribution.
   19.23 - *
   19.24 - *  Version: $Id: sc6.c 3579 2006-06-06 13:35:29Z thiadmer $
   19.25 - */
   19.26 -#include <assert.h>
   19.27 -#include <stdio.h>
   19.28 -#include <stdlib.h>     /* for macro max() */
   19.29 -#include <stddef.h>     /* for macro offsetof() */
   19.30 -#include <string.h>
   19.31 -#include <ctype.h>
   19.32 -#if defined FORTIFY
   19.33 -  #include <alloc/fortify.h>
   19.34 -#endif
   19.35 -#include "lstring.h"
   19.36 -#include "sc.h"
   19.37 -#include "amxdbg.h"
   19.38 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
   19.39 -  #include <sclinux.h>
   19.40 -#endif
   19.41 -
   19.42 -
   19.43 -static void append_dbginfo(FILE *fout);
   19.44 -
   19.45 -
   19.46 -typedef cell (*OPCODE_PROC)(FILE *fbin,char *params,cell opcode);
   19.47 -
   19.48 -typedef struct {
   19.49 -  cell opcode;
   19.50 -  char *name;
   19.51 -  int segment;          /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */
   19.52 -  OPCODE_PROC func;
   19.53 -} OPCODE;
   19.54 -
   19.55 -static cell codeindex;  /* similar to "code_idx" */
   19.56 -static cell *lbltab;    /* label table */
   19.57 -static int writeerror;
   19.58 -static int bytes_in, bytes_out;
   19.59 -static jmp_buf compact_err;
   19.60 -
   19.61 -/* apparently, strtol() does not work correctly on very large (unsigned)
   19.62 - * hexadecimal values */
   19.63 -static ucell hex2long(const char *s,char **n)
   19.64 -{
   19.65 -  ucell result=0L;
   19.66 -  int negate=FALSE;
   19.67 -  int digit;
   19.68 -
   19.69 -  /* ignore leading whitespace */
   19.70 -  while (*s==' ' || *s=='\t')
   19.71 -    s++;
   19.72 -
   19.73 -  /* allow a negation sign to create the two's complement of numbers */
   19.74 -  if (*s=='-') {
   19.75 -    negate=TRUE;
   19.76 -    s++;
   19.77 -  } /* if */
   19.78 -
   19.79 -  assert((*s>='0' && *s<='9') || (*s>='a' && *s<='f') || (*s>='a' && *s<='f'));
   19.80 -  for ( ;; ) {
   19.81 -    if (*s>='0' && *s<='9')
   19.82 -      digit=*s-'0';
   19.83 -    else if (*s>='a' && *s<='f')
   19.84 -      digit=*s-'a' + 10;
   19.85 -    else if (*s>='A' && *s<='F')
   19.86 -      digit=*s-'A' + 10;
   19.87 -    else
   19.88 -      break;    /* probably whitespace */
   19.89 -    result=(result<<4) | digit;
   19.90 -    s++;
   19.91 -  } /* for */
   19.92 -  if (n!=NULL)
   19.93 -    *n=(char*)s;
   19.94 -  if (negate)
   19.95 -    result=(~result)+1; /* take two's complement of the result */
   19.96 -  return (ucell)result;
   19.97 -}
   19.98 -
   19.99 -static ucell getparam(const char *s,char **n)
  19.100 -{
  19.101 -  ucell result=0;
  19.102 -  for ( ;; ) {
  19.103 -    result+=hex2long(s,(char**)&s);
  19.104 -    if (*s!='+')
  19.105 -      break;
  19.106 -    s++;
  19.107 -  } /* for */
  19.108 -  if (n!=NULL)
  19.109 -    *n=(char*)s;
  19.110 -  return result;
  19.111 -}
  19.112 -
  19.113 -#if BYTE_ORDER==BIG_ENDIAN
  19.114 -static uint16_t *align16(uint16_t *v)
  19.115 -{
  19.116 -  unsigned char *s = (unsigned char *)v;
  19.117 -  unsigned char t;
  19.118 -
  19.119 -  /* swap two bytes */
  19.120 -  t=s[0];
  19.121 -  s[0]=s[1];
  19.122 -  s[1]=t;
  19.123 -  return v;
  19.124 -}
  19.125 -
  19.126 -static uint32_t *align32(uint32_t *v)
  19.127 -{
  19.128 -  unsigned char *s = (unsigned char *)v;
  19.129 -  unsigned char t;
  19.130 -
  19.131 -  /* swap outer two bytes */
  19.132 -  t=s[0];
  19.133 -  s[0]=s[3];
  19.134 -  s[3]=t;
  19.135 -  /* swap inner two bytes */
  19.136 -  t=s[1];
  19.137 -  s[1]=s[2];
  19.138 -  s[2]=t;
  19.139 -  return v;
  19.140 -}
  19.141 -
  19.142 -#if PAWN_CELL_SIZE>=64
  19.143 -static uint64_t *align64(uint64_t *v)
  19.144 -{
  19.145 -	unsigned char *s = (unsigned char *)v;
  19.146 -	unsigned char t;
  19.147 -
  19.148 -	t=s[0];
  19.149 -	s[0]=s[7];
  19.150 -	s[7]=t;
  19.151 -
  19.152 -	t=s[1];
  19.153 -	s[1]=s[6];
  19.154 -	s[6]=t;
  19.155 -
  19.156 -	t=s[2];
  19.157 -	s[2]=s[5];
  19.158 -	s[5]=t;
  19.159 -
  19.160 -	t=s[3];
  19.161 -	s[3]=s[4];
  19.162 -	s[4]=t;
  19.163 -
  19.164 -	return v;
  19.165 -}
  19.166 -#endif
  19.167 -
  19.168 -  #if PAWN_CELL_SIZE==16
  19.169 -    #define aligncell(v)  align16(v)
  19.170 -  #elif PAWN_CELL_SIZE==32
  19.171 -    #define aligncell(v)  align32(v)
  19.172 -  #elif PAWN_CELL_SIZE==64
  19.173 -    #define aligncell(v)  align64(v)
  19.174 -  #endif
  19.175 -#else
  19.176 -  #define align16(v)    (v)
  19.177 -  #define align32(v)    (v)
  19.178 -  #define aligncell(v)  (v)
  19.179 -#endif
  19.180 -
  19.181 -static char *skipwhitespace(char *str)
  19.182 -{
  19.183 -  while (isspace(*str))
  19.184 -    str++;
  19.185 -  return str;
  19.186 -}
  19.187 -
  19.188 -static char *stripcomment(char *str)
  19.189 -{
  19.190 -  char *ptr=strchr(str,';');
  19.191 -  if (ptr!=NULL) {
  19.192 -    *ptr++='\n';        /* terminate the line, but leave the '\n' */
  19.193 -    *ptr='\0';
  19.194 -  } /* if */
  19.195 -  return str;
  19.196 -}
  19.197 -
  19.198 -static void write_encoded(FILE *fbin,ucell *c,int num)
  19.199 -{
  19.200 -  #if PAWN_CELL_SIZE == 16
  19.201 -    #define ENC_MAX   3     /* a 16-bit cell is encoded in max. 3 bytes */
  19.202 -    #define ENC_MASK  0x03  /* after 2x7 bits, 2 bits remain to make 16 bits */
  19.203 -  #elif PAWN_CELL_SIZE == 32
  19.204 -    #define ENC_MAX   5     /* a 32-bit cell is encoded in max. 5 bytes */
  19.205 -    #define ENC_MASK  0x0f  /* after 4x7 bits, 4 bits remain to make 32 bits */
  19.206 -  #elif PAWN_CELL_SIZE == 64
  19.207 -    #define ENC_MAX   10    /* a 32-bit cell is encoded in max. 10 bytes */
  19.208 -    #define ENC_MASK  0x01  /* after 9x7 bits, 1 bit remains to make 64 bits */
  19.209 -  #endif
  19.210 -
  19.211 -  assert(fbin!=NULL);
  19.212 -  while (num-->0) {
  19.213 -    if (sc_compress) {
  19.214 -      ucell p=(ucell)*c;
  19.215 -      unsigned char t[ENC_MAX];
  19.216 -      unsigned char code;
  19.217 -      int index;
  19.218 -      for (index=0; index<ENC_MAX; index++) {
  19.219 -        t[index]=(unsigned char)(p & 0x7f);     /* store 7 bits */
  19.220 -        p>>=7;
  19.221 -      } /* for */
  19.222 -      /* skip leading zeros */
  19.223 -      while (index>1 && t[index-1]==0 && (t[index-2] & 0x40)==0)
  19.224 -        index--;
  19.225 -      /* skip leading -1s */
  19.226 -      if (index==ENC_MAX && t[index-1]==ENC_MASK && (t[index-2] & 0x40)!=0)
  19.227 -        index--;
  19.228 -      while (index>1 && t[index-1]==0x7f && (t[index-2] & 0x40)!=0)
  19.229 -        index--;
  19.230 -      /* write high byte first, write continuation bits */
  19.231 -      assert(index>0);
  19.232 -      while (index-->0) {
  19.233 -        code=(unsigned char)((index==0) ? t[index] : (t[index]|0x80));
  19.234 -        writeerror |= !pc_writebin(fbin,&code,1);
  19.235 -        bytes_out++;
  19.236 -      } /* while */
  19.237 -      bytes_in+=sizeof *c;
  19.238 -      assert(AMX_COMPACTMARGIN>2);
  19.239 -      if (bytes_out-bytes_in>=AMX_COMPACTMARGIN-2)
  19.240 -        longjmp(compact_err,1);
  19.241 -    } else {
  19.242 -      assert((pc_lengthbin(fbin) % sizeof(cell)) == 0);
  19.243 -      writeerror |= !pc_writebin(fbin,aligncell(c),sizeof *c);
  19.244 -    } /* if */
  19.245 -    c++;
  19.246 -  } /* while */
  19.247 -}
  19.248 -
  19.249 -#if defined __BORLANDC__ || defined __WATCOMC__
  19.250 -  #pragma argsused
  19.251 -#endif
  19.252 -static cell noop(FILE *fbin,char *params,cell opcode)
  19.253 -{
  19.254 -  return 0;
  19.255 -}
  19.256 -
  19.257 -#if defined __BORLANDC__ || defined __WATCOMC__
  19.258 -  #pragma argsused
  19.259 -#endif
  19.260 -static cell set_currentfile(FILE *fbin,char *params,cell opcode)
  19.261 -{
  19.262 -  fcurrent=(short)getparam(params,NULL);
  19.263 -  return 0;
  19.264 -}
  19.265 -
  19.266 -#if defined __BORLANDC__ || defined __WATCOMC__
  19.267 -  #pragma argsused
  19.268 -#endif
  19.269 -static cell parm0(FILE *fbin,char *params,cell opcode)
  19.270 -{
  19.271 -  if (fbin!=NULL)
  19.272 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.273 -  return opcodes(1);
  19.274 -}
  19.275 -
  19.276 -static cell parm1(FILE *fbin,char *params,cell opcode)
  19.277 -{
  19.278 -  ucell p=getparam(params,NULL);
  19.279 -  if (fbin!=NULL) {
  19.280 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.281 -    write_encoded(fbin,&p,1);
  19.282 -  } /* if */
  19.283 -  return opcodes(1)+opargs(1);
  19.284 -}
  19.285 -
  19.286 -static cell parm2(FILE *fbin,char *params,cell opcode)
  19.287 -{
  19.288 -  ucell p1=getparam(params,&params);
  19.289 -  ucell p2=getparam(params,NULL);
  19.290 -  if (fbin!=NULL) {
  19.291 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.292 -    write_encoded(fbin,&p1,1);
  19.293 -    write_encoded(fbin,&p2,1);
  19.294 -  } /* if */
  19.295 -  return opcodes(1)+opargs(2);
  19.296 -}
  19.297 -
  19.298 -static cell parm3(FILE *fbin,char *params,cell opcode)
  19.299 -{
  19.300 -  ucell p1=getparam(params,&params);
  19.301 -  ucell p2=getparam(params,&params);
  19.302 -  ucell p3=getparam(params,NULL);
  19.303 -  if (fbin!=NULL) {
  19.304 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.305 -    write_encoded(fbin,&p1,1);
  19.306 -    write_encoded(fbin,&p2,1);
  19.307 -    write_encoded(fbin,&p3,1);
  19.308 -  } /* if */
  19.309 -  return opcodes(1)+opargs(3);
  19.310 -}
  19.311 -
  19.312 -static cell parm4(FILE *fbin,char *params,cell opcode)
  19.313 -{
  19.314 -  ucell p1=getparam(params,&params);
  19.315 -  ucell p2=getparam(params,&params);
  19.316 -  ucell p3=getparam(params,&params);
  19.317 -  ucell p4=getparam(params,NULL);
  19.318 -  if (fbin!=NULL) {
  19.319 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.320 -    write_encoded(fbin,&p1,1);
  19.321 -    write_encoded(fbin,&p2,1);
  19.322 -    write_encoded(fbin,&p3,1);
  19.323 -    write_encoded(fbin,&p4,1);
  19.324 -  } /* if */
  19.325 -  return opcodes(1)+opargs(4);
  19.326 -}
  19.327 -
  19.328 -static cell parm5(FILE *fbin,char *params,cell opcode)
  19.329 -{
  19.330 -  ucell p1=getparam(params,&params);
  19.331 -  ucell p2=getparam(params,&params);
  19.332 -  ucell p3=getparam(params,&params);
  19.333 -  ucell p4=getparam(params,&params);
  19.334 -  ucell p5=getparam(params,NULL);
  19.335 -  if (fbin!=NULL) {
  19.336 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.337 -    write_encoded(fbin,&p1,1);
  19.338 -    write_encoded(fbin,&p2,1);
  19.339 -    write_encoded(fbin,&p3,1);
  19.340 -    write_encoded(fbin,&p4,1);
  19.341 -    write_encoded(fbin,&p5,1);
  19.342 -  } /* if */
  19.343 -  return opcodes(1)+opargs(5);
  19.344 -}
  19.345 -
  19.346 -#if defined __BORLANDC__ || defined __WATCOMC__
  19.347 -  #pragma argsused
  19.348 -#endif
  19.349 -static cell do_dump(FILE *fbin,char *params,cell opcode)
  19.350 -{
  19.351 -  ucell p;
  19.352 -  int num = 0;
  19.353 -
  19.354 -  while (*params!='\0') {
  19.355 -    p=getparam(params,&params);
  19.356 -    if (fbin!=NULL)
  19.357 -      write_encoded(fbin,&p,1);
  19.358 -    num++;
  19.359 -    while (isspace(*params))
  19.360 -      params++;
  19.361 -  } /* while */
  19.362 -  return num*sizeof(cell);
  19.363 -}
  19.364 -
  19.365 -static cell do_call(FILE *fbin,char *params,cell opcode)
  19.366 -{
  19.367 -  char name[sNAMEMAX+1];
  19.368 -  int i;
  19.369 -  symbol *sym;
  19.370 -  ucell p;
  19.371 -
  19.372 -  for (i=0; !isspace(*params); i++,params++) {
  19.373 -    assert(*params!='\0');
  19.374 -    assert(i<sNAMEMAX);
  19.375 -    name[i]=*params;
  19.376 -  } /* for */
  19.377 -  name[i]='\0';
  19.378 -
  19.379 -  if (name[0]=='l' && name[1]=='.') {
  19.380 -    /* this is a label, not a function symbol */
  19.381 -    i=(int)hex2long(name+2,NULL);
  19.382 -    assert(i>=0 && i<sc_labnum);
  19.383 -    if (fbin!=NULL) {
  19.384 -      assert(lbltab!=NULL);
  19.385 -      p=lbltab[i];
  19.386 -    } /* if */
  19.387 -  } else {
  19.388 -    /* look up the function address; note that the correct file number must
  19.389 -     * already have been set (in order for static globals to be found).
  19.390 -     */
  19.391 -    sym=findglb(name,sGLOBAL);
  19.392 -    assert(sym!=NULL);
  19.393 -    assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
  19.394 -    assert(sym->vclass==sGLOBAL);
  19.395 -    p=sym->addr;
  19.396 -  } /* if */
  19.397 -
  19.398 -  if (fbin!=NULL) {
  19.399 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.400 -    write_encoded(fbin,&p,1);
  19.401 -  } /* if */
  19.402 -  return opcodes(1)+opargs(1);
  19.403 -}
  19.404 -
  19.405 -static cell do_jump(FILE *fbin,char *params,cell opcode)
  19.406 -{
  19.407 -  int i;
  19.408 -  ucell p;
  19.409 -
  19.410 -  i=(int)hex2long(params,NULL);
  19.411 -  assert(i>=0 && i<sc_labnum);
  19.412 -
  19.413 -  if (fbin!=NULL) {
  19.414 -    assert(lbltab!=NULL);
  19.415 -    p=lbltab[i];
  19.416 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.417 -    write_encoded(fbin,&p,1);
  19.418 -  } /* if */
  19.419 -  return opcodes(1)+opargs(1);
  19.420 -}
  19.421 -
  19.422 -static cell do_switch(FILE *fbin,char *params,cell opcode)
  19.423 -{
  19.424 -  int i;
  19.425 -  ucell p;
  19.426 -
  19.427 -  i=(int)hex2long(params,NULL);
  19.428 -  assert(i>=0 && i<sc_labnum);
  19.429 -
  19.430 -  if (fbin!=NULL) {
  19.431 -    assert(lbltab!=NULL);
  19.432 -    p=lbltab[i];
  19.433 -    write_encoded(fbin,(ucell*)&opcode,1);
  19.434 -    write_encoded(fbin,&p,1);
  19.435 -  } /* if */
  19.436 -  return opcodes(1)+opargs(1);
  19.437 -}
  19.438 -
  19.439 -#if defined __BORLANDC__ || defined __WATCOMC__
  19.440 -  #pragma argsused
  19.441 -#endif
  19.442 -static cell do_case(FILE *fbin,char *params,cell opcode)
  19.443 -{
  19.444 -  int i;
  19.445 -  ucell p,v;
  19.446 -
  19.447 -  v=hex2long(params,&params);
  19.448 -  i=(int)hex2long(params,NULL);
  19.449 -  assert(i>=0 && i<sc_labnum);
  19.450 -
  19.451 -  if (fbin!=NULL) {
  19.452 -    assert(lbltab!=NULL);
  19.453 -    p=lbltab[i];
  19.454 -    write_encoded(fbin,&v,1);
  19.455 -    write_encoded(fbin,&p,1);
  19.456 -  } /* if */
  19.457 -  return opcodes(0)+opargs(2);
  19.458 -}
  19.459 -
  19.460 -static OPCODE opcodelist[] = {
  19.461 -  /* node for "invalid instruction" */
  19.462 -  {  0, NULL,         0,        noop },
  19.463 -  /* opcodes in sorted order */
  19.464 -  { 78, "add",        sIN_CSEG, parm0 },
  19.465 -  { 87, "add.c",      sIN_CSEG, parm1 },
  19.466 -  { 14, "addr.alt",   sIN_CSEG, parm1 },
  19.467 -  { 13, "addr.pri",   sIN_CSEG, parm1 },
  19.468 -  { 30, "align.alt",  sIN_CSEG, parm1 },
  19.469 -  { 29, "align.pri",  sIN_CSEG, parm1 },
  19.470 -  { 81, "and",        sIN_CSEG, parm0 },
  19.471 -  {121, "bounds",     sIN_CSEG, parm1 },
  19.472 -  {137, "break",      sIN_CSEG, parm0 },  /* version 8 */
  19.473 -  { 49, "call",       sIN_CSEG, do_call },
  19.474 -  { 50, "call.pri",   sIN_CSEG, parm0 },
  19.475 -  {  0, "case",       sIN_CSEG, do_case },
  19.476 -  {130, "casetbl",    sIN_CSEG, parm0 },  /* version 1 */
  19.477 -  {118, "cmps",       sIN_CSEG, parm1 },
  19.478 -  {  0, "code",       sIN_CSEG, set_currentfile },
  19.479 -  {156, "const",      sIN_CSEG, parm2 },  /* version 9 */
  19.480 -  { 12, "const.alt",  sIN_CSEG, parm1 },
  19.481 -  { 11, "const.pri",  sIN_CSEG, parm1 },
  19.482 -  {157, "const.s",    sIN_CSEG, parm2 },  /* version 9 */
  19.483 -  {  0, "data",       sIN_DSEG, set_currentfile },
  19.484 -  {114, "dec",        sIN_CSEG, parm1 },
  19.485 -  {113, "dec.alt",    sIN_CSEG, parm0 },
  19.486 -  {116, "dec.i",      sIN_CSEG, parm0 },
  19.487 -  {112, "dec.pri",    sIN_CSEG, parm0 },
  19.488 -  {115, "dec.s",      sIN_CSEG, parm1 },
  19.489 -  {  0, "dump",       sIN_DSEG, do_dump },
  19.490 -  { 95, "eq",         sIN_CSEG, parm0 },
  19.491 -  {106, "eq.c.alt",   sIN_CSEG, parm1 },
  19.492 -  {105, "eq.c.pri",   sIN_CSEG, parm1 },
  19.493 -/*{124, "file",       sIN_CSEG, do_file }, */
  19.494 -  {119, "fill",       sIN_CSEG, parm1 },
  19.495 -  {100, "geq",        sIN_CSEG, parm0 },
  19.496 -  { 99, "grtr",       sIN_CSEG, parm0 },
  19.497 -  {120, "halt",       sIN_CSEG, parm1 },
  19.498 -  { 45, "heap",       sIN_CSEG, parm1 },
  19.499 -  { 27, "idxaddr",    sIN_CSEG, parm0 },
  19.500 -  { 28, "idxaddr.b",  sIN_CSEG, parm1 },
  19.501 -  {109, "inc",        sIN_CSEG, parm1 },
  19.502 -  {108, "inc.alt",    sIN_CSEG, parm0 },
  19.503 -  {111, "inc.i",      sIN_CSEG, parm0 },
  19.504 -  {107, "inc.pri",    sIN_CSEG, parm0 },
  19.505 -  {110, "inc.s",      sIN_CSEG, parm1 },
  19.506 -  { 86, "invert",     sIN_CSEG, parm0 },
  19.507 -  { 55, "jeq",        sIN_CSEG, do_jump },
  19.508 -  { 60, "jgeq",       sIN_CSEG, do_jump },
  19.509 -  { 59, "jgrtr",      sIN_CSEG, do_jump },
  19.510 -  { 58, "jleq",       sIN_CSEG, do_jump },
  19.511 -  { 57, "jless",      sIN_CSEG, do_jump },
  19.512 -  { 56, "jneq",       sIN_CSEG, do_jump },
  19.513 -  { 54, "jnz",        sIN_CSEG, do_jump },
  19.514 -  { 52, "jrel",       sIN_CSEG, parm1 },  /* always a number */
  19.515 -  { 64, "jsgeq",      sIN_CSEG, do_jump },
  19.516 -  { 63, "jsgrtr",     sIN_CSEG, do_jump },
  19.517 -  { 62, "jsleq",      sIN_CSEG, do_jump },
  19.518 -  { 61, "jsless",     sIN_CSEG, do_jump },
  19.519 -  { 51, "jump",       sIN_CSEG, do_jump },
  19.520 -  {128, "jump.pri",   sIN_CSEG, parm0 },  /* version 1 */
  19.521 -  { 53, "jzer",       sIN_CSEG, do_jump },
  19.522 -  { 31, "lctrl",      sIN_CSEG, parm1 },
  19.523 -  { 98, "leq",        sIN_CSEG, parm0 },
  19.524 -  { 97, "less",       sIN_CSEG, parm0 },
  19.525 -  { 25, "lidx",       sIN_CSEG, parm0 },
  19.526 -  { 26, "lidx.b",     sIN_CSEG, parm1 },
  19.527 -/*{125, "line",       sIN_CSEG, parm2 }, */
  19.528 -  {  2, "load.alt",   sIN_CSEG, parm1 },
  19.529 -  {154, "load.both",  sIN_CSEG, parm2 },  /* version 9 */
  19.530 -  {  9, "load.i",     sIN_CSEG, parm0 },
  19.531 -  {  1, "load.pri",   sIN_CSEG, parm1 },
  19.532 -  {  4, "load.s.alt", sIN_CSEG, parm1 },
  19.533 -  {155, "load.s.both",sIN_CSEG, parm2 },  /* version 9 */
  19.534 -  {  3, "load.s.pri", sIN_CSEG, parm1 },
  19.535 -  { 10, "lodb.i",     sIN_CSEG, parm1 },
  19.536 -  {  6, "lref.alt",   sIN_CSEG, parm1 },
  19.537 -  {  5, "lref.pri",   sIN_CSEG, parm1 },
  19.538 -  {  8, "lref.s.alt", sIN_CSEG, parm1 },
  19.539 -  {  7, "lref.s.pri", sIN_CSEG, parm1 },
  19.540 -  { 34, "move.alt",   sIN_CSEG, parm0 },
  19.541 -  { 33, "move.pri",   sIN_CSEG, parm0 },
  19.542 -  {117, "movs",       sIN_CSEG, parm1 },
  19.543 -  { 85, "neg",        sIN_CSEG, parm0 },
  19.544 -  { 96, "neq",        sIN_CSEG, parm0 },
  19.545 -  {134, "nop",        sIN_CSEG, parm0 },  /* version 6 */
  19.546 -  { 84, "not",        sIN_CSEG, parm0 },
  19.547 -  { 82, "or",         sIN_CSEG, parm0 },
  19.548 -  { 43, "pop.alt",    sIN_CSEG, parm0 },
  19.549 -  { 42, "pop.pri",    sIN_CSEG, parm0 },
  19.550 -  { 46, "proc",       sIN_CSEG, parm0 },
  19.551 -  { 40, "push",       sIN_CSEG, parm1 },
  19.552 -  {133, "push.adr",   sIN_CSEG, parm1 },  /* version 4 */
  19.553 -  { 37, "push.alt",   sIN_CSEG, parm0 },
  19.554 -  { 39, "push.c",     sIN_CSEG, parm1 },
  19.555 -  { 36, "push.pri",   sIN_CSEG, parm0 },
  19.556 -  { 38, "push.r",     sIN_CSEG, parm1 },  /* obsolete (never generated) */
  19.557 -  { 41, "push.s",     sIN_CSEG, parm1 },
  19.558 -  {139, "push2",      sIN_CSEG, parm2 },  /* version 9 */
  19.559 -  {141, "push2.adr",  sIN_CSEG, parm2 },  /* version 9 */
  19.560 -  {138, "push2.c",    sIN_CSEG, parm2 },  /* version 9 */
  19.561 -  {140, "push2.s",    sIN_CSEG, parm2 },  /* version 9 */
  19.562 -  {143, "push3",      sIN_CSEG, parm3 },  /* version 9 */
  19.563 -  {145, "push3.adr",  sIN_CSEG, parm3 },  /* version 9 */
  19.564 -  {142, "push3.c",    sIN_CSEG, parm3 },  /* version 9 */
  19.565 -  {144, "push3.s",    sIN_CSEG, parm3 },  /* version 9 */
  19.566 -  {147, "push4",      sIN_CSEG, parm4 },  /* version 9 */
  19.567 -  {149, "push4.adr",  sIN_CSEG, parm4 },  /* version 9 */
  19.568 -  {146, "push4.c",    sIN_CSEG, parm4 },  /* version 9 */
  19.569 -  {148, "push4.s",    sIN_CSEG, parm4 },  /* version 9 */
  19.570 -  {151, "push5",      sIN_CSEG, parm5 },  /* version 9 */
  19.571 -  {153, "push5.adr",  sIN_CSEG, parm5 },  /* version 9 */
  19.572 -  {150, "push5.c",    sIN_CSEG, parm5 },  /* version 9 */
  19.573 -  {152, "push5.s",    sIN_CSEG, parm5 },  /* version 9 */
  19.574 -  { 47, "ret",        sIN_CSEG, parm0 },
  19.575 -  { 48, "retn",       sIN_CSEG, parm0 },
  19.576 -  { 32, "sctrl",      sIN_CSEG, parm1 },
  19.577 -  { 73, "sdiv",       sIN_CSEG, parm0 },
  19.578 -  { 74, "sdiv.alt",   sIN_CSEG, parm0 },
  19.579 -  {104, "sgeq",       sIN_CSEG, parm0 },
  19.580 -  {103, "sgrtr",      sIN_CSEG, parm0 },
  19.581 -  { 65, "shl",        sIN_CSEG, parm0 },
  19.582 -  { 69, "shl.c.alt",  sIN_CSEG, parm1 },
  19.583 -  { 68, "shl.c.pri",  sIN_CSEG, parm1 },
  19.584 -  { 66, "shr",        sIN_CSEG, parm0 },
  19.585 -  { 71, "shr.c.alt",  sIN_CSEG, parm1 },
  19.586 -  { 70, "shr.c.pri",  sIN_CSEG, parm1 },
  19.587 -  { 94, "sign.alt",   sIN_CSEG, parm0 },
  19.588 -  { 93, "sign.pri",   sIN_CSEG, parm0 },
  19.589 -  {102, "sleq",       sIN_CSEG, parm0 },
  19.590 -  {101, "sless",      sIN_CSEG, parm0 },
  19.591 -  { 72, "smul",       sIN_CSEG, parm0 },
  19.592 -  { 88, "smul.c",     sIN_CSEG, parm1 },
  19.593 -/*{127, "srange",     sIN_CSEG, parm2 }, -- version 1 */
  19.594 -  { 20, "sref.alt",   sIN_CSEG, parm1 },
  19.595 -  { 19, "sref.pri",   sIN_CSEG, parm1 },
  19.596 -  { 22, "sref.s.alt", sIN_CSEG, parm1 },
  19.597 -  { 21, "sref.s.pri", sIN_CSEG, parm1 },
  19.598 -  { 67, "sshr",       sIN_CSEG, parm0 },
  19.599 -  { 44, "stack",      sIN_CSEG, parm1 },
  19.600 -  {  0, "stksize",    0,        noop },
  19.601 -  { 16, "stor.alt",   sIN_CSEG, parm1 },
  19.602 -  { 23, "stor.i",     sIN_CSEG, parm0 },
  19.603 -  { 15, "stor.pri",   sIN_CSEG, parm1 },
  19.604 -  { 18, "stor.s.alt", sIN_CSEG, parm1 },
  19.605 -  { 17, "stor.s.pri", sIN_CSEG, parm1 },
  19.606 -  { 24, "strb.i",     sIN_CSEG, parm1 },
  19.607 -  { 79, "sub",        sIN_CSEG, parm0 },
  19.608 -  { 80, "sub.alt",    sIN_CSEG, parm0 },
  19.609 -  {132, "swap.alt",   sIN_CSEG, parm0 },  /* version 4 */
  19.610 -  {131, "swap.pri",   sIN_CSEG, parm0 },  /* version 4 */
  19.611 -  {129, "switch",     sIN_CSEG, do_switch }, /* version 1 */
  19.612 -/*{126, "symbol",     sIN_CSEG, do_symbol }, */
  19.613 -/*{136, "symtag",     sIN_CSEG, parm1 },  -- version 7 */
  19.614 -  {123, "sysreq.c",   sIN_CSEG, parm1 },
  19.615 -  {135, "sysreq.n",   sIN_CSEG, parm2 },  /* version 9 (replaces SYSREQ.d from earlier version) */
  19.616 -  {122, "sysreq.pri", sIN_CSEG, parm0 },
  19.617 -  { 76, "udiv",       sIN_CSEG, parm0 },
  19.618 -  { 77, "udiv.alt",   sIN_CSEG, parm0 },
  19.619 -  { 75, "umul",       sIN_CSEG, parm0 },
  19.620 -  { 35, "xchg",       sIN_CSEG, parm0 },
  19.621 -  { 83, "xor",        sIN_CSEG, parm0 },
  19.622 -  { 91, "zero",       sIN_CSEG, parm1 },
  19.623 -  { 90, "zero.alt",   sIN_CSEG, parm0 },
  19.624 -  { 89, "zero.pri",   sIN_CSEG, parm0 },
  19.625 -  { 92, "zero.s",     sIN_CSEG, parm1 },
  19.626 -};
  19.627 -
  19.628 -#define MAX_INSTR_LEN   30
  19.629 -static int findopcode(char *instr,int maxlen)
  19.630 -{
  19.631 -  int low,high,mid,cmp;
  19.632 -  char str[MAX_INSTR_LEN];
  19.633 -
  19.634 -  if (maxlen>=MAX_INSTR_LEN)
  19.635 -    return 0;
  19.636 -  strlcpy(str,instr,maxlen+1);
  19.637 -  /* look up the instruction with a binary search
  19.638 -   * the assembler is case insensitive to instructions (but case sensitive
  19.639 -   * to symbols)
  19.640 -   */
  19.641 -  low=1;                /* entry 0 is reserved (for "not found") */
  19.642 -  high=(sizeof opcodelist / sizeof opcodelist[0])-1;
  19.643 -  while (low<high) {
  19.644 -    mid=(low+high)/2;
  19.645 -    assert(opcodelist[mid].name!=NULL);
  19.646 -    cmp=stricmp(str,opcodelist[mid].name);
  19.647 -    if (cmp>0)
  19.648 -      low=mid+1;
  19.649 -    else
  19.650 -      high=mid;
  19.651 -  } /* while */
  19.652 -
  19.653 -  assert(low==high);
  19.654 -  if (stricmp(str,opcodelist[low].name)==0)
  19.655 -    return low;         /* found */
  19.656 -  return 0;             /* not found, return special index */
  19.657 -}
  19.658 -
  19.659 -SC_FUNC int assemble(FILE *fout,FILE *fin)
  19.660 -{
  19.661 -  AMX_HEADER hdr;
  19.662 -  AMX_FUNCSTUBNT func;
  19.663 -  int numpublics,numnatives,numlibraries,numpubvars,numtags,padding;
  19.664 -  long nametablesize,nameofs;
  19.665 -  #if PAWN_CELL_SIZE > 32
  19.666 -    char line[512];
  19.667 -  #else
  19.668 -    char line[256];
  19.669 -  #endif
  19.670 -  char *instr,*params;
  19.671 -  int i,pass,size;
  19.672 -  int16_t count;
  19.673 -  symbol *sym, **nativelist;
  19.674 -  constvalue *constptr;
  19.675 -  cell mainaddr;
  19.676 -  char nullchar = 0;
  19.677 -
  19.678 -  /* if compression failed, restart the assembly with compaction switched off */
  19.679 -  if (setjmp(compact_err)!=0) {
  19.680 -    assert(sc_compress);  /* cannot arrive here if compact encoding was disabled */
  19.681 -    sc_compress=FALSE;
  19.682 -    pc_resetbin(fout,0);
  19.683 -    error(232);           /* disabled compact encoding */
  19.684 -  } /* if */
  19.685 -
  19.686 -  #if !defined NDEBUG
  19.687 -    /* verify that the opcode list is sorted (skip entry 1; it is reserved
  19.688 -     * for a non-existant opcode)
  19.689 -     */
  19.690 -    assert(opcodelist[1].name!=NULL);
  19.691 -    for (i=2; i<(sizeof opcodelist / sizeof opcodelist[0]); i++) {
  19.692 -      assert(opcodelist[i].name!=NULL);
  19.693 -      assert(stricmp(opcodelist[i].name,opcodelist[i-1].name)>0);
  19.694 -    } /* for */
  19.695 -  #endif
  19.696 -
  19.697 -  writeerror=FALSE;
  19.698 -  nametablesize=sizeof(int16_t);
  19.699 -  numpublics=0;
  19.700 -  numnatives=0;
  19.701 -  numpubvars=0;
  19.702 -  mainaddr=-1;
  19.703 -  /* count number of public and native functions and public variables */
  19.704 -  for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
  19.705 -    int match=0;
  19.706 -    if (sym->ident==iFUNCTN) {
  19.707 -      if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0)
  19.708 -        match=++numnatives;
  19.709 -      if ((sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
  19.710 -        match=++numpublics;
  19.711 -      if (strcmp(sym->name,uMAINFUNC)==0) {
  19.712 -        assert(sym->vclass==sGLOBAL);
  19.713 -        mainaddr=sym->addr;
  19.714 -      } /* if */
  19.715 -    } else if (sym->ident==iVARIABLE) {
  19.716 -      if ((sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0)
  19.717 -        match=++numpubvars;
  19.718 -    } /* if */
  19.719 -    if (match) {
  19.720 -      char alias[sNAMEMAX+1];
  19.721 -      assert(sym!=NULL);
  19.722 -      if ((sym->usage & uNATIVE)==0 || !lookup_alias(alias,sym->name)) {
  19.723 -        assert(strlen(sym->name)<=sNAMEMAX);
  19.724 -        strcpy(alias,sym->name);
  19.725 -      } /* if */
  19.726 -      nametablesize+=strlen(alias)+1;
  19.727 -    } /* if */
  19.728 -  } /* for */
  19.729 -  assert(numnatives==ntv_funcid);
  19.730 -
  19.731 -  /* count number of libraries */
  19.732 -  numlibraries=0;
  19.733 -  if (pc_addlibtable) {
  19.734 -    for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
  19.735 -      if (constptr->value>0) {
  19.736 -        assert(strlen(constptr->name)>0);
  19.737 -        numlibraries++;
  19.738 -        nametablesize+=strlen(constptr->name)+1;
  19.739 -      } /* if */
  19.740 -    } /* for */
  19.741 -  } /* if */
  19.742 -
  19.743 -  /* count number of public tags */
  19.744 -  numtags=0;
  19.745 -  for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
  19.746 -    if ((constptr->value & PUBLICTAG)!=0) {
  19.747 -      assert(strlen(constptr->name)>0);
  19.748 -      numtags++;
  19.749 -      nametablesize+=strlen(constptr->name)+1;
  19.750 -    } /* if */
  19.751 -  } /* for */
  19.752 -
  19.753 -  /* pad the header to sc_dataalign
  19.754 -   * => thereby the code segment is aligned
  19.755 -   * => since the code segment is padded to a sc_dataalign boundary, the data segment is aligned
  19.756 -   * => and thereby the stack top is aligned too
  19.757 -   */
  19.758 -  assert(sc_dataalign!=0);
  19.759 -  padding= (int)(sc_dataalign - (sizeof hdr + nametablesize) % sc_dataalign);
  19.760 -  if (padding==sc_dataalign)
  19.761 -    padding=0;
  19.762 -
  19.763 -  /* write the abstract machine header */
  19.764 -  memset(&hdr, 0, sizeof hdr);
  19.765 -  hdr.magic=(unsigned short)AMX_MAGIC;
  19.766 -  hdr.file_version=(char)((pc_optimize<=sOPTIMIZE_NOMACRO) ? MAX_FILE_VER_JIT : CUR_FILE_VERSION);
  19.767 -  hdr.amx_version=(char)((pc_optimize<=sOPTIMIZE_NOMACRO) ? MIN_AMX_VER_JIT : MIN_AMX_VERSION);
  19.768 -  hdr.flags=(short)(sc_debug & sSYMBOLIC);
  19.769 -  if (sc_compress)
  19.770 -    hdr.flags|=AMX_FLAG_COMPACT;
  19.771 -  if (sc_debug==0)
  19.772 -    hdr.flags|=AMX_FLAG_NOCHECKS;
  19.773 -  if (pc_memflags & suSLEEP_INSTR)
  19.774 -    hdr.flags|=AMX_FLAG_SLEEP;
  19.775 -  hdr.defsize=sizeof(AMX_FUNCSTUBNT);
  19.776 -  hdr.publics=sizeof hdr; /* public table starts right after the header */
  19.777 -  hdr.natives=hdr.publics + numpublics*sizeof(AMX_FUNCSTUBNT);
  19.778 -  hdr.libraries=hdr.natives + numnatives*sizeof(AMX_FUNCSTUBNT);
  19.779 -  hdr.pubvars=hdr.libraries + numlibraries*sizeof(AMX_FUNCSTUBNT);
  19.780 -  hdr.tags=hdr.pubvars + numpubvars*sizeof(AMX_FUNCSTUBNT);
  19.781 -  hdr.nametable=hdr.tags + numtags*sizeof(AMX_FUNCSTUBNT);
  19.782 -  hdr.cod=hdr.nametable + nametablesize + padding;
  19.783 -  hdr.dat=hdr.cod + code_idx;
  19.784 -  hdr.hea=hdr.dat + glb_declared*sizeof(cell);
  19.785 -  hdr.stp=hdr.hea + pc_stksize*sizeof(cell);
  19.786 -  hdr.cip=mainaddr;
  19.787 -  hdr.size=hdr.hea; /* preset, this is incorrect in case of compressed output */
  19.788 -  pc_writebin(fout,&hdr,sizeof hdr);
  19.789 -
  19.790 -  /* dump zeros up to the rest of the header, so that we can easily "seek" */
  19.791 -  for (nameofs=sizeof hdr; nameofs<hdr.cod; nameofs++)
  19.792 -    pc_writebin(fout, &nullchar, 1);
  19.793 -  nameofs=hdr.nametable+sizeof(int16_t);
  19.794 -
  19.795 -  /* write the public functions table */
  19.796 -  count=0;
  19.797 -  for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
  19.798 -    if (sym->ident==iFUNCTN
  19.799 -        && (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
  19.800 -    {
  19.801 -      assert(sym->vclass==sGLOBAL);
  19.802 -      func.address=sym->addr;
  19.803 -      func.nameofs=nameofs;
  19.804 -      #if BYTE_ORDER==BIG_ENDIAN
  19.805 -        align32(&func.address);
  19.806 -        align32(&func.nameofs);
  19.807 -      #endif
  19.808 -      pc_resetbin(fout,hdr.publics+count*sizeof(AMX_FUNCSTUBNT));
  19.809 -      pc_writebin(fout,&func,sizeof func);
  19.810 -      pc_resetbin(fout,nameofs);
  19.811 -      pc_writebin(fout,sym->name,strlen(sym->name)+1);
  19.812 -      nameofs+=strlen(sym->name)+1;
  19.813 -      count++;
  19.814 -    } /* if */
  19.815 -  } /* for */
  19.816 -
  19.817 -  /* write the natives table */
  19.818 -  /* The native functions must be written in sorted order. (They are
  19.819 -   * sorted on their "id", not on their name). A nested loop to find
  19.820 -   * each successive function would be an O(n^2) operation. But we
  19.821 -   * do not really need to sort, because the native function id's
  19.822 -   * are sequential and there are no duplicates. So we first walk
  19.823 -   * through the complete symbol list and store a pointer to every
  19.824 -   * native function of interest in a temporary table, where its id
  19.825 -   * serves as the index in the table. Now we can walk the table and
  19.826 -   * have all native functions in sorted order.
  19.827 -   */
  19.828 -  if (numnatives>0) {
  19.829 -    nativelist=(symbol **)malloc(numnatives*sizeof(symbol *));
  19.830 -    if (nativelist==NULL)
  19.831 -      error(103);               /* insufficient memory */
  19.832 -    #if !defined NDEBUG
  19.833 -      memset(nativelist,0,numnatives*sizeof(symbol *)); /* for NULL checking */
  19.834 -    #endif
  19.835 -    for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
  19.836 -      if (sym->ident==iFUNCTN && (sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0) {
  19.837 -        assert(sym->addr < numnatives);
  19.838 -        nativelist[(int)sym->addr]=sym;
  19.839 -      } /* if */
  19.840 -    } /* for */
  19.841 -    count=0;
  19.842 -    for (i=0; i<numnatives; i++) {
  19.843 -      char alias[sNAMEMAX+1];
  19.844 -      sym=nativelist[i];
  19.845 -      assert(sym!=NULL);
  19.846 -      if (!lookup_alias(alias,sym->name)) {
  19.847 -        assert(strlen(sym->name)<=sNAMEMAX);
  19.848 -        strcpy(alias,sym->name);
  19.849 -      } /* if */
  19.850 -      assert(sym->vclass==sGLOBAL);
  19.851 -      func.address=0;
  19.852 -      func.nameofs=nameofs;
  19.853 -      #if BYTE_ORDER==BIG_ENDIAN
  19.854 -        align32(&func.address);
  19.855 -        align32(&func.nameofs);
  19.856 -      #endif
  19.857 -      pc_resetbin(fout,hdr.natives+count*sizeof(AMX_FUNCSTUBNT));
  19.858 -      pc_writebin(fout,&func,sizeof func);
  19.859 -      pc_resetbin(fout,nameofs);
  19.860 -      pc_writebin(fout,alias,strlen(alias)+1);
  19.861 -      nameofs+=strlen(alias)+1;
  19.862 -      count++;
  19.863 -    } /* for */
  19.864 -    free(nativelist);
  19.865 -  } /* if */
  19.866 -
  19.867 -  /* write the libraries table */
  19.868 -  if (pc_addlibtable) {
  19.869 -    count=0;
  19.870 -    for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
  19.871 -      if (constptr->value>0) {
  19.872 -        assert(strlen(constptr->name)>0);
  19.873 -        func.address=0;
  19.874 -        func.nameofs=nameofs;
  19.875 -        #if BYTE_ORDER==BIG_ENDIAN
  19.876 -          align32(&func.address);
  19.877 -          align32(&func.nameofs);
  19.878 -        #endif
  19.879 -        pc_resetbin(fout,hdr.libraries+count*sizeof(AMX_FUNCSTUBNT));
  19.880 -        pc_writebin(fout,&func,sizeof func);
  19.881 -        pc_resetbin(fout,nameofs);
  19.882 -        pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
  19.883 -        nameofs+=strlen(constptr->name)+1;
  19.884 -        count++;
  19.885 -      } /* if */
  19.886 -    } /* for */
  19.887 -  } /* if */
  19.888 -
  19.889 -  /* write the public variables table */
  19.890 -  count=0;
  19.891 -  for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
  19.892 -    if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) {
  19.893 -      assert((sym->usage & uDEFINE)!=0);
  19.894 -      assert(sym->vclass==sGLOBAL);
  19.895 -      func.address=sym->addr;
  19.896 -      func.nameofs=nameofs;
  19.897 -      #if BYTE_ORDER==BIG_ENDIAN
  19.898 -        align32(&func.address);
  19.899 -        align32(&func.nameofs);
  19.900 -      #endif
  19.901 -      pc_resetbin(fout,hdr.pubvars+count*sizeof(AMX_FUNCSTUBNT));
  19.902 -      pc_writebin(fout,&func,sizeof func);
  19.903 -      pc_resetbin(fout,nameofs);
  19.904 -      pc_writebin(fout,sym->name,strlen(sym->name)+1);
  19.905 -      nameofs+=strlen(sym->name)+1;
  19.906 -      count++;
  19.907 -    } /* if */
  19.908 -  } /* for */
  19.909 -
  19.910 -  /* write the public tagnames table */
  19.911 -  count=0;
  19.912 -  for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
  19.913 -    if ((constptr->value & PUBLICTAG)!=0) {
  19.914 -      assert(strlen(constptr->name)>0);
  19.915 -      func.address=constptr->value & TAGMASK;
  19.916 -      func.nameofs=nameofs;
  19.917 -      #if BYTE_ORDER==BIG_ENDIAN
  19.918 -        align32(&func.address);
  19.919 -        align32(&func.nameofs);
  19.920 -      #endif
  19.921 -      pc_resetbin(fout,hdr.tags+count*sizeof(AMX_FUNCSTUBNT));
  19.922 -      pc_writebin(fout,&func,sizeof func);
  19.923 -      pc_resetbin(fout,nameofs);
  19.924 -      pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
  19.925 -      nameofs+=strlen(constptr->name)+1;
  19.926 -      count++;
  19.927 -    } /* if */
  19.928 -  } /* for */
  19.929 -
  19.930 -  /* write the "maximum name length" field in the name table */
  19.931 -  assert(nameofs==hdr.nametable+nametablesize);
  19.932 -  pc_resetbin(fout,hdr.nametable);
  19.933 -  count=sNAMEMAX;
  19.934 -  #if BYTE_ORDER==BIG_ENDIAN
  19.935 -    align16(&count);
  19.936 -  #endif
  19.937 -  pc_writebin(fout,&count,sizeof count);
  19.938 -  pc_resetbin(fout,hdr.cod);
  19.939 -
  19.940 -  /* First pass: relocate all labels */
  19.941 -  /* This pass is necessary because the code addresses of labels is only known
  19.942 -   * after the peephole optimization flag. Labels can occur inside expressions
  19.943 -   * (e.g. the conditional operator), which are optimized.
  19.944 -   */
  19.945 -  lbltab=NULL;
  19.946 -  if (sc_labnum>0) {
  19.947 -    /* only very short programs have zero labels; no first pass is needed
  19.948 -     * if there are no labels */
  19.949 -    lbltab=(cell *)malloc(sc_labnum*sizeof(cell));
  19.950 -    if (lbltab==NULL)
  19.951 -      error(103);               /* insufficient memory */
  19.952 -    codeindex=0;
  19.953 -    pc_resetasm(fin);
  19.954 -    while (pc_readasm(fin,line,sizeof line)!=NULL) {
  19.955 -      stripcomment(line);
  19.956 -      instr=skipwhitespace(line);
  19.957 -      /* ignore empty lines */
  19.958 -      if (*instr=='\0')
  19.959 -        continue;
  19.960 -      if (tolower(*instr)=='l' && *(instr+1)=='.') {
  19.961 -        int lindex=(int)hex2long(instr+2,NULL);
  19.962 -        assert(lindex>=0 && lindex<sc_labnum);
  19.963 -        lbltab[lindex]=codeindex;
  19.964 -      } else {
  19.965 -        /* get to the end of the instruction (make use of the '\n' that fgets()
  19.966 -         * added at the end of the line; this way we will *always* drop on a
  19.967 -         * whitespace character) */
  19.968 -        for (params=instr; *params!='\0' && !isspace(*params); params++)
  19.969 -          /* nothing */;
  19.970 -        assert(params>instr);
  19.971 -        i=findopcode(instr,(int)(params-instr));
  19.972 -        if (opcodelist[i].name==NULL) {
  19.973 -          *params='\0';
  19.974 -          error(104,instr);     /* invalid assembler instruction */
  19.975 -        } /* if */
  19.976 -        if (opcodelist[i].segment==sIN_CSEG)
  19.977 -          codeindex+=opcodelist[i].func(NULL,skipwhitespace(params),opcodelist[i].opcode);
  19.978 -      } /* if */
  19.979 -    } /* while */
  19.980 -  } /* if */
  19.981 -
  19.982 -  /* Second pass (actually 2 more passes, one for all code and one for all data) */
  19.983 -  bytes_in=0;
  19.984 -  bytes_out=0;
  19.985 -  for (pass=sIN_CSEG; pass<=sIN_DSEG; pass++) {
  19.986 -    pc_resetasm(fin);
  19.987 -    while (pc_readasm(fin,line,sizeof line)!=NULL) {
  19.988 -      stripcomment(line);
  19.989 -      instr=skipwhitespace(line);
  19.990 -      /* ignore empty lines and labels (labels have a special syntax, so these
  19.991 -       * must be parsed separately) */
  19.992 -      if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.')
  19.993 -        continue;
  19.994 -      /* get to the end of the instruction (make use of the '\n' that fgets()
  19.995 -       * added at the end of the line; this way we will *always* drop on a
  19.996 -       * whitespace character) */
  19.997 -      for (params=instr; *params!='\0' && !isspace(*params); params++)
  19.998 -        /* nothing */;
  19.999 -      assert(params>instr);
 19.1000 -      i=findopcode(instr,(int)(params-instr));
 19.1001 -      assert(opcodelist[i].name!=NULL);
 19.1002 -      if (opcodelist[i].segment==pass)
 19.1003 -        opcodelist[i].func(fout,skipwhitespace(params),opcodelist[i].opcode);
 19.1004 -    } /* while */
 19.1005 -  } /* for */
 19.1006 -  if (bytes_out-bytes_in>0)
 19.1007 -    error(106);         /* compression buffer overflow */
 19.1008 -
 19.1009 -  if (lbltab!=NULL) {
 19.1010 -    free(lbltab);
 19.1011 -    #if !defined NDEBUG
 19.1012 -      lbltab=NULL;
 19.1013 -    #endif
 19.1014 -  } /* if */
 19.1015 -
 19.1016 -  if (sc_compress)
 19.1017 -    hdr.size=pc_lengthbin(fout);/* get this value before appending debug info */
 19.1018 -  if (!writeerror && (sc_debug & sSYMBOLIC)!=0)
 19.1019 -    append_dbginfo(fout);       /* optionally append debug file */
 19.1020 -
 19.1021 -  if (writeerror)
 19.1022 -    error(101,"disk full");
 19.1023 -
 19.1024 -  /* adjust the header */
 19.1025 -  size=(int)hdr.cod;    /* save, the value in the header may be swapped */
 19.1026 -  #if BYTE_ORDER==BIG_ENDIAN
 19.1027 -    align32(&hdr.size);
 19.1028 -    align16(&hdr.magic);
 19.1029 -    align16(&hdr.flags);
 19.1030 -    align16(&hdr.defsize);
 19.1031 -    align32(&hdr.publics);
 19.1032 -    align32(&hdr.natives);
 19.1033 -    align32(&hdr.libraries);
 19.1034 -    align32(&hdr.pubvars);
 19.1035 -    align32(&hdr.tags);
 19.1036 -    align32(&hdr.nametable);
 19.1037 -    align32(&hdr.cod);
 19.1038 -    align32(&hdr.dat);
 19.1039 -    align32(&hdr.hea);
 19.1040 -    align32(&hdr.stp);
 19.1041 -    align32(&hdr.cip);
 19.1042 -  #endif
 19.1043 -  pc_resetbin(fout,0);
 19.1044 -  pc_writebin(fout,&hdr,sizeof hdr);
 19.1045 -
 19.1046 -  /* return the size of the header (including name tables, but excluding code
 19.1047 -   * or data sections)
 19.1048 -   */
 19.1049 -  return size;
 19.1050 -}
 19.1051 -
 19.1052 -static void append_dbginfo(FILE *fout)
 19.1053 -{
 19.1054 -  AMX_DBG_HDR dbghdr;
 19.1055 -  AMX_DBG_LINE dbgline;
 19.1056 -  AMX_DBG_SYMBOL dbgsym;
 19.1057 -  AMX_DBG_SYMDIM dbgidxtag[sDIMEN_MAX];
 19.1058 -  int index,dim,dbgsymdim;
 19.1059 -  char *str,*prevstr,*name,*prevname;
 19.1060 -  ucell codeidx,previdx;
 19.1061 -  constvalue *constptr;
 19.1062 -  char symname[2*sNAMEMAX+16];
 19.1063 -  int16_t id1,id2;
 19.1064 -  ucell address;
 19.1065 -
 19.1066 -  /* header with general information */
 19.1067 -  memset(&dbghdr, 0, sizeof dbghdr);
 19.1068 -  dbghdr.size=sizeof dbghdr;
 19.1069 -  dbghdr.magic=AMX_DBG_MAGIC;
 19.1070 -  dbghdr.file_version=CUR_FILE_VERSION;
 19.1071 -  dbghdr.amx_version=MIN_AMX_VERSION;
 19.1072 -
 19.1073 -  /* first pass: collect the number of items in various tables */
 19.1074 -
 19.1075 -  /* file table */
 19.1076 -  previdx=0;
 19.1077 -  prevstr=NULL;
 19.1078 -  prevname=NULL;
 19.1079 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1080 -    assert(str!=NULL);
 19.1081 -    assert(str[0]!='\0' && str[1]==':');
 19.1082 -    if (str[0]=='F') {
 19.1083 -      codeidx=hex2long(str+2,&name);
 19.1084 -      if (codeidx!=previdx) {
 19.1085 -        if (prevstr!=NULL) {
 19.1086 -          assert(prevname!=NULL);
 19.1087 -          dbghdr.files++;
 19.1088 -          dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
 19.1089 -        } /* if */
 19.1090 -        previdx=codeidx;
 19.1091 -      } /* if */
 19.1092 -      prevstr=str;
 19.1093 -      prevname=skipwhitespace(name);
 19.1094 -    } /* if */
 19.1095 -  } /* for */
 19.1096 -  if (prevstr!=NULL) {
 19.1097 -    assert(prevname!=NULL);
 19.1098 -    dbghdr.files++;
 19.1099 -    dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
 19.1100 -  } /* if */
 19.1101 -
 19.1102 -  /* line number table */
 19.1103 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1104 -    assert(str!=NULL);
 19.1105 -    assert(str[0]!='\0' && str[1]==':');
 19.1106 -    if (str[0]=='L') {
 19.1107 -      dbghdr.lines++;
 19.1108 -      dbghdr.size+=sizeof(AMX_DBG_LINE);
 19.1109 -    } /* if */
 19.1110 -  } /* for */
 19.1111 -
 19.1112 -  /* symbol table */
 19.1113 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1114 -    assert(str!=NULL);
 19.1115 -    assert(str[0]!='\0' && str[1]==':');
 19.1116 -    if (str[0]=='S') {
 19.1117 -      dbghdr.symbols++;
 19.1118 -      name=strchr(str+2,':');
 19.1119 -      assert(name!=NULL);
 19.1120 -      dbghdr.size+=sizeof(AMX_DBG_SYMBOL)+strlen(skipwhitespace(name+1));
 19.1121 -      if ((prevstr=strchr(name,'['))!=NULL)
 19.1122 -        while ((prevstr=strchr(prevstr+1,':'))!=NULL)
 19.1123 -          dbghdr.size+=sizeof(AMX_DBG_SYMDIM);
 19.1124 -    } /* if */
 19.1125 -  } /* for */
 19.1126 -
 19.1127 -  /* tag table */
 19.1128 -  for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1129 -    assert(strlen(constptr->name)>0);
 19.1130 -    dbghdr.tags++;
 19.1131 -    dbghdr.size+=sizeof(AMX_DBG_TAG)+strlen(constptr->name);
 19.1132 -  } /* for */
 19.1133 -
 19.1134 -  /* automaton table */
 19.1135 -  for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1136 -    assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0);
 19.1137 -    dbghdr.automatons++;
 19.1138 -    dbghdr.size+=sizeof(AMX_DBG_MACHINE)+strlen(constptr->name);
 19.1139 -  } /* for */
 19.1140 -
 19.1141 -  /* state table */
 19.1142 -  for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1143 -    assert(strlen(constptr->name)>0);
 19.1144 -    dbghdr.states++;
 19.1145 -    dbghdr.size+=sizeof(AMX_DBG_STATE)+strlen(constptr->name);
 19.1146 -  } /* for */
 19.1147 -
 19.1148 -
 19.1149 -  /* pass 2: generate the tables */
 19.1150 -  #if BYTE_ORDER==BIG_ENDIAN
 19.1151 -    align32((uint32_t*)&dbghdr.size);
 19.1152 -    align16(&dbghdr.magic);
 19.1153 -    align16(&dbghdr.flags);
 19.1154 -    align16(&dbghdr.files);
 19.1155 -    align16(&dbghdr.lines);
 19.1156 -    align16(&dbghdr.symbols);
 19.1157 -    align16(&dbghdr.tags);
 19.1158 -    align16(&dbghdr.automatons);
 19.1159 -    align16(&dbghdr.states);
 19.1160 -  #endif
 19.1161 -  writeerror |= !pc_writebin(fout,&dbghdr,sizeof dbghdr);
 19.1162 -
 19.1163 -  /* file table */
 19.1164 -  previdx=0;
 19.1165 -  prevstr=NULL;
 19.1166 -  prevname=NULL;
 19.1167 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1168 -    assert(str!=NULL);
 19.1169 -    assert(str[0]!='\0' && str[1]==':');
 19.1170 -    if (str[0]=='F') {
 19.1171 -      codeidx=hex2long(str+2,&name);
 19.1172 -      if (codeidx!=previdx) {
 19.1173 -        if (prevstr!=NULL) {
 19.1174 -          assert(prevname!=NULL);
 19.1175 -          #if BYTE_ORDER==BIG_ENDIAN
 19.1176 -            aligncell(&previdx);
 19.1177 -          #endif
 19.1178 -          writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
 19.1179 -          writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
 19.1180 -        } /* if */
 19.1181 -        previdx=codeidx;
 19.1182 -      } /* if */
 19.1183 -      prevstr=str;
 19.1184 -      prevname=skipwhitespace(name);
 19.1185 -    } /* if */
 19.1186 -  } /* for */
 19.1187 -  if (prevstr!=NULL) {
 19.1188 -    assert(prevname!=NULL);
 19.1189 -    #if BYTE_ORDER==BIG_ENDIAN
 19.1190 -      aligncell(&previdx);
 19.1191 -    #endif
 19.1192 -    writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
 19.1193 -    writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
 19.1194 -  } /* if */
 19.1195 -
 19.1196 -  /* line number table */
 19.1197 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1198 -    assert(str!=NULL);
 19.1199 -    assert(str[0]!='\0' && str[1]==':');
 19.1200 -    if (str[0]=='L') {
 19.1201 -      dbgline.address=hex2long(str+2,&str);
 19.1202 -      dbgline.line=(int32_t)hex2long(str,NULL);
 19.1203 -      #if BYTE_ORDER==BIG_ENDIAN
 19.1204 -        aligncell(&dbgline.address);
 19.1205 -        align32(&dbgline.line);
 19.1206 -      #endif
 19.1207 -      writeerror |= !pc_writebin(fout,&dbgline,sizeof dbgline);
 19.1208 -    } /* if */
 19.1209 -  } /* for */
 19.1210 -
 19.1211 -  /* symbol table */
 19.1212 -  for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
 19.1213 -    assert(str!=NULL);
 19.1214 -    assert(str[0]!='\0' && str[1]==':');
 19.1215 -    if (str[0]=='S') {
 19.1216 -      dbgsym.address=hex2long(str+2,&str);
 19.1217 -      dbgsym.tag=(int16_t)hex2long(str,&str);
 19.1218 -      str=skipwhitespace(str);
 19.1219 -      assert(*str==':');
 19.1220 -      name=skipwhitespace(str+1);
 19.1221 -      str=strchr(name,' ');
 19.1222 -      assert(str!=NULL);
 19.1223 -      assert((int)(str-name)<sizeof symname);
 19.1224 -      strlcpy(symname,name,(int)(str-name)+1);
 19.1225 -      dbgsym.codestart=hex2long(str,&str);
 19.1226 -      dbgsym.codeend=hex2long(str,&str);
 19.1227 -      dbgsym.ident=(char)hex2long(str,&str);
 19.1228 -      dbgsym.vclass=(char)hex2long(str,&str);
 19.1229 -      dbgsym.dim=0;
 19.1230 -      str=skipwhitespace(str);
 19.1231 -      if (*str=='[') {
 19.1232 -        while (*(str=skipwhitespace(str+1))!=']') {
 19.1233 -          dbgidxtag[dbgsym.dim].tag=(int16_t)hex2long(str,&str);
 19.1234 -          str=skipwhitespace(str);
 19.1235 -          assert(*str==':');
 19.1236 -          dbgidxtag[dbgsym.dim].size=hex2long(str+1,&str);
 19.1237 -          dbgsym.dim++;
 19.1238 -        } /* while */
 19.1239 -      } /* if */
 19.1240 -      dbgsymdim = dbgsym.dim;
 19.1241 -      #if BYTE_ORDER==BIG_ENDIAN
 19.1242 -        aligncell(&dbgsym.address);
 19.1243 -        align16(&dbgsym.tag);
 19.1244 -        aligncell(&dbgsym.codestart);
 19.1245 -        aligncell(&dbgsym.codeend);
 19.1246 -        align16(&dbgsym.dim);
 19.1247 -      #endif
 19.1248 -      writeerror |= !pc_writebin(fout,&dbgsym,offsetof(AMX_DBG_SYMBOL, name));
 19.1249 -      writeerror |= !pc_writebin(fout,symname,strlen(symname)+1);
 19.1250 -      for (dim=0; dim<dbgsymdim; dim++) {
 19.1251 -        #if BYTE_ORDER==BIG_ENDIAN
 19.1252 -          align16(&dbgidxtag[dim].tag);
 19.1253 -          aligncell(&dbgidxtag[dim].size);
 19.1254 -        #endif
 19.1255 -        writeerror |= !pc_writebin(fout,&dbgidxtag[dim],sizeof dbgidxtag[dim]);
 19.1256 -      } /* for */
 19.1257 -    } /* if */
 19.1258 -  } /* for */
 19.1259 -
 19.1260 -  /* tag table */
 19.1261 -  for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1262 -    assert(strlen(constptr->name)>0);
 19.1263 -    id1=(int16_t)(constptr->value & TAGMASK);
 19.1264 -    #if BYTE_ORDER==BIG_ENDIAN
 19.1265 -      align16(&id1);
 19.1266 -    #endif
 19.1267 -    writeerror |= !pc_writebin(fout,&id1,sizeof id1);
 19.1268 -    writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
 19.1269 -  } /* for */
 19.1270 -
 19.1271 -  /* automaton table */
 19.1272 -  for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1273 -    assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0);
 19.1274 -    id1=(int16_t)constptr->index;
 19.1275 -    address=(ucell)constptr->value;
 19.1276 -    #if BYTE_ORDER==BIG_ENDIAN
 19.1277 -      align16(&id1);
 19.1278 -      aligncell(&address);
 19.1279 -    #endif
 19.1280 -    writeerror |= !pc_writebin(fout,&id1,sizeof id1);
 19.1281 -    writeerror |= !pc_writebin(fout,&address,sizeof address);
 19.1282 -    writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
 19.1283 -  } /* for */
 19.1284 -
 19.1285 -  /* state table */
 19.1286 -  for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
 19.1287 -    assert(strlen(constptr->name)>0);
 19.1288 -    id1=(int16_t)constptr->value;
 19.1289 -    id2=(int16_t)constptr->index;
 19.1290 -    address=(ucell)constptr->value;
 19.1291 -    #if BYTE_ORDER==BIG_ENDIAN
 19.1292 -      align16(&id1);
 19.1293 -      align16(&id2);
 19.1294 -    #endif
 19.1295 -    writeerror |= !pc_writebin(fout,&id1,sizeof id1);
 19.1296 -    writeerror |= !pc_writebin(fout,&id2,sizeof id2);
 19.1297 -    writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
 19.1298 -  } /* for */
 19.1299 -
 19.1300 -  delete_dbgstringtable();
 19.1301 -}
    20.1 --- a/compiler-init/sc7.c	Sat Jul 15 01:36:48 2006 +0000
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,703 +0,0 @@
    20.4 -/*  Pawn compiler - Staging buffer and optimizer
    20.5 - *
    20.6 - *  The staging buffer
    20.7 - *  ------------------
    20.8 - *  The staging buffer allows buffered output of generated code, deletion
    20.9 - *  of redundant code, optimization by a tinkering process and reversing
   20.10 - *  the ouput of evaluated expressions (which is used for the reversed
   20.11 - *  evaluation of arguments in functions).
   20.12 - *  Initially, stgwrite() writes to the file directly, but after a call to
   20.13 - *  stgset(TRUE), output is redirected to the buffer. After a call to
   20.14 - *  stgset(FALSE), stgwrite()'s output is directed to the file again. Thus
   20.15 - *  only one routine is used for writing to the output, which can be
   20.16 - *  buffered output or direct output.
   20.17 - *
   20.18 - *  staging buffer variables:   stgbuf  - the buffer
   20.19 - *                              stgidx  - current index in the staging buffer
   20.20 - *                              staging - if true, write to the staging buffer;
   20.21 - *                                        if false, write to file directly.
   20.22 - *
   20.23 - * The peephole optimizer uses a dual "pipeline". The staging buffer (described
   20.24 - * above) gets optimized for each expression or sub-expression in a function
   20.25 - * call. The peephole optimizer is recursive, but it does not span multiple
   20.26 - * sub-expressions. However, the data gets written to a second buffer that
   20.27 - * behaves much like the staging buffer. This second buffer gathers all
   20.28 - * optimized strings from the staging buffer for a complete expression. The
   20.29 - * peephole optmizer then runs over this second buffer to find optimzations
   20.30 - * across function parameter boundaries.
   20.31 - *
   20.32 - *
   20.33 - *  Copyright (c) ITB CompuPhase, 1997-2006
   20.34 - *
   20.35 - *  This software is provided "as-is", without any express or implied warranty.
   20.36 - *  In no event will the authors be held liable for any damages arising from
   20.37 - *  the use of this software.
   20.38 - *
   20.39 - *  Permission is granted to anyone to use this software for any purpose,
   20.40 - *  including commercial applications, and to alter it and redistribute it
   20.41 - *  freely, subject to the following restrictions:
   20.42 - *
   20.43 - *  1.  The origin of this software must not be misrepresented; you must not
   20.44 - *      claim that you wrote the original software. If you use this software in
   20.45 - *      a product, an acknowledgment in the product documentation would be
   20.46 - *      appreciated but is not required.
   20.47 - *  2.  Altered source versions must be plainly marked as such, and must not be
   20.48 - *      misrepresented as being the original software.
   20.49 - *  3.  This notice may not be removed or altered from any source distribution.
   20.50 - *
   20.51 - *  Version: $Id: sc7.c 3579 2006-06-06 13:35:29Z thiadmer $
   20.52 - */
   20.53 -#include <assert.h>
   20.54 -#include <stdio.h>
   20.55 -#include <stdlib.h>     /* for atoi() */
   20.56 -#include <string.h>
   20.57 -#include <ctype.h>
   20.58 -#if defined FORTIFY
   20.59 -  #include <alloc/fortify.h>
   20.60 -#endif
   20.61 -#include "sc.h"
   20.62 -
   20.63 -#if defined _MSC_VER
   20.64 -  #pragma warning(push)
   20.65 -  #pragma warning(disable:4125)  /* decimal digit terminates octal escape sequence */
   20.66 -#endif
   20.67 -
   20.68 -#include "sc7.scp"
   20.69 -
   20.70 -#if defined _MSC_VER
   20.71 -  #pragma warning(pop)
   20.72 -#endif
   20.73 -
   20.74 -static int stgstring(char *start,char *end);
   20.75 -static void stgopt(char *start,char *end,int (*outputfunc)(char *str));
   20.76 -
   20.77 -
   20.78 -#define sSTG_GROW   512
   20.79 -#define sSTG_MAX    20480
   20.80 -
   20.81 -static char *stgbuf=NULL;
   20.82 -static int stgmax=0;    /* current size of the staging buffer */
   20.83 -
   20.84 -static char *stgpipe=NULL;
   20.85 -static int pipemax=0;   /* current size of the stage pipe, a second staging buffer */
   20.86 -static int pipeidx=0;
   20.87 -
   20.88 -#define CHECK_STGBUFFER(index) if ((int)(index)>=stgmax)  grow_stgbuffer(&stgbuf, stgmax, (index)+1)
   20.89 -#define CHECK_STGPIPE(index)   if ((int)(index)>=pipemax) grow_stgbuffer(&stgpipe, pipemax, (index)+1)
   20.90 -
   20.91 -static void grow_stgbuffer(char **buffer, int curmax, int requiredsize)
   20.92 -{
   20.93 -  char *p;
   20.94 -  int clear= (*buffer==NULL); /* if previously none, empty buffer explicitly */
   20.95 -
   20.96 -  assert(curmax<requiredsize);
   20.97 -  /* if the staging buffer (holding intermediate code for one line) grows
   20.98 -   * over a few kBytes, there is probably a run-away expression
   20.99 -   */
  20.100 -  if (requiredsize>sSTG_MAX)
  20.101 -    error(102,"staging buffer");    /* staging buffer overflow (fatal error) */
  20.102 -  curmax=requiredsize+sSTG_GROW;
  20.103 -  if (*buffer!=NULL)
  20.104 -    p=(char *)realloc(*buffer,curmax*sizeof(char));
  20.105 -  else
  20.106 -    p=(char *)malloc(curmax*sizeof(char));
  20.107 -  if (p==NULL)
  20.108 -    error(102,"staging buffer");    /* staging buffer overflow (fatal error) */
  20.109 -  *buffer=p;
  20.110 -  if (clear)
  20.111 -    **buffer='\0';
  20.112 -}
  20.113 -
  20.114 -SC_FUNC void stgbuffer_cleanup(void)
  20.115 -{
  20.116 -  if (stgbuf!=NULL) {
  20.117 -    free(stgbuf);
  20.118 -    stgbuf=NULL;
  20.119 -    stgmax=0;
  20.120 -  } /* if */
  20.121 -  if (stgpipe!=NULL) {
  20.122 -    free(stgpipe);
  20.123 -    stgpipe=NULL;
  20.124 -    pipemax=0;
  20.125 -    pipeidx=0;
  20.126 -  } /* if */
  20.127 -}
  20.128 -
  20.129 -/* the variables "stgidx" and "staging" are declared in "scvars.c" */
  20.130 -
  20.131 -/*  stgmark
  20.132 - *
  20.133 - *  Copies a mark into the staging buffer. At this moment there are three
  20.134 - *  possible marks:
  20.135 - *     sSTARTREORDER    identifies the beginning of a series of expression
  20.136 - *                      strings that must be written to the output file in
  20.137 - *                      reordered order
  20.138 - *    sENDREORDER       identifies the end of 'reverse evaluation'
  20.139 - *    sEXPRSTART + idx  only valid within a block that is evaluated in
  20.140 - *                      reordered order, it identifies the start of an
  20.141 - *                      expression; the "idx" value is the argument position
  20.142 - *
  20.143 - *  Global references: stgidx  (altered)
  20.144 - *                     stgbuf  (altered)
  20.145 - *                     staging (referred to only)
  20.146 - */
  20.147 -SC_FUNC void stgmark(char mark)
  20.148 -{
  20.149 -  if (staging) {
  20.150 -    CHECK_STGBUFFER(stgidx);
  20.151 -    stgbuf[stgidx++]=mark;
  20.152 -  } /* if */
  20.153 -}
  20.154 -
  20.155 -static int rebuffer(char *str)
  20.156 -{
  20.157 -  if (sc_status==statWRITE) {
  20.158 -    if (pipeidx>=2 && stgpipe[pipeidx-1]=='\0' && stgpipe[pipeidx-2]!='\n')
  20.159 -      pipeidx-=1;                      /* overwrite last '\0' */
  20.160 -    while (*str!='\0') {               /* copy to staging buffer */
  20.161 -      CHECK_STGPIPE(pipeidx);
  20.162 -      stgpipe[pipeidx++]=*str++;
  20.163 -    } /* while */
  20.164 -    CHECK_STGPIPE(pipeidx);
  20.165 -    stgpipe[pipeidx++]='\0';
  20.166 -  } /* if */
  20.167 -  return TRUE;
  20.168 -}
  20.169 -
  20.170 -static int filewrite(char *str)
  20.171 -{
  20.172 -  if (sc_status==statWRITE)
  20.173 -    return pc_writeasm(outf,str);
  20.174 -  return TRUE;
  20.175 -}
  20.176 -
  20.177 -/*  stgwrite
  20.178 - *
  20.179 - *  Writes the string "st" to the staging buffer or to the output file. In the
  20.180 - *  case of writing to the staging buffer, the terminating byte of zero is
  20.181 - *  copied too, but... the optimizer can only work on complete lines (not on
  20.182 - *  fractions of it. Therefore if the string is staged, if the last character
  20.183 - *  written to the buffer is a '\0' and the previous-to-last is not a '\n',
  20.184 - *  the string is concatenated to the last string in the buffer (the '\0' is
  20.185 - *  overwritten). This also means an '\n' used in the middle of a string isn't
  20.186 - *  recognized and could give wrong results with the optimizer.
  20.187 - *  Even when writing to the output file directly, all strings are buffered
  20.188 - *  until a whole line is complete.
  20.189 - *
  20.190 - *  Global references: stgidx  (altered)
  20.191 - *                     stgbuf  (altered)
  20.192 - *                     staging (referred to only)
  20.193 - */
  20.194 -SC_FUNC void stgwrite(const char *st)
  20.195 -{
  20.196 -  int len;
  20.197 -
  20.198 -  if (staging) {
  20.199 -    assert(stgidx==0 || stgbuf!=NULL);  /* staging buffer must be valid if there is (apparently) something in it */
  20.200 -    if (stgidx>=2 && stgbuf[stgidx-1]=='\0' && stgbuf[stgidx-2]!='\n')
  20.201 -      stgidx-=1;                       /* overwrite last '\0' */
  20.202 -    while (*st!='\0') {                /* copy to staging buffer */
  20.203 -      CHECK_STGBUFFER(stgidx);
  20.204 -      stgbuf[stgidx++]=*st++;
  20.205 -    } /* while */
  20.206 -    CHECK_STGBUFFER(stgidx);
  20.207 -    stgbuf[stgidx++]='\0';
  20.208 -  } else {
  20.209 -    len=(stgbuf!=NULL) ? strlen(stgbuf) : 0;
  20.210 -    CHECK_STGBUFFER(len+strlen(st)+1);
  20.211 -    strcat(stgbuf,st);
  20.212 -    len=strlen(stgbuf);
  20.213 -    if (len>0 && stgbuf[len-1]=='\n') {
  20.214 -      filewrite(stgbuf);
  20.215 -      stgbuf[0]='\0';
  20.216 -    } /* if */
  20.217 -  } /* if */
  20.218 -}
  20.219 -
  20.220 -/*  stgout
  20.221 - *
  20.222 - *  Writes the staging buffer to the output file via stgstring() (for
  20.223 - *  reversing expressions in the buffer) and stgopt() (for optimizing). It
  20.224 - *  resets "stgidx".
  20.225 - *
  20.226 - *  Global references: stgidx  (altered)
  20.227 - *                     stgbuf  (referred to only)
  20.228 - *                     staging (referred to only)
  20.229 - */
  20.230 -SC_FUNC void stgout(int index)
  20.231 -{
  20.232 -  int reordered=0;
  20.233 -  int idx;
  20.234 -
  20.235 -  if (!staging)
  20.236 -    return;
  20.237 -  assert(pipeidx==0);
  20.238 -
  20.239 -  /* first pass: sub-expressions */
  20.240 -  if (sc_status==statWRITE)
  20.241 -    reordered=stgstring(&stgbuf[index],&stgbuf[stgidx]);
  20.242 -  stgidx=index;
  20.243 -
  20.244 -  /* second pass: optimize the buffer created in the first pass */
  20.245 -  if (sc_status==statWRITE) {
  20.246 -    if (reordered) {
  20.247 -      stgopt(stgpipe,stgpipe+pipeidx,filewrite);
  20.248 -    } else {
  20.249 -      /* there is no sense in re-optimizing if the order of the sub-expressions
  20.250 -       * did not change; so output directly
  20.251 -       */
  20.252 -      for (idx=0; idx<pipeidx; idx+=strlen(stgpipe+idx)+1)
  20.253 -        filewrite(stgpipe+idx);
  20.254 -    } /* if */
  20.255 -  } /* if */
  20.256 -  pipeidx=0;  /* reset second pipe */
  20.257 -}
  20.258 -
  20.259 -typedef struct {
  20.260 -  char *start,*end;
  20.261 -} argstack;
  20.262 -
  20.263 -/*  stgstring
  20.264 - *
  20.265 - *  Analyses whether code strings should be output to the file as they appear
  20.266 - *  in the staging buffer or whether portions of it should be re-ordered.
  20.267 - *  Re-ordering takes place in function argument lists; Pawn passes arguments
  20.268 - *  to functions from right to left. When arguments are "named" rather than
  20.269 - *  positional, the order in the source stream is indeterminate.
  20.270 - *  This function calls itself recursively in case it needs to re-order code
  20.271 - *  strings, and it uses a private stack (or list) to mark the start and the
  20.272 - *  end of expressions in their correct (reversed) order.
  20.273 - *  In any case, stgstring() sends a block as large as possible to the
  20.274 - *  optimizer stgopt().
  20.275 - *
  20.276 - *  In "reorder" mode, each set of code strings must start with the token
  20.277 - *  sEXPRSTART, even the first. If the token sSTARTREORDER is represented
  20.278 - *  by '[', sENDREORDER by ']' and sEXPRSTART by '|' the following applies:
  20.279 - *     '[]...'     valid, but useless; no output
  20.280 - *     '[|...]     valid, but useless; only one string
  20.281 - *     '[|...|...] valid and usefull
  20.282 - *     '[...|...]  invalid, first string doesn't start with '|'
  20.283 - *     '[|...|]    invalid
  20.284 - */
  20.285 -static int stgstring(char *start,char *end)
  20.286 -{
  20.287 -  char *ptr;
  20.288 -  int nest,argc,arg;
  20.289 -  argstack *stack;
  20.290 -  int reordered=0;
  20.291 -
  20.292 -  while (start<end) {
  20.293 -    if (*start==sSTARTREORDER) {
  20.294 -      start+=1;         /* skip token */
  20.295 -      /* allocate a argstack with sMAXARGS items */
  20.296 -      stack=(argstack *)malloc(sMAXARGS*sizeof(argstack));
  20.297 -      if (stack==NULL)
  20.298 -        error(103);     /* insufficient memory */
  20.299 -      reordered=1;      /* mark that the expression is reordered */
  20.300 -      nest=1;           /* nesting counter */
  20.301 -      argc=0;           /* argument counter */
  20.302 -      arg=-1;           /* argument index; no valid argument yet */
  20.303 -      do {
  20.304 -        switch (*start) {
  20.305 -        case sSTARTREORDER:
  20.306 -          nest++;
  20.307 -          start++;
  20.308 -          break;
  20.309 -        case sENDREORDER:
  20.310 -          nest--;
  20.311 -          start++;
  20.312 -          break;
  20.313 -        default:
  20.314 -          if ((*start & sEXPRSTART)==sEXPRSTART) {
  20.315 -            if (nest==1) {
  20.316 -              if (arg>=0)
  20.317 -                stack[arg].end=start-1; /* finish previous argument */
  20.318 -              arg=(unsigned char)*start - sEXPRSTART;
  20.319 -              stack[arg].start=start+1;
  20.320 -              if (arg>=argc)
  20.321 -                argc=arg+1;
  20.322 -            } /* if */
  20.323 -            start++;
  20.324 -          } else {
  20.325 -            start+=strlen(start)+1;
  20.326 -          } /* if */
  20.327 -        } /* switch */
  20.328 -      } while (nest); /* enddo */
  20.329 -      if (arg>=0)
  20.330 -        stack[arg].end=start-1;   /* finish previous argument */
  20.331 -      while (argc>0) {
  20.332 -        argc--;
  20.333 -        stgstring(stack[argc].start,stack[argc].end);
  20.334 -      } /* while */
  20.335 -      free(stack);
  20.336 -    } else {
  20.337 -      ptr=start;
  20.338 -      while (ptr<end && *ptr!=sSTARTREORDER)
  20.339 -        ptr+=strlen(ptr)+1;
  20.340 -      stgopt(start,ptr,rebuffer);
  20.341 -      start=ptr;
  20.342 -    } /* if */
  20.343 -  } /* while */
  20.344 -  return reordered;
  20.345 -}
  20.346 -
  20.347 -/*  stgdel
  20.348 - *
  20.349 - *  Scraps code from the staging buffer by resetting "stgidx" to "index".
  20.350 - *
  20.351 - *  Global references: stgidx (altered)
  20.352 - *                     staging (reffered to only)
  20.353 - */
  20.354 -SC_FUNC void stgdel(int index,cell code_index)
  20.355 -{
  20.356 -  if (staging) {
  20.357 -    stgidx=index;
  20.358 -    code_idx=code_index;
  20.359 -  } /* if */
  20.360 -}
  20.361 -
  20.362 -SC_FUNC int stgget(int *index,cell *code_index)
  20.363 -{
  20.364 -  if (staging) {
  20.365 -    *index=stgidx;
  20.366 -    *code_index=code_idx;
  20.367 -  } /* if */
  20.368 -  return staging;
  20.369 -}
  20.370 -
  20.371 -/*  stgset
  20.372 - *
  20.373 - *  Sets staging on or off. If it's turned off, the staging buffer must be
  20.374 - *  initialized to an empty string. If it's turned on, the routine makes sure
  20.375 - *  the index ("stgidx") is set to 0 (it should already be 0).
  20.376 - *
  20.377 - *  Global references: staging  (altered)
  20.378 - *                     stgidx   (altered)
  20.379 - *                     stgbuf   (contents altered)
  20.380 - */
  20.381 -SC_FUNC void stgset(int onoff)
  20.382 -{
  20.383 -  staging=onoff;
  20.384 -  if (staging){
  20.385 -    assert(stgidx==0);
  20.386 -    stgidx=0;
  20.387 -    CHECK_STGBUFFER(stgidx);
  20.388 -    /* write any contents that may be put in the buffer by stgwrite()
  20.389 -     * when "staging" was 0
  20.390 -     */
  20.391 -    if (strlen(stgbuf)>0)
  20.392 -      filewrite(stgbuf);
  20.393 -  } /* if */
  20.394 -  stgbuf[0]='\0';
  20.395 -}
  20.396 -
  20.397 -/* phopt_init
  20.398 - * Initialize all sequence strings of the peehole optimizer. The strings
  20.399 - * are embedded in the .EXE file in compressed format, here we expand
  20.400 - * them (and allocate memory for the sequences).
  20.401 - */
  20.402 -static SEQUENCE *sequences;
  20.403 -
  20.404 -SC_FUNC int phopt_init(void)
  20.405 -{
  20.406 -  int number, i, len;
  20.407 -  char str[160];
  20.408 -
  20.409 -  /* count number of sequences */
  20.410 -  for (number=0; sequences_cmp[number].find!=NULL; number++)
  20.411 -    /* nothing */;
  20.412 -  number++;             /* include an item for the NULL terminator */
  20.413 -
  20.414 -  if ((sequences=(SEQUENCE*)malloc(number * sizeof(SEQUENCE)))==NULL)
  20.415 -    return FALSE;
  20.416 -
  20.417 -  /* pre-initialize all to NULL (in case of failure) */
  20.418 -  for (i=0; i<number; i++) {
  20.419 -    sequences[i].find=NULL;
  20.420 -    sequences[i].replace=NULL;
  20.421 -    sequences[i].savesize=0;
  20.422 -  } /* for */
  20.423 -
  20.424 -  /* expand all strings */
  20.425 -  for (i=0; i<number-1; i++) {
  20.426 -    len = strexpand(str,(unsigned char*)sequences_cmp[i].find,sizeof str,SCPACK_TABLE);
  20.427 -    assert(len<=sizeof str);
  20.428 -    assert(len==(int)strlen(str)+1);
  20.429 -    sequences[i].find=(char*)malloc(len);
  20.430 -    if (sequences[i].find!=NULL)
  20.431 -      strcpy(sequences[i].find,str);
  20.432 -    len = strexpand(str,(unsigned char*)sequences_cmp[i].replace,sizeof str,SCPACK_TABLE);
  20.433 -    assert(len<=sizeof str);
  20.434 -    assert(len==(int)strlen(str)+1);
  20.435 -    sequences[i].replace=(char*)malloc(len);
  20.436 -    if (sequences[i].replace!=NULL)
  20.437 -      strcpy(sequences[i].replace,str);
  20.438 -    sequences[i].savesize=sequences_cmp[i].savesize;
  20.439 -    if (sequences[i].find==NULL || sequences[i].replace==NULL)
  20.440 -      return phopt_cleanup();
  20.441 -  } /* for */
  20.442 -
  20.443 -  return TRUE;
  20.444 -}
  20.445 -
  20.446 -SC_FUNC int phopt_cleanup(void)
  20.447 -{
  20.448 -  int i;
  20.449 -  if (sequences!=NULL) {
  20.450 -    i=0;
  20.451 -    while (sequences[i].find!=NULL || sequences[i].replace!=NULL) {
  20.452 -      if (sequences[i].find!=NULL)
  20.453 -        free(sequences[i].find);
  20.454 -      if (sequences[i].replace!=NULL)
  20.455 -        free(sequences[i].replace);
  20.456 -      i++;
  20.457 -    } /* while */
  20.458 -    free(sequences);
  20.459 -    sequences=NULL;
  20.460 -  } /* if */
  20.461 -  return FALSE;
  20.462 -}
  20.463 -
  20.464 -#define MAX_OPT_VARS    5
  20.465 -#define MAX_OPT_CAT     5       /* max. values that are concatenated */
  20.466 -#if sNAMEMAX > (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
  20.467 -  #define MAX_ALIAS       sNAMEMAX
  20.468 -#else
  20.469 -  #define MAX_ALIAS       (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
  20.470 -#endif
  20.471 -
  20.472 -static int matchsequence(char *start,char *end,char *pattern,
  20.473 -                         char symbols[MAX_OPT_VARS][MAX_ALIAS+1],
  20.474 -                         int *match_length)
  20.475 -{
  20.476 -  int var,i;
  20.477 -  char str[MAX_ALIAS+1];
  20.478 -  char *start_org=start;
  20.479 -  cell value;
  20.480 -  char *ptr;
  20.481 -
  20.482 -  *match_length=0;
  20.483 -  for (var=0; var<MAX_OPT_VARS; var++)
  20.484 -    symbols[var][0]='\0';
  20.485 -
  20.486 -  while (*start=='\t' || *start==' ')
  20.487 -    start++;
  20.488 -  while (*pattern) {
  20.489 -    if (start>=end)
  20.490 -      return FALSE;
  20.491 -    switch (*pattern) {
  20.492 -    case '%':   /* new "symbol" */
  20.493 -      pattern++;
  20.494 -      assert(isdigit(*pattern));
  20.495 -      var=atoi(pattern) - 1;
  20.496 -      assert(var>=0 && var<MAX_OPT_VARS);
  20.497 -      assert(*start=='-' || alphanum(*start));
  20.498 -      for (i=0; start<end && (*start=='-' || *start=='+' || alphanum(*start)); i++,start++) {
  20.499 -        assert(i<=MAX_ALIAS);
  20.500 -        str[i]=*start;
  20.501 -      } /* for */
  20.502 -      str[i]='\0';
  20.503 -      if (symbols[var][0]!='\0') {
  20.504 -        if (strcmp(symbols[var],str)!=0)
  20.505 -          return FALSE; /* symbols should be identical */
  20.506 -      } else {
  20.507 -        strcpy(symbols[var],str);
  20.508 -      } /* if */
  20.509 -      break;
  20.510 -    case '-':
  20.511 -      value=-strtol(pattern+1,&pattern,16);
  20.512 -      ptr=itoh((ucell)value);
  20.513 -      while (*ptr!='\0') {
  20.514 -        if (tolower(*start) != tolower(*ptr))
  20.515 -          return FALSE;
  20.516 -        start++;
  20.517 -        ptr++;
  20.518 -      } /* while */
  20.519 -      pattern--;  /* there is an increment following at the end of the loop */
  20.520 -      break;
  20.521 -    case ' ':
  20.522 -      if (*start!='\t' && *start!=' ')
  20.523 -        return FALSE;
  20.524 -      while (start<end && (*start=='\t' || *start==' '))
  20.525 -        start++;
  20.526 -      break;
  20.527 -    case '!':
  20.528 -      while (start<end && (*start=='\t' || *start==' '))
  20.529 -        start++;                /* skip trailing white space */
  20.530 -      if (*start==';')
  20.531 -        while (start<end && *start!='\n')
  20.532 -          start++;              /* skip trailing comment */
  20.533 -      if (*start!='\n')
  20.534 -        return FALSE;
  20.535 -      assert(*(start+1)=='\0');
  20.536 -      start+=2;                 /* skip '\n' and '\0' */
  20.537 -      if (*(pattern+1)!='\0')
  20.538 -        while (start<end && *start=='\t' || *start==' ')
  20.539 -          start++;              /* skip leading white space of next instruction */
  20.540 -      break;
  20.541 -    default:
  20.542 -      if (tolower(*start) != tolower(*pattern))
  20.543 -        return FALSE;
  20.544 -      start++;
  20.545 -    } /* switch */
  20.546 -    pattern++;
  20.547 -  } /* while */
  20.548 -
  20.549 -  *match_length=(int)(start-start_org);
  20.550 -  return TRUE;
  20.551 -}
  20.552 -
  20.553 -static char *replacesequence(char *pattern,char symbols[MAX_OPT_VARS][MAX_ALIAS+1],int *repl_length)
  20.554 -{
  20.555 -  char *lptr;
  20.556 -  int var;
  20.557 -  char *buffer;
  20.558 -
  20.559 -  /* calculate the length of the new buffer
  20.560 -   * this is the length of the pattern plus the length of all symbols (note
  20.561 -   * that the same symbol may occur multiple times in the pattern) plus
  20.562 -   * line endings and startings ('\t' to start a line and '\n\0' to end one)
  20.563 -   */
  20.564 -  assert(repl_length!=NULL);
  20.565 -  *repl_length=0;
  20.566 -  lptr=pattern;
  20.567 -  while (*lptr) {
  20.568 -    switch (*lptr) {
  20.569 -    case '%':
  20.570 -      lptr++;           /* skip '%' */
  20.571 -      assert(isdigit(*lptr));
  20.572 -      var=atoi(lptr) - 1;
  20.573 -      assert(var>=0 && var<MAX_OPT_VARS);
  20.574 -      assert(symbols[var][0]!='\0');    /* variable should be defined */
  20.575 -      *repl_length+=strlen(symbols[var]);
  20.576 -      break;
  20.577 -    case '!':
  20.578 -      *repl_length+=3;  /* '\t', '\n' & '\0' */
  20.579 -      break;
  20.580 -    default:
  20.581 -      *repl_length+=1;
  20.582 -    } /* switch */
  20.583 -    lptr++;
  20.584 -  } /* while */
  20.585 -
  20.586 -  /* allocate a buffer to replace the sequence in */
  20.587 -  if ((buffer=(char*)malloc(*repl_length))==NULL)
  20.588 -    return (char*)error(103);
  20.589 -
  20.590 -  /* replace the pattern into this temporary buffer */
  20.591 -  lptr=buffer;
  20.592 -  *lptr++='\t';         /* the "replace" patterns do not have tabs */
  20.593 -  while (*pattern) {
  20.594 -    assert((int)(lptr-buffer)<*repl_length);
  20.595 -    switch (*pattern) {
  20.596 -    case '%':
  20.597 -      /* write out the symbol */
  20.598 -      pattern++;
  20.599 -      assert(isdigit(*pattern));
  20.600 -      var=atoi(pattern) - 1;
  20.601 -      assert(var>=0 && var<MAX_OPT_VARS);
  20.602 -      assert(symbols[var][0]!='\0');    /* variable should be defined */
  20.603 -      strcpy(lptr,symbols[var]);
  20.604 -      lptr+=strlen(symbols[var]);
  20.605 -      break;
  20.606 -    case '!':
  20.607 -      /* finish the line, optionally start the next line with an indent */
  20.608 -      *lptr++='\n';
  20.609 -      *lptr++='\0';
  20.610 -      if (*(pattern+1)!='\0')
  20.611 -        *lptr++='\t';
  20.612 -      break;
  20.613 -    default:
  20.614 -      *lptr++=*pattern;
  20.615 -    } /* switch */
  20.616 -    pattern++;
  20.617 -  } /* while */
  20.618 -
  20.619 -  assert((int)(lptr-buffer)==*repl_length);
  20.620 -  return buffer;
  20.621 -}
  20.622 -
  20.623 -static void strreplace(char *dest,char *replace,int sub_length,int repl_length,int dest_length)
  20.624 -{
  20.625 -  int offset=sub_length-repl_length;
  20.626 -  if (offset>0) {               /* delete a section */
  20.627 -    memmove(dest,dest+offset,dest_length-offset);
  20.628 -    memset(dest+dest_length-offset,0xcc,offset); /* not needed, but for cleanlyness */
  20.629 -  } else if (offset<0) {        /* insert a section */
  20.630 -    memmove(dest-offset, dest, dest_length);
  20.631 -  } /* if */
  20.632 -  memcpy(dest, replace, repl_length);
  20.633 -}
  20.634 -
  20.635 -/*  stgopt
  20.636 - *
  20.637 - *  Optimizes the staging buffer by checking for series of instructions that
  20.638 - *  can be coded more compact. The routine expects the lines in the staging
  20.639 - *  buffer to be separated with '\n' and '\0' characters.
  20.640 - *
  20.641 - *  The longest sequences should probably be checked first.
  20.642 - */
  20.643 -
  20.644 -static void stgopt(char *start,char *end,int (*outputfunc)(char *str))
  20.645 -{
  20.646 -  char symbols[MAX_OPT_VARS][MAX_ALIAS+1];
  20.647 -  int seq,match_length,repl_length;
  20.648 -  int matches;
  20.649 -  char *debut=start;  /* save original start of the buffer */
  20.650 -
  20.651 -  assert(sequences!=NULL);
  20.652 -  /* do not match anything if debug-level is maximum */
  20.653 -  if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) {
  20.654 -    do {
  20.655 -      matches=0;
  20.656 -      start=debut;
  20.657 -      while (start<end) {
  20.658 -        seq=0;
  20.659 -        while (sequences[seq].find!=NULL) {
  20.660 -          assert(seq>=0);
  20.661 -          if (*sequences[seq].find=='\0') {
  20.662 -            if (pc_optimize==sOPTIMIZE_NOMACRO) {
  20.663 -              break;    /* don't look further */
  20.664 -            } else {
  20.665 -              seq++;    /* continue with next string */
  20.666 -              continue;
  20.667 -            } /* if */
  20.668 -          } /* if */
  20.669 -          if (matchsequence(start,end,sequences[seq].find,symbols,&match_length)) {
  20.670 -            char *replace=replacesequence(sequences[seq].replace,symbols,&repl_length);
  20.671 -            /* If the replacement is bigger than the original section, we may need
  20.672 -             * to "grow" the staging buffer. This is quite complex, due to the
  20.673 -             * re-ordering of expressions that can also happen in the staging
  20.674 -             * buffer. In addition, it should not happen: the peephole optimizer
  20.675 -             * must replace sequences with *shorter* sequences, not longer ones.
  20.676 -             * So, I simply forbid sequences that are longer than the ones they
  20.677 -             * are meant to replace.
  20.678 -             */
  20.679 -            assert(match_length>=repl_length);
  20.680 -            if (match_length>=repl_length) {
  20.681 -              strreplace(start,replace,match_length,repl_length,(int)(end-start));
  20.682 -              end-=match_length-repl_length;
  20.683 -              free(replace);
  20.684 -              code_idx-=sequences[seq].savesize;
  20.685 -              seq=0;                      /* restart search for matches */
  20.686 -              matches++;
  20.687 -            } else {
  20.688 -              /* actually, we should never get here (match_length<repl_length) */
  20.689 -              assert(0);
  20.690 -              seq++;
  20.691 -            } /* if */
  20.692 -          } else {
  20.693 -            seq++;
  20.694 -          } /* if */
  20.695 -        } /* while */
  20.696 -        assert(sequences[seq].find==NULL || *sequences[seq].find=='\0' && pc_optimize==sOPTIMIZE_NOMACRO);
  20.697 -        start += strlen(start) + 1;       /* to next string */
  20.698 -      } /* while (start<end) */
  20.699 -    } while (matches>0);
  20.700 -  } /* if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) */
  20.701 -
  20.702 -  for (start=debut; start<end; start+=strlen(start)+1)
  20.703 -    outputfunc(start);
  20.704 -}
  20.705 -
  20.706 -#undef SCPACK_TABLE
    21.1 --- a/compiler-init/sc7.scp	Sat Jul 15 01:36:48 2006 +0000
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,2022 +0,0 @@
    21.4 -/*  Pawn compiler - Peephole optimizer "sequences" strings (plain
    21.5 - *                   and compressed formats)
    21.6 - *
    21.7 - *  Copyright (c) ITB CompuPhase, 2000-2006
    21.8 - *
    21.9 - *  This software is provided "as-is", without any express or implied warranty.
   21.10 - *  In no event will the authors be held liable for any damages arising from
   21.11 - *  the use of this software.
   21.12 - *
   21.13 - *  Permission is granted to anyone to use this software for any purpose,
   21.14 - *  including commercial applications, and to alter it and redistribute it
   21.15 - *  freely, subject to the following restrictions:
   21.16 - *
   21.17 - *  1.  The origin of this software must not be misrepresented; you must not
   21.18 - *      claim that you wrote the original software. If you use this software in
   21.19 - *      a product, an acknowledgment in the product documentation would be
   21.20 - *      appreciated but is not required.
   21.21 - *  2.  Altered source versions must be plainly marked as such, and must not be
   21.22 - *      misrepresented as being the original software.
   21.23 - *  3.  This notice may not be removed or altered from any source distribution.
   21.24 - *
   21.25 - *  Version: $Id: sc7.sch 3577 2006-06-02 16:22:52Z thiadmer $
   21.26 - */
   21.27 -
   21.28 -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
   21.29 -
   21.30 -#define SCPACK_TERMINATOR ,     /* end each section with a comma */
   21.31 -
   21.32 -#define SCPACK_TABLE sequences_table
   21.33 -/*-*SCPACK start of pair table, do not change or remove this line */
   21.34 -unsigned char sequences_table[][2] = {
   21.35 -  {49,33}, {37,128}, {32,129}, {32,37}, {114,105}, {112,132}, {46,133}, {97,100}, {46,97}, {136,108}, {137,116}, {115,104}, {111,135}, {117,139}, {112,141}, {108,140},
   21.36 -  {131,50}, {144,33}, {46,115}, {138,33}, {59,36}, {134,130}, {143,146}, {115,116}, {134,145}, {110,151}, {111,153}, {99,154}, {112,147}, {135,100}, {134,33}, {114,33},
   21.37 -  {111,156}, {112,160}, {46,99}, {138,130}, {142,158}, {131,51}, {150,152}, {112,33}, {120,167}, {101,168}, {148,169}, {97,159}, {112,171}, {148,172}, {165,33}, {173,142},
   21.38 -  {122,101}, {176,114}, {101,113}, {110,100}, {149,164}, {157,114}, {33,161}, {131,49}, {103,33}, {157,33}, {104,184}, {99,186}, {120,187}, {98,111}, {118,101}, {111,190},
   21.39 -  {109,191}, {130,170}, {131,52}, {106,177}, {138,145}, {180,166}, {192,147}, {108,162}, {163,166}, {143,149}, {115,174}, {117,179}, {139,199}, {203,202}, {189,205}, {105,100},
   21.40 -  {115,103}, {115,108}, {207,120}, {195,130}, {46,135}, {178,33}, {212,114}, {204,134}, {155,149}, {142,162}, {183,145}, {150,149}, {143,152}, {194,33}, {130,175}, {97,179},
   21.41 -  {177,111}, {182,185}, {143,46}, {183,144}, {155,152}, {145,175}, {114,101}, {230,102}, {108,231}, {101,115}, {233,115}, {114,116}, {142,147}, {105,33}, {155,163}, {178,130},
   21.42 -  {215,32}, {240,50}, {143,196}, {155,197}, {181,197}, {181,200}, {108,210}, {46,98}, {241,225}, {208,235}, {209,234}, {224,158}, {143,163}, {150,163}, {155,200}
   21.43 -};
   21.44 -/*-*SCPACK end of pair table, do not change or remove this line */
   21.45 -
   21.46 -#define seqsize(o,p)    (opcodes(o)+opargs(p))
   21.47 -typedef struct {
   21.48 -  char *find;
   21.49 -  char *replace;
   21.50 -  int savesize;         /* number of bytes saved (in bytecode) */
   21.51 -} SEQUENCE;
   21.52 -static SEQUENCE sequences_cmp[] = {
   21.53 -  /* A very common sequence in four varieties
   21.54 -   *    load.s.pri n1           load.s.pri n2
   21.55 -   *    push.pri                load.s.alt n1
   21.56 -   *    load.s.pri n2           -
   21.57 -   *    pop.alt                 -
   21.58 -   *    --------------------------------------
   21.59 -   *    load.pri n1             load.s.pri n2
   21.60 -   *    push.pri                load.alt n1
   21.61 -   *    load.s.pri n2           -
   21.62 -   *    pop.alt                 -
   21.63 -   *    --------------------------------------
   21.64 -   *    load.s.pri n1           load.pri n2
   21.65 -   *    push.pri                load.s.alt n1
   21.66 -   *    load.pri n2             -
   21.67 -   *    pop.alt                 -
   21.68 -   *    --------------------------------------
   21.69 -   *    load.pri n1             load.pri n2
   21.70 -   *    push.pri                load.alt n1
   21.71 -   *    load.pri n2             -
   21.72 -   *    pop.alt                 -
   21.73 -   */
   21.74 -  {
   21.75 -    #ifdef SCPACK
   21.76 -      "load.s.pri %1!push.pri!load.s.pri %2!pop.alt!",
   21.77 -      "load.s.pri %2!load.s.alt %1!",
   21.78 -    #else
   21.79 -      "\226\305\241",
   21.80 -      "\246\375",
   21.81 -    #endif
   21.82 -    seqsize(4,2) - seqsize(2,2)
   21.83 -  },
   21.84 -  {
   21.85 -    #ifdef SCPACK
   21.86 -      "load.pri %1!push.pri!load.s.pri %2!pop.alt!",
   21.87 -      "load.s.pri %2!load.alt %1!",
   21.88 -    #else
   21.89 -      "\217\305\241",
   21.90 -      "\246\374",
   21.91 -    #endif
   21.92 -    seqsize(4,2) - seqsize(2,2)
   21.93 -  },
   21.94 -  {
   21.95 -    #ifdef SCPACK
   21.96 -      "load.s.pri %1!push.pri!load.pri %2!pop.alt!",
   21.97 -      "load.pri %2!load.s.alt %1!",
   21.98 -    #else
   21.99 -      "\226\264\334\241",
  21.100 -      "\334\375",
  21.101 -    #endif
  21.102 -    seqsize(4,2) - seqsize(2,2)
  21.103 -  },
  21.104 -  {
  21.105 -    #ifdef SCPACK
  21.106 -      "load.pri %1!push.pri!load.pri %2!pop.alt!",
  21.107 -      "load.pri %2!load.alt %1!",
  21.108 -    #else
  21.109 -      "\217\264\334\241",
  21.110 -      "\334\374",
  21.111 -    #endif
  21.112 -    seqsize(4,2) - seqsize(2,2)
  21.113 -  },
  21.114 -  /* (#1#) The above also occurs with "addr.pri" (array
  21.115 -   * indexing) as the first line; so that adds 2 cases.
  21.116 -   */
  21.117 -  {
  21.118 -    #ifdef SCPACK
  21.119 -      "addr.pri %1!push.pri!load.s.pri %2!pop.alt!",
  21.120 -      "addr.alt %1!load.s.pri %2!",
  21.121 -    #else
  21.122 -      "\364\241",
  21.123 -      "\365",
  21.124 -    #endif
  21.125 -    seqsize(4,2) - seqsize(2,2)
  21.126 -  },
  21.127 -  {
  21.128 -    #ifdef SCPACK
  21.129 -      "addr.pri %1!push.pri!load.pri %2!pop.alt!",
  21.130 -      "addr.alt %1!load.pri %2!",
  21.131 -    #else
  21.132 -      "\265\264\334\241",
  21.133 -      "\265\243\334",
  21.134 -    #endif
  21.135 -    seqsize(4,2) - seqsize(2,2)
  21.136 -  },
  21.137 -  /* And the same sequence with const.pri as either the first
  21.138 -   * or the second load instruction: four more cases.
  21.139 -   */
  21.140 -  {
  21.141 -    #ifdef SCPACK
  21.142 -      "const.pri %1!push.pri!load.s.pri %2!pop.alt!",
  21.143 -      "load.s.pri %2!const.alt %1!",
  21.144 -    #else
  21.145 -      "\363\241",
  21.146 -      "\246\356",
  21.147 -    #endif
  21.148 -    seqsize(4,2) - seqsize(2,2)
  21.149 -  },
  21.150 -  {
  21.151 -    #ifdef SCPACK
  21.152 -      "const.pri %1!push.pri!load.pri %2!pop.alt!",
  21.153 -      "load.pri %2!const.alt %1!",
  21.154 -    #else
  21.155 -      "\233\264\334\241",
  21.156 -      "\334\356",
  21.157 -    #endif
  21.158 -    seqsize(4,2) - seqsize(2,2)
  21.159 -  },
  21.160 -  {
  21.161 -    #ifdef SCPACK
  21.162 -      "load.s.pri %1!push.pri!const.pri %2!pop.alt!",
  21.163 -      "const.pri %2!load.s.alt %1!",
  21.164 -    #else
  21.165 -      "\226\264\344\241",
  21.166 -      "\344\375",
  21.167 -    #endif
  21.168 -    seqsize(4,2) - seqsize(2,2)
  21.169 -  },
  21.170 -  {
  21.171 -    #ifdef SCPACK
  21.172 -      "load.pri %1!push.pri!const.pri %2!pop.alt!",
  21.173 -      "const.pri %2!load.alt %1!",
  21.174 -    #else
  21.175 -      "\217\264\344\241",
  21.176 -      "\344\374",
  21.177 -    #endif
  21.178 -    seqsize(4,2) - seqsize(2,2)
  21.179 -  },
  21.180 -  /* The same as above, but now with "addr.pri" (array
  21.181 -   * indexing) on the first line and const.pri on
  21.182 -   * the second.
  21.183 -   */
  21.184 -  {
  21.185 -    #ifdef SCPACK
  21.186 -      "addr.pri %1!push.pri!const.pri %2!pop.alt!",
  21.187 -      "addr.alt %1!const.pri %2!",
  21.188 -    #else
  21.189 -      "\265\264\344\241",
  21.190 -      "\265\243\344",
  21.191 -    #endif
  21.192 -    seqsize(4,2) - seqsize(2,2)
  21.193 -  },
  21.194 -  {
  21.195 -    #ifdef SCPACK
  21.196 -      "addr.pri %1!push.pri!zero.pri!pop.alt!",
  21.197 -      "addr.alt %1!zero.pri!",
  21.198 -    #else
  21.199 -      "\265\264\373\241",
  21.200 -      "\265\243\373",
  21.201 -    #endif
  21.202 -    seqsize(4,1) - seqsize(2,1)
  21.203 -  },
  21.204 -  /* ??? add references */
  21.205 -  /* Chained relational operators can contain sequences like:
  21.206 -   *    move.pri                load.s.pri n1
  21.207 -   *    push.pri                -
  21.208 -   *    load.s.pri n1           -
  21.209 -   *    pop.alt                 -
  21.210 -   * The above also accurs for "load.pri" and for "const.pri",
  21.211 -   * so add another two cases.
  21.212 -   */
  21.213 -  {
  21.214 -    #ifdef SCPACK
  21.215 -      "move.pri!push.pri!load.s.pri %1!pop.alt!",
  21.216 -      "load.s.pri %1!",
  21.217 -    #else
  21.218 -      "\300\236\244\333\241",
  21.219 -      "\333",
  21.220 -    #endif
  21.221 -    seqsize(4,1) - seqsize(1,1)
  21.222 -  },
  21.223 -  {
  21.224 -    #ifdef SCPACK
  21.225 -      "move.pri!push.pri!load.pri %1!pop.alt!",
  21.226 -      "load.pri %1!",
  21.227 -    #else
  21.228 -      "\300\236\244\311\241",
  21.229 -      "\311",
  21.230 -    #endif
  21.231 -    seqsize(4,1) - seqsize(1,1)
  21.232 -  },
  21.233 -  {
  21.234 -    #ifdef SCPACK
  21.235 -      "move.pri!push.pri!const.pri %1!pop.alt!",
  21.236 -      "const.pri %1!",
  21.237 -    #else
  21.238 -      "\300\236\244\330\241",
  21.239 -      "\330",
  21.240 -    #endif
  21.241 -    seqsize(4,1) - seqsize(1,1)
  21.242 -  },
  21.243 -  /* More optimizations for chained relational operators; the
  21.244 -   * continuation sequences can be simplified if they turn out
  21.245 -   * to be termination sequences:
  21.246 -   *    xchg                    sless       also for sless, sgeq and sleq
  21.247 -   *    sgrtr                   pop.alt
  21.248 -   *    swap.alt                and
  21.249 -   *    and                     ;$exp
  21.250 -   *    pop.alt                 -
  21.251 -   *    ;$exp                   -
  21.252 -   *    --------------------------------------
  21.253 -   *    xchg                    sless       also for sless, sgeq and sleq
  21.254 -   *    sgrtr                   pop.alt
  21.255 -   *    swap.alt                and
  21.256 -   *    and                     jzer n1
  21.257 -   *    pop.alt                 -
  21.258 -   *    jzer n1                 -
  21.259 -   *    --------------------------------------
  21.260 -   *    xchg                    jsgeq  n1   also for sless, sgeq and sleq
  21.261 -   *    sgrtr                   ;$exp       (occurs for non-chained comparisons)
  21.262 -   *    jzer n1                 -
  21.263 -   *    ;$exp                   -
  21.264 -   *    --------------------------------------
  21.265 -   *    xchg                    sless       also for sless, sgeq and sleq
  21.266 -   *    sgrtr                   ;$exp       (occurs for non-chained comparisons)
  21.267 -   *    ;$exp                   -
  21.268 -   */
  21.269 -  {
  21.270 -    #ifdef SCPACK
  21.271 -      "xchg!sgrtr!swap.alt!and!pop.alt!;$exp!",
  21.272 -      "sless!pop.alt!and!;$exp!",
  21.273 -    #else
  21.274 -      "\274\371\237swa\234\337\266\252",
  21.275 -      "\372\266\337!\252",
  21.276 -    #endif
  21.277 -    seqsize(5,0) - seqsize(3,0)
  21.278 -  },
  21.279 -  {
  21.280 -    #ifdef SCPACK
  21.281 -      "xchg!sless!swap.alt!and!pop.alt!;$exp!",
  21.282 -      "sgrtr!pop.alt!and!;$exp!",
  21.283 -    #else
  21.284 -      "\274\372!swa\234\337\266\252",
  21.285 -      "\371\237\241\337!\252",
  21.286 -    #endif
  21.287 -    seqsize(5,0) - seqsize(3,0)
  21.288 -  },
  21.289 -  {
  21.290 -    #ifdef SCPACK
  21.291 -      "xchg!sgeq!swap.alt!and!pop.alt!;$exp!",
  21.292 -      "sleq!pop.alt!and!;$exp!",
  21.293 -    #else
  21.294 -      "\274\320\325swa\234\337\266\252",
  21.295 -      "\321\262\266\337!\252",
  21.296 -    #endif
  21.297 -    seqsize(5,0) - seqsize(3,0)
  21.298 -  },
  21.299 -  {
  21.300 -    #ifdef SCPACK
  21.301 -      "xchg!sleq!swap.alt!and!pop.alt!;$exp!",
  21.302 -      "sgeq!pop.alt!and!;$exp!",
  21.303 -    #else
  21.304 -      "\274\321\325swa\234\337\266\252",
  21.305 -      "\320\262\266\337!\252",
  21.306 -    #endif
  21.307 -    seqsize(5,0) - seqsize(3,0)
  21.308 -  },
  21.309 -  {
  21.310 -    #ifdef SCPACK
  21.311 -      "xchg!sgrtr!swap.alt!and!pop.alt!jzer %1!",
  21.312 -      "sless!pop.alt!and!jzer %1!",
  21.313 -    #else
  21.314 -      "\274\371\237swa\234\337\266\323",
  21.315 -      "\372\266\337!\323",
  21.316 -    #endif
  21.317 -    seqsize(5,0) - seqsize(3,0)
  21.318 -  },
  21.319 -  {
  21.320 -    #ifdef SCPACK
  21.321 -      "xchg!sless!swap.alt!and!pop.alt!jzer %1!",
  21.322 -      "sgrtr!pop.alt!and!jzer %1!",
  21.323 -    #else
  21.324 -      "\274\372!swa\234\337\266\323",
  21.325 -      "\371\237\241\337!\323",
  21.326 -    #endif
  21.327 -    seqsize(5,0) - seqsize(3,0)
  21.328 -  },
  21.329 -  {
  21.330 -    #ifdef SCPACK
  21.331 -      "xchg!sgeq!swap.alt!and!pop.alt!jzer %1!",
  21.332 -      "sleq!pop.alt!and!jzer %1!",
  21.333 -    #else
  21.334 -      "\274\320\325swa\234\337\266\323",
  21.335 -      "\321\262\266\337!\323",
  21.336 -    #endif
  21.337 -    seqsize(5,0) - seqsize(3,0)
  21.338 -  },
  21.339 -  {
  21.340 -    #ifdef SCPACK
  21.341 -      "xchg!sleq!swap.alt!and!pop.alt!jzer %1!",
  21.342 -      "sgeq!pop.alt!and!jzer %1!",
  21.343 -    #else
  21.344 -      "\274\321\325swa\234\337\266\323",
  21.345 -      "\320\262\266\337!\323",
  21.346 -    #endif
  21.347 -    seqsize(5,0) - seqsize(3,0)
  21.348 -  },
  21.349 -  {
  21.350 -    #ifdef SCPACK
  21.351 -      "xchg!sgrtr!jzer %1!;$exp!",
  21.352 -      "jsgeq %1!;$exp!",
  21.353 -    #else
  21.354 -      "\274\371\237\303\301",
  21.355 -      "j\320\262\301",
  21.356 -    #endif
  21.357 -    seqsize(3,1) - seqsize(1,1)
  21.358 -  },
  21.359 -  {
  21.360 -    #ifdef SCPACK
  21.361 -      "xchg!sless!jzer %1!;$exp!",
  21.362 -      "jsleq %1!;$exp!",
  21.363 -    #else
  21.364 -      "\274\372!\303\301",
  21.365 -      "j\321\262\301",
  21.366 -    #endif
  21.367 -    seqsize(3,1) - seqsize(1,1)
  21.368 -  },
  21.369 -  {
  21.370 -    #ifdef SCPACK
  21.371 -      "xchg!sgeq!jzer %1!;$exp!",
  21.372 -      "jsgrtr %1!;$exp!",
  21.373 -    #else
  21.374 -      "\274\320\325\303\301",
  21.375 -      "j\371r\301",
  21.376 -    #endif
  21.377 -    seqsize(3,1) - seqsize(1,1)
  21.378 -  },
  21.379 -  {
  21.380 -    #ifdef SCPACK
  21.381 -      "xchg!sleq!jzer %1!;$exp!",
  21.382 -      "jsless %1!;$exp!",
  21.383 -    #else
  21.384 -      "\274\321\325\303\301",
  21.385 -      "j\372\301",
  21.386 -    #endif
  21.387 -    seqsize(3,1) - seqsize(1,1)
  21.388 -  },
  21.389 -  {
  21.390 -    #ifdef SCPACK
  21.391 -      "xchg!sgrtr!;$exp!",
  21.392 -      "sless!;$exp!",
  21.393 -    #else
  21.394 -      "\274\371\237\252",
  21.395 -      "\372!\252",
  21.396 -    #endif
  21.397 -    seqsize(2,0) - seqsize(1,0)
  21.398 -  },
  21.399 -  {
  21.400 -    #ifdef SCPACK
  21.401 -      "xchg!sless!;$exp!",
  21.402 -      "sgrtr!;$exp!",
  21.403 -    #else
  21.404 -      "\274\372!\252",
  21.405 -      "\371\237\252",
  21.406 -    #endif
  21.407 -    seqsize(2,0) - seqsize(1,0)
  21.408 -  },
  21.409 -  {
  21.410 -    #ifdef SCPACK
  21.411 -      "xchg!sgeq!;$exp!",
  21.412 -      "sleq!;$exp!",
  21.413 -    #else
  21.414 -      "\274\320\325\252",
  21.415 -      "\321\325\252",
  21.416 -    #endif
  21.417 -    seqsize(2,0) - seqsize(1,0)
  21.418 -  },
  21.419 -  {
  21.420 -    #ifdef SCPACK
  21.421 -      "xchg!sleq!;$exp!",
  21.422 -      "sgeq!;$exp!",
  21.423 -    #else
  21.424 -      "\274\321\325\252",
  21.425 -      "\320\325\252",
  21.426 -    #endif
  21.427 -    seqsize(2,0) - seqsize(1,0)
  21.428 -  },
  21.429 -  /* The entry to chained operators is also opt to optimization
  21.430 -   *    load.s.pri n1           load.s.pri n2
  21.431 -   *    load.s.alt n2           load.s.alt n1
  21.432 -   *    xchg                    -
  21.433 -   *    --------------------------------------
  21.434 -   *    load.s.pri n1           load.pri n2
  21.435 -   *    load.alt n2             load.s.alt n1
  21.436 -   *    xchg                    -
  21.437 -   *    --------------------------------------
  21.438 -   *    load.s.pri n1           const.pri n2
  21.439 -   *    const.alt n2            load.s.alt n1
  21.440 -   *    xchg                    -
  21.441 -   *    --------------------------------------
  21.442 -   * and all permutations...
  21.443 -   */
  21.444 -  {
  21.445 -    #ifdef SCPACK
  21.446 -      "load.s.pri %1!load.s.alt %2!xchg!",
  21.447 -      "load.s.pri %2!load.s.alt %1!",
  21.448 -    #else
  21.449 -      "\333\226\304\274",
  21.450 -      "\246\375",
  21.451 -    #endif
  21.452 -    seqsize(3,2) - seqsize(2,2)
  21.453 -  },
  21.454 -  {
  21.455 -    #ifdef SCPACK
  21.456 -      "load.s.pri %1!load.alt %2!xchg!",
  21.457 -      "load.pri %2!load.s.alt %1!",
  21.458 -    #else
  21.459 -      "\333\362\274",
  21.460 -      "\334\375",
  21.461 -    #endif
  21.462 -    seqsize(3,2) - seqsize(2,2)
  21.463 -  },
  21.464 -  {
  21.465 -    #ifdef SCPACK
  21.466 -      "load.s.pri %1!const.alt %2!xchg!",
  21.467 -      "const.pri %2!load.s.alt %1!",
  21.468 -    #else
  21.469 -      "\333\233\304\274",
  21.470 -      "\344\375",
  21.471 -    #endif
  21.472 -    seqsize(3,2) - seqsize(2,2)
  21.473 -  },
  21.474 -  {
  21.475 -    #ifdef SCPACK
  21.476 -      "load.pri %1!load.s.alt %2!xchg!",
  21.477 -      "load.s.pri %2!load.alt %1!",
  21.478 -    #else
  21.479 -      "\311\226\304\274",
  21.480 -      "\246\374",
  21.481 -    #endif
  21.482 -    seqsize(3,2) - seqsize(2,2)
  21.483 -  },
  21.484 -  {
  21.485 -    #ifdef SCPACK
  21.486 -      "load.pri %1!load.alt %2!xchg!",
  21.487 -      "load.pri %2!load.alt %1!",
  21.488 -    #else
  21.489 -      "\311\362\274",
  21.490 -      "\334\374",
  21.491 -    #endif
  21.492 -    seqsize(3,2) - seqsize(2,2)
  21.493 -  },
  21.494 -  {
  21.495 -    #ifdef SCPACK
  21.496 -      "load.pri %1!const.alt %2!xchg!",
  21.497 -      "const.pri %2!load.alt %1!",
  21.498 -    #else
  21.499 -      "\311\233\304\274",
  21.500 -      "\344\374",
  21.501 -    #endif
  21.502 -    seqsize(3,2) - seqsize(2,2)
  21.503 -  },
  21.504 -  {
  21.505 -    #ifdef SCPACK
  21.506 -      "const.pri %1!load.s.alt %2!xchg!",
  21.507 -      "load.s.pri %2!const.alt %1!",
  21.508 -    #else
  21.509 -      "\330\226\304\274",
  21.510 -      "\246\356",
  21.511 -    #endif
  21.512 -    seqsize(3,2) - seqsize(2,2)
  21.513 -  },
  21.514 -  {
  21.515 -    #ifdef SCPACK
  21.516 -      "const.pri %1!load.alt %2!xchg!",
  21.517 -      "load.pri %2!const.alt %1!",
  21.518 -    #else
  21.519 -      "\330\362\274",
  21.520 -      "\334\356",
  21.521 -    #endif
  21.522 -    seqsize(3,2) - seqsize(2,2)
  21.523 -  },
  21.524 -  /* some sequences where PRI is moved to ALT can be optimized
  21.525 -   * further when considering what follows
  21.526 -   *    move.alt                const.alt n1
  21.527 -   *    const.pri %1            -
  21.528 -   *    xchg                    -
  21.529 -   * (also for load.s.pri and load.pri)
  21.530 -   *    --------------------------------------
  21.531 -   *    lref.pri %1             lref.alt %1
  21.532 -   *    move.alt                [load.pri %2]
  21.533 -   *    [load.pri %2]           -
  21.534 -   * (where [load.pri %2] may also be another operatrion loading PRI)
  21.535 -   */
  21.536 -  {
  21.537 -    #ifdef SCPACK
  21.538 -      "move.alt!const.pri %1!xchg!",
  21.539 -      "const.alt %1!",
  21.540 -    #else
  21.541 -      "\306\330\274",
  21.542 -      "\356",
  21.543 -    #endif
  21.544 -    seqsize(3,1) - seqsize(1,1)
  21.545 -  },
  21.546 -  {
  21.547 -    #ifdef SCPACK
  21.548 -      "move.alt!load.pri %1!xchg!",
  21.549 -      "load.alt %1!",
  21.550 -    #else
  21.551 -      "\306\311\274",
  21.552 -      "\374",
  21.553 -    #endif
  21.554 -    seqsize(3,1) - seqsize(1,1)
  21.555 -  },
  21.556 -  {
  21.557 -    #ifdef SCPACK
  21.558 -      "move.alt!load.s.pri %1!xchg!",
  21.559 -      "load.s.alt %1!",
  21.560 -    #else
  21.561 -      "\306\333\274",
  21.562 -      "\375",
  21.563 -    #endif
  21.564 -    seqsize(3,1) - seqsize(1,1)
  21.565 -  },
  21.566 -  /* ----- */
  21.567 -  {
  21.568 -    #ifdef SCPACK
  21.569 -      "lref.pri %1!move.alt!load.pri %2!",
  21.570 -      "lref.alt %1!load.pri %2!",
  21.571 -    #else
  21.572 -      "\350\225\306\334",
  21.573 -      "\350\243\334",
  21.574 -    #endif
  21.575 -    seqsize(3,2) - seqsize(2,2)
  21.576 -  },
  21.577 -  {
  21.578 -    #ifdef SCPACK
  21.579 -      "lref.pri %1!move.alt!load.s.pri %2!",
  21.580 -      "lref.alt %1!load.s.pri %2!",
  21.581 -    #else
  21.582 -      "\350\225\306\246",
  21.583 -      "\350\310",
  21.584 -    #endif
  21.585 -    seqsize(3,2) - seqsize(2,2)
  21.586 -  },
  21.587 -  {
  21.588 -    #ifdef SCPACK
  21.589 -      "lref.pri %1!move.alt!const.pri %2!",
  21.590 -      "lref.alt %1!const.pri %2!",
  21.591 -    #else
  21.592 -      "\350\225\306\344",
  21.593 -      "\350\243\344",
  21.594 -    #endif
  21.595 -    seqsize(3,2) - seqsize(2,2)
  21.596 -  },
  21.597 -  {
  21.598 -    #ifdef SCPACK
  21.599 -      "lref.s.pri %1!move.alt!load.pri %2!",
  21.600 -      "lref.s.alt %1!load.pri %2!",
  21.601 -    #else
  21.602 -      "\350\222\225\306\334",
  21.603 -      "\350\222\243\334",
  21.604 -    #endif
  21.605 -    seqsize(3,2) - seqsize(2,2)
  21.606 -  },
  21.607 -  {
  21.608 -    #ifdef SCPACK
  21.609 -      "lref.s.pri %1!move.alt!load.s.pri %2!",
  21.610 -      "lref.s.alt %1!load.s.pri %2!",
  21.611 -    #else
  21.612 -      "\350\222\225\306\246",
  21.613 -      "\350\222\310",
  21.614 -    #endif
  21.615 -    seqsize(3,2) - seqsize(2,2)
  21.616 -  },
  21.617 -  {
  21.618 -    #ifdef SCPACK
  21.619 -      "lref.s.pri %1!move.alt!const.pri %2!",
  21.620 -      "lref.s.alt %1!const.pri %2!",
  21.621 -    #else
  21.622 -      "\350\222\225\306\344",
  21.623 -      "\350\222\243\344",
  21.624 -    #endif
  21.625 -    seqsize(3,2) - seqsize(2,2)
  21.626 -  },
  21.627 -  /* Array indexing can merit from special instructions.
  21.628 -   * Simple indexed array lookup can be optimized quite
  21.629 -   * a bit.
  21.630 -   *    addr.pri n1             addr.alt n1
  21.631 -   *    push.pri                load.s.pri n2
  21.632 -   *    load.s.pri n2           bounds n3
  21.633 -   *    bounds n3               lidx.b n4
  21.634 -   *    shl.c.pri n4            -
  21.635 -   *    pop.alt                 -
  21.636 -   *    add                     -
  21.637 -   *    load.i                  -
  21.638 -   *
  21.639 -   * And to prepare for storing a value in an array
  21.640 -   *    addr.pri n1             addr.alt n1
  21.641 -   *    push.pri                load.s.pri n2
  21.642 -   *    load.s.pri n2           bounds n3
  21.643 -   *    bounds n3               idxaddr.b n4
  21.644 -   *    shl.c.pri n4            -
  21.645 -   *    pop.alt                 -
  21.646 -   *    add                     -
  21.647 -   *
  21.648 -   * Notes (additional cases):
  21.649 -   * 1. instruction addr.pri can also be const.pri (for
  21.650 -   *    global arrays)
  21.651 -   * 2. the bounds instruction can be absent
  21.652 -   * 3. when "n4" (the shift value) is the 2 (with 32-bit cells), use the
  21.653 -   *    even more optimal instructions LIDX and IDDXADDR
  21.654 -   *
  21.655 -   * If the array index is more complex, one can only optimize
  21.656 -   * the last four instructions:
  21.657 -   *    shl.c.pri n1            pop.alt
  21.658 -   *    pop.alt                 lidx.b n1
  21.659 -   *    add                     -
  21.660 -   *    loadi                   -
  21.661 -   *    --------------------------------------
  21.662 -   *    shl.c.pri n1            pop.alt
  21.663 -   *    pop.alt                 idxaddr.b n1
  21.664 -   *    add                     -
  21.665 -   */
  21.666 -#if !defined BIT16
  21.667 -  /* loading from array, "cell" shifted */
  21.668 -  {
  21.669 -    #ifdef SCPACK
  21.670 -      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
  21.671 -      "addr.alt %1!load.s.pri %2!bounds %3!lidx!",
  21.672 -    #else
  21.673 -      "\364\316\370\342\355",
  21.674 -      "\365\316\366!",
  21.675 -    #endif
  21.676 -    seqsize(8,4) - seqsize(4,3)
  21.677 -  },
  21.678 -  {
  21.679 -    #ifdef SCPACK
  21.680 -      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
  21.681 -      "const.alt %1!load.s.pri %2!bounds %3!lidx!",
  21.682 -    #else
  21.683 -      "\363\316\370\342\355",
  21.684 -      "\376\316\366!",
  21.685 -    #endif
  21.686 -    seqsize(8,4) - seqsize(4,3)
  21.687 -  },
  21.688 -  {
  21.689 -    #ifdef SCPACK
  21.690 -      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
  21.691 -      "addr.alt %1!load.s.pri %2!lidx!",
  21.692 -    #else
  21.693 -      "\364\370\342\355",
  21.694 -      "\365\366!",
  21.695 -    #endif
  21.696 -    seqsize(7,3) - seqsize(3,2)
  21.697 -  },
  21.698 -  {
  21.699 -    #ifdef SCPACK
  21.700 -      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
  21.701 -      "const.alt %1!load.s.pri %2!lidx!",
  21.702 -    #else
  21.703 -      "\363\370\342\355",
  21.704 -      "\376\366!",
  21.705 -    #endif
  21.706 -    seqsize(7,3) - seqsize(3,2)
  21.707 -  },
  21.708 -#endif
  21.709 -  /* loading from array, not "cell" shifted */
  21.710 -  {
  21.711 -    #ifdef SCPACK
  21.712 -      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
  21.713 -      "addr.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
  21.714 -    #else
  21.715 -      "\364\316\327\302\341\342\355",
  21.716 -      "\365\316\366\367\335",
  21.717 -    #endif
  21.718 -    seqsize(8,4) - seqsize(4,4)
  21.719 -  },
  21.720 -  {
  21.721 -    #ifdef SCPACK
  21.722 -      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
  21.723 -      "const.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
  21.724 -    #else
  21.725 -      "\363\316\327\302\341\342\355",
  21.726 -      "\376\316\366\367\335",
  21.727 -    #endif
  21.728 -    seqsize(8,4) - seqsize(4,4)
  21.729 -  },
  21.730 -  {
  21.731 -    #ifdef SCPACK
  21.732 -      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
  21.733 -      "addr.alt %1!load.s.pri %2!lidx.b %3!",
  21.734 -    #else
  21.735 -      "\364\327\256\241\271\342\355",
  21.736 -      "\365\366\367\256",
  21.737 -    #endif
  21.738 -    seqsize(7,3) - seqsize(3,3)
  21.739 -  },
  21.740 -  {
  21.741 -    #ifdef SCPACK
  21.742 -      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
  21.743 -      "const.alt %1!load.s.pri %2!lidx.b %3!",
  21.744 -    #else
  21.745 -      "\363\327\256\241\271\342\355",
  21.746 -      "\376\366\367\256",
  21.747 -    #endif
  21.748 -    seqsize(7,3) - seqsize(3,3)
  21.749 -  },
  21.750 -#if !defined BIT16
  21.751 -  /* array index calculation for storing a value, "cell" aligned */
  21.752 -  {
  21.753 -    #ifdef SCPACK
  21.754 -      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
  21.755 -      "addr.alt %1!load.s.pri %2!bounds %3!idxaddr!",
  21.756 -    #else
  21.757 -      "\364\316\370",
  21.758 -      "\365\316\322\235\237",
  21.759 -    #endif
  21.760 -    seqsize(7,4) - seqsize(4,3)
  21.761 -  },
  21.762 -  {
  21.763 -    #ifdef SCPACK
  21.764 -      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
  21.765 -      "const.alt %1!load.s.pri %2!bounds %3!idxaddr!",
  21.766 -    #else
  21.767 -      "\363\316\370",
  21.768 -      "\376\316\322\235\237",
  21.769 -    #endif
  21.770 -    seqsize(7,4) - seqsize(4,3)
  21.771 -  },
  21.772 -  {
  21.773 -    #ifdef SCPACK
  21.774 -      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
  21.775 -      "addr.alt %1!load.s.pri %2!idxaddr!",
  21.776 -    #else
  21.777 -      "\364\370",
  21.778 -      "\365\322\235\237",
  21.779 -    #endif
  21.780 -    seqsize(6,3) - seqsize(3,2)
  21.781 -  },
  21.782 -  {
  21.783 -    #ifdef SCPACK
  21.784 -      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
  21.785 -      "const.alt %1!load.s.pri %2!idxaddr!",
  21.786 -    #else
  21.787 -      "\363\370",
  21.788 -      "\376\322\235\237",
  21.789 -    #endif
  21.790 -    seqsize(6,3) - seqsize(3,2)
  21.791 -  },
  21.792 -#endif
  21.793 -  /* array index calculation for storing a value, not "cell" packed */
  21.794 -  {
  21.795 -    #ifdef SCPACK
  21.796 -      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
  21.797 -      "addr.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
  21.798 -    #else
  21.799 -      "\364\316\327\302\341",
  21.800 -      "\365\316\322\265\367\335",
  21.801 -    #endif
  21.802 -    seqsize(7,4) - seqsize(4,4)
  21.803 -  },
  21.804 -  {
  21.805 -    #ifdef SCPACK
  21.806 -      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
  21.807 -      "const.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
  21.808 -    #else
  21.809 -      "\363\316\327\302\341",
  21.810 -      "\376\316\322\265\367\335",
  21.811 -    #endif
  21.812 -    seqsize(7,4) - seqsize(4,4)
  21.813 -  },
  21.814 -  {
  21.815 -    #ifdef SCPACK
  21.816 -      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
  21.817 -      "addr.alt %1!load.s.pri %2!idxaddr.b %3!",
  21.818 -    #else
  21.819 -      "\364\327\256\241\271",
  21.820 -      "\365\322\265\367\256",
  21.821 -    #endif
  21.822 -    seqsize(6,3) - seqsize(3,3)
  21.823 -  },
  21.824 -  {
  21.825 -    #ifdef SCPACK
  21.826 -      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
  21.827 -      "const.alt %1!load.s.pri %2!idxaddr.b %3!",
  21.828 -    #else
  21.829 -      "\363\327\256\241\271",
  21.830 -      "\376\322\265\367\256",
  21.831 -    #endif
  21.832 -    seqsize(6,3) - seqsize(3,3)
  21.833 -  },
  21.834 -#if !defined BIT16
  21.835 -  /* the shorter array indexing sequences, see above for comments */
  21.836 -  {
  21.837 -    #ifdef SCPACK
  21.838 -      "shl.c.pri 2!pop.alt!add!loadi!",
  21.839 -      "pop.alt!lidx!",
  21.840 -    #else
  21.841 -      "\370\217\355",
  21.842 -      "\241\366!",
  21.843 -    #endif
  21.844 -    seqsize(4,1) - seqsize(2,0)
  21.845 -  },
  21.846 -  {
  21.847 -    #ifdef SCPACK
  21.848 -      "shl.c.pri 2!pop.alt!add!",
  21.849 -      "pop.alt!idxaddr!",
  21.850 -    #else
  21.851 -      "\370",
  21.852 -      "\241\322\235\237",
  21.853 -    #endif
  21.854 -    seqsize(3,1) - seqsize(2,0)
  21.855 -  },
  21.856 -#endif
  21.857 -  {
  21.858 -    #ifdef SCPACK
  21.859 -      "shl.c.pri %1!pop.alt!add!loadi!",
  21.860 -      "pop.alt!lidx.b %1!",
  21.861 -    #else
  21.862 -      "\314\225\241\271\217\355",
  21.863 -      "\241\366\367\202",
  21.864 -    #endif
  21.865 -    seqsize(4,1) - seqsize(2,1)
  21.866 -  },
  21.867 -  {
  21.868 -    #ifdef SCPACK
  21.869 -      "shl.c.pri %1!pop.alt!add!",
  21.870 -      "pop.alt!idxaddr.b %1!",
  21.871 -    #else
  21.872 -      "\314\225\241\271",
  21.873 -      "\241\322\265\367\202",
  21.874 -    #endif
  21.875 -    seqsize(3,1) - seqsize(2,1)
  21.876 -  },
  21.877 -  /* For packed arrays, there is another case (packed arrays
  21.878 -   * do not take advantage of the LIDX or IDXADDR instructions).
  21.879 -   *    addr.pri n1             addr.alt n1
  21.880 -   *    push.pri                load.s.pri n2
  21.881 -   *    load.s.pri n2           bounds n3
  21.882 -   *    bounds n3               -
  21.883 -   *    pop.alt                 -
  21.884 -   *
  21.885 -   * Notes (additional cases):
  21.886 -   * 1. instruction addr.pri can also be const.pri (for
  21.887 -   *    global arrays)
  21.888 -   * 2. the bounds instruction can be absent, but that
  21.889 -   *    case is already handled (see #1#)
  21.890 -   */
  21.891 -  {
  21.892 -    #ifdef SCPACK
  21.893 -      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
  21.894 -      "addr.alt %1!load.s.pri %2!bounds %3!",
  21.895 -    #else
  21.896 -      "\364\316\241",
  21.897 -      "\365\316",
  21.898 -    #endif
  21.899 -    seqsize(5,3) - seqsize(3,3)
  21.900 -  },
  21.901 -  {
  21.902 -    #ifdef SCPACK
  21.903 -      "const.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
  21.904 -      "const.alt %1!load.s.pri %2!bounds %3!",
  21.905 -    #else
  21.906 -      "\363\316\241",
  21.907 -      "\376\316",
  21.908 -    #endif
  21.909 -    seqsize(5,3) - seqsize(3,3)
  21.910 -  },
  21.911 -  /* Declaration of simple variables often follows the sequence:
  21.912 -   *    ;$lcl <name> <stk>      ;$lcl <name> <stk>
  21.913 -   *    stack -4                push.c <constval>
  21.914 -   *    const.pri <constval>    ;$exp
  21.915 -   *    stor.s.pri <stk>        -
  21.916 -   *    ;$exp                   -
  21.917 -   */
  21.918 -  {
  21.919 -    #ifdef SCPACK
  21.920 -      ";$lcl %1 %2!stack -4!const.pri %3!stor.s.pri %2!;$exp!",
  21.921 -      ";$lcl %1 %2!push.c %3!;$exp!",
  21.922 -    #else
  21.923 -      "\224lcl\332\227ack -4!\233\206\256\227or\222\230\252",
  21.924 -      "\224lcl\332\331\256\252",
  21.925 -    #endif
  21.926 -    seqsize(3,3) - seqsize(1,1)
  21.927 -  },
  21.928 -  {
  21.929 -    #ifdef SCPACK
  21.930 -      ";$lcl %1 %2!stack -4!zero.pri!stor.s.pri %2!;$exp!",
  21.931 -      ";$lcl %1 %2!push.c 0!;$exp!",
  21.932 -    #else
  21.933 -      "\224lcl\332\227ack -4!\373\227or\222\230\252",
  21.934 -      "\224lcl\332\331 0!\252",
  21.935 -    #endif
  21.936 -    seqsize(3,2) - seqsize(1,1)
  21.937 -  },
  21.938 -  /* During a calculation, the intermediate result must sometimes
  21.939 -   * be moved from PRI to ALT, like in:
  21.940 -   *    push.pri                move.alt
  21.941 -   *    load.s.pri n1           load.s.pri n1
  21.942 -   *    pop.alt                 -
  21.943 -   *
  21.944 -   * The above also accurs for "load.pri" and for "const.pri",
  21.945 -   * so add another two cases.
  21.946 -   */
  21.947 -  {
  21.948 -    #ifdef SCPACK
  21.949 -      "push.pri!load.s.pri %1!pop.alt!",
  21.950 -      "move.alt!load.s.pri %1!",
  21.951 -    #else
  21.952 -      "\244\333\241",
  21.953 -      "\306\333",
  21.954 -    #endif
  21.955 -    seqsize(3,1) - seqsize(2,1)
  21.956 -  },
  21.957 -  {
  21.958 -    #ifdef SCPACK
  21.959 -      "push.pri!load.pri %1!pop.alt!",
  21.960 -      "move.alt!load.pri %1!",
  21.961 -    #else
  21.962 -      "\244\311\241",
  21.963 -      "\306\311",
  21.964 -    #endif
  21.965 -    seqsize(3,1) - seqsize(2,1)
  21.966 -  },
  21.967 -  {
  21.968 -    #ifdef SCPACK
  21.969 -      "push.pri!const.pri %1!pop.alt!",
  21.970 -      "move.alt!const.pri %1!",
  21.971 -    #else
  21.972 -      "\244\330\241",
  21.973 -      "\306\330",
  21.974 -    #endif
  21.975 -    seqsize(3,1) - seqsize(2,1)
  21.976 -  },
  21.977 -  {
  21.978 -    #ifdef SCPACK
  21.979 -      "push.pri!zero.pri!pop.alt!",
  21.980 -      "move.alt!zero.pri!",
  21.981 -    #else
  21.982 -      "\244\373\241",
  21.983 -      "\306\373",
  21.984 -    #endif
  21.985 -    seqsize(3,0) - seqsize(2,0)
  21.986 -  },
  21.987 -  /* saving PRI and then loading from its address
  21.988 -   * occurs when indexing a multi-dimensional array
  21.989 -   */
  21.990 -  {
  21.991 -    #ifdef SCPACK
  21.992 -      "push.pri!load.i!pop.alt!",
  21.993 -      "move.alt!load.i!",
  21.994 -    #else
  21.995 -      "\244\342i\266",
  21.996 -      "\306\342\355",
  21.997 -    #endif
  21.998 -    seqsize(3,0) - seqsize(2,0)
  21.999 -  },
 21.1000 -  /* An even simpler PUSH/POP optimization (occurs in
 21.1001 -   * switch statements):
 21.1002 -   *    push.pri                move.alt
 21.1003 -   *    pop.alt                 -
 21.1004 -   */
 21.1005 -  {
 21.1006 -    #ifdef SCPACK
 21.1007 -      "push.pri!pop.alt!",
 21.1008 -      "move.alt!",
 21.1009 -    #else
 21.1010 -      "\244\241",
 21.1011 -      "\306",
 21.1012 -    #endif
 21.1013 -    seqsize(2,0) - seqsize(1,0)
 21.1014 -  },
 21.1015 -  /* Some simple arithmetic sequences
 21.1016 -   */
 21.1017 -  {
 21.1018 -    #ifdef SCPACK
 21.1019 -      "move.alt!load.s.pri %1!add!",
 21.1020 -      "load.s.alt %1!add!",
 21.1021 -    #else
 21.1022 -      "\306\333\271",
 21.1023 -      "\375\271",
 21.1024 -    #endif
 21.1025 -    seqsize(3,1) - seqsize(2,1)
 21.1026 -  },
 21.1027 -  {
 21.1028 -    #ifdef SCPACK
 21.1029 -      "move.alt!load.pri %1!add!",
 21.1030 -      "load.alt %1!add!",
 21.1031 -    #else
 21.1032 -      "\306\311\271",
 21.1033 -      "\374\271",
 21.1034 -    #endif
 21.1035 -    seqsize(3,1) - seqsize(2,1)
 21.1036 -  },
 21.1037 -  {
 21.1038 -    #ifdef SCPACK
 21.1039 -      "move.alt!const.pri %1!add!",
 21.1040 -      "const.alt %1!add!",
 21.1041 -    #else
 21.1042 -      "\306\330\271",
 21.1043 -      "\356\271",
 21.1044 -    #endif
 21.1045 -    seqsize(3,1) - seqsize(2,1)
 21.1046 -  },
 21.1047 -  {
 21.1048 -    #ifdef SCPACK
 21.1049 -      "move.alt!load.s.pri %1!sub.alt!",
 21.1050 -      "load.s.alt %1!sub!",
 21.1051 -    #else
 21.1052 -      "\306\333sub\223",
 21.1053 -      "\375sub!",
 21.1054 -    #endif
 21.1055 -    seqsize(3,1) - seqsize(2,1)
 21.1056 -  },
 21.1057 -  {
 21.1058 -    #ifdef SCPACK
 21.1059 -      "move.alt!load.pri %1!sub.alt!",
 21.1060 -      "load.alt %1!sub!",
 21.1061 -    #else
 21.1062 -      "\306\311sub\223",
 21.1063 -      "\374sub!",
 21.1064 -    #endif
 21.1065 -    seqsize(3,1) - seqsize(2,1)
 21.1066 -  },
 21.1067 -  {
 21.1068 -    #ifdef SCPACK
 21.1069 -      "move.alt!const.pri %1!sub.alt!",
 21.1070 -      "const.alt %1!sub!",
 21.1071 -    #else
 21.1072 -      "\306\330sub\223",
 21.1073 -      "\356sub!",
 21.1074 -    #endif
 21.1075 -    seqsize(3,1) - seqsize(2,1)
 21.1076 -  },
 21.1077 -  /* User-defined operators first load the operands into registers and
 21.1078 -   * then have them pushed onto the stack. This can give rise to sequences
 21.1079 -   * like:
 21.1080 -   *    const.pri n1            push.c n1
 21.1081 -   *    const.alt n2            push.c n2
 21.1082 -   *    push.pri                -
 21.1083 -   *    push.alt                -
 21.1084 -   * A similar sequence occurs with the two PUSH.pri/alt instructions inverted.
 21.1085 -   * The first, second, or both CONST.pri/alt instructions can also be
 21.1086 -   * LOAD.pri/alt.
 21.1087 -   * This gives 2 x 4 cases.
 21.1088 -   */
 21.1089 -  {
 21.1090 -    #ifdef SCPACK
 21.1091 -      "const.pri %1!const.alt %2!push.pri!push.alt!",
 21.1092 -      "push.c %1!push.c %2!",
 21.1093 -    #else
 21.1094 -      "\330\233\304\244\354",
 21.1095 -      "\331\202\331\221",
 21.1096 -    #endif
 21.1097 -    seqsize(4,2) - seqsize(2,2)
 21.1098 -  },
 21.1099 -  {
 21.1100 -    #ifdef SCPACK
 21.1101 -      "const.pri %1!const.alt %2!push.alt!push.pri!",
 21.1102 -      "push.c %2!push.c %1!",
 21.1103 -    #else
 21.1104 -      "\330\233\304\354\244",
 21.1105 -      "\331\221\331\202",
 21.1106 -    #endif
 21.1107 -    seqsize(4,2) - seqsize(2,2)
 21.1108 -  },
 21.1109 -  {
 21.1110 -    #ifdef SCPACK
 21.1111 -      "const.pri %1!load.alt %2!push.pri!push.alt!",
 21.1112 -      "push.c %1!push %2!",
 21.1113 -    #else
 21.1114 -      "\330\362\244\354",
 21.1115 -      "\331\202\216\221",
 21.1116 -    #endif
 21.1117 -    seqsize(4,2) - seqsize(2,2)
 21.1118 -  },
 21.1119 -  {
 21.1120 -    #ifdef SCPACK
 21.1121 -      "const.pri %1!load.alt %2!push.alt!push.pri!",
 21.1122 -      "push %2!push.c %1!",
 21.1123 -    #else
 21.1124 -      "\330\362\354\244",
 21.1125 -      "\216\221\331\202",
 21.1126 -    #endif
 21.1127 -    seqsize(4,2) - seqsize(2,2)
 21.1128 -  },
 21.1129 -  {
 21.1130 -    #ifdef SCPACK
 21.1131 -      "load.pri %1!const.alt %2!push.pri!push.alt!",
 21.1132 -      "push %1!push.c %2!",
 21.1133 -    #else
 21.1134 -      "\311\233\304\244\354",
 21.1135 -      "\216\202\331\221",
 21.1136 -    #endif
 21.1137 -    seqsize(4,2) - seqsize(2,2)
 21.1138 -  },
 21.1139 -  {
 21.1140 -    #ifdef SCPACK
 21.1141 -      "load.pri %1!const.alt %2!push.alt!push.pri!",
 21.1142 -      "push.c %2!push %1!",
 21.1143 -    #else
 21.1144 -      "\311\233\304\354\244",
 21.1145 -      "\331\221\216\202",
 21.1146 -    #endif
 21.1147 -    seqsize(4,2) - seqsize(2,2)
 21.1148 -  },
 21.1149 -  {
 21.1150 -    #ifdef SCPACK
 21.1151 -      "load.pri %1!load.alt %2!push.pri!push.alt!",
 21.1152 -      "push %1!push %2!",
 21.1153 -    #else
 21.1154 -      "\311\362\244\354",
 21.1155 -      "\216\202\216\221",
 21.1156 -    #endif
 21.1157 -    seqsize(4,2) - seqsize(2,2)
 21.1158 -  },
 21.1159 -  {
 21.1160 -    #ifdef SCPACK
 21.1161 -      "load.pri %1!load.alt %2!push.alt!push.pri!",
 21.1162 -      "push %2!push %1!",
 21.1163 -    #else
 21.1164 -      "\311\362\354\244",
 21.1165 -      "\216\221\216\202",
 21.1166 -    #endif
 21.1167 -    seqsize(4,2) - seqsize(2,2)
 21.1168 -  },
 21.1169 -  /* Function calls (parameters are passed on the stack)
 21.1170 -   *    load.s.pri n1           push.s n1
 21.1171 -   *    push.pri                -
 21.1172 -   *    --------------------------------------
 21.1173 -   *    load.pri n1             push n1
 21.1174 -   *    push.pri                -
 21.1175 -   *    --------------------------------------
 21.1176 -   *    const.pri n1            push.c n1
 21.1177 -   *    push.pri                -
 21.1178 -   *    --------------------------------------
 21.1179 -   *    zero.pri                push.c 0
 21.1180 -   *    push.pri                -
 21.1181 -   *    --------------------------------------
 21.1182 -   *    addr.pri n1             push.adr n1
 21.1183 -   *    push.pri                -
 21.1184 -   *
 21.1185 -   * However, PRI must not be needed after this instruction
 21.1186 -   * if this shortcut is used. Check for the ;$par comment.
 21.1187 -   */
 21.1188 -  {
 21.1189 -    #ifdef SCPACK
 21.1190 -      "load.s.pri %1!push.pri!;$par!",
 21.1191 -      "push.s %1!;$par!",
 21.1192 -    #else
 21.1193 -      "\226\264\255",
 21.1194 -      "\216\222\202\255",
 21.1195 -    #endif
 21.1196 -    seqsize(2,1) - seqsize(1,1)
 21.1197 -  },
 21.1198 -  {
 21.1199 -    #ifdef SCPACK
 21.1200 -      "load.pri %1!push.pri!;$par!",
 21.1201 -      "push %1!;$par!",
 21.1202 -    #else
 21.1203 -      "\217\264\255",
 21.1204 -      "\216\202\255",
 21.1205 -    #endif
 21.1206 -    seqsize(2,1) - seqsize(1,1)
 21.1207 -  },
 21.1208 -  {
 21.1209 -    #ifdef SCPACK
 21.1210 -      "const.pri %1!push.pri!;$par!",
 21.1211 -      "push.c %1!;$par!",
 21.1212 -    #else
 21.1213 -      "\233\264\255",
 21.1214 -      "\331\202\255",
 21.1215 -    #endif
 21.1216 -    seqsize(2,1) - seqsize(1,1)
 21.1217 -  },
 21.1218 -  {
 21.1219 -    #ifdef SCPACK
 21.1220 -      "zero.pri!push.pri!;$par!",
 21.1221 -      "push.c 0!;$par!",
 21.1222 -    #else
 21.1223 -      "\373\244\255",
 21.1224 -      "\331 0!\255",
 21.1225 -    #endif
 21.1226 -    seqsize(2,0) - seqsize(1,1)
 21.1227 -  },
 21.1228 -  {
 21.1229 -    #ifdef SCPACK
 21.1230 -      "addr.pri %1!push.pri!;$par!",
 21.1231 -      "push.adr %1!;$par!",
 21.1232 -    #else
 21.1233 -      "\265\264\255",
 21.1234 -      "\216\326\202\255",
 21.1235 -    #endif
 21.1236 -    seqsize(2,1) - seqsize(1,1)
 21.1237 -  },
 21.1238 -  /* References with a default value generate new cells on the heap
 21.1239 -   * dynamically. That code often ends with:
 21.1240 -   *    move.pri                push.alt
 21.1241 -   *    push.pri                -
 21.1242 -   */
 21.1243 -  {
 21.1244 -    #ifdef SCPACK
 21.1245 -      "move.pri!push.pri!",
 21.1246 -      "push.alt!",
 21.1247 -    #else
 21.1248 -      "\300\236\244",
 21.1249 -      "\354",
 21.1250 -    #endif
 21.1251 -    seqsize(2,0) - seqsize(1,0)
 21.1252 -  },
 21.1253 -  /* Simple arithmetic operations on constants. Noteworthy is the
 21.1254 -   * subtraction of a constant, since it is converted to the addition
 21.1255 -   * of the inverse value.
 21.1256 -   *    const.alt n1            add.c n1
 21.1257 -   *    add                     -
 21.1258 -   *    --------------------------------------
 21.1259 -   *    const.alt n1            add.c -n1
 21.1260 -   *    sub                     -
 21.1261 -   *    --------------------------------------
 21.1262 -   *    const.alt n1            smul.c n1
 21.1263 -   *    smul                    -
 21.1264 -   *    --------------------------------------
 21.1265 -   *    const.alt n1            eq.c.pri n1
 21.1266 -   *    eq                      -
 21.1267 -   */
 21.1268 -  {
 21.1269 -    #ifdef SCPACK
 21.1270 -      "const.alt %1!add!",
 21.1271 -      "add.c %1!",
 21.1272 -    #else
 21.1273 -      "\356\271",
 21.1274 -      "\235\242\202",
 21.1275 -    #endif
 21.1276 -    seqsize(2,1) - seqsize(1,1)
 21.1277 -  },
 21.1278 -  {
 21.1279 -    #ifdef SCPACK
 21.1280 -      "const.alt %1!sub!",
 21.1281 -      "add.c -%1!",
 21.1282 -    #else
 21.1283 -      "\356sub!",
 21.1284 -      "\235\242 -\201",
 21.1285 -    #endif
 21.1286 -    seqsize(2,1) - seqsize(1,1)
 21.1287 -  },
 21.1288 -  {
 21.1289 -    #ifdef SCPACK
 21.1290 -      "const.alt %1!smul!",
 21.1291 -      "smul.c %1!",
 21.1292 -    #else
 21.1293 -      "\356smul!",
 21.1294 -      "smu\307\202",
 21.1295 -    #endif
 21.1296 -    seqsize(2,1) - seqsize(1,1)
 21.1297 -  },
 21.1298 -  {
 21.1299 -    #ifdef SCPACK
 21.1300 -      "const.alt %1!eq!",
 21.1301 -      "eq.c.pri %1!",
 21.1302 -    #else
 21.1303 -      "\356\325",
 21.1304 -      "\262\242\225",
 21.1305 -    #endif
 21.1306 -    seqsize(2,1) - seqsize(1,1)
 21.1307 -  },
 21.1308 -  /* Some operations use the alternative subtraction operation --these
 21.1309 -   * can also be optimized.
 21.1310 -   *    const.pri n1            load.s.pri n2
 21.1311 -   *    load.s.alt n2           add.c -n1
 21.1312 -   *    sub.alt                 -
 21.1313 -   *    --------------------------------------
 21.1314 -   *    const.pri n1            load.pri n2
 21.1315 -   *    load.alt n2             add.c -n1
 21.1316 -   *    sub.alt                 -
 21.1317 -   */
 21.1318 -  {
 21.1319 -    #ifdef SCPACK
 21.1320 -      "const.pri %1!load.s.alt %2!sub.alt!",
 21.1321 -      "load.s.pri %2!add.c -%1!",
 21.1322 -    #else
 21.1323 -      "\330\226\304sub\223",
 21.1324 -      "\246\235\242 -\201",
 21.1325 -    #endif
 21.1326 -    seqsize(3,2) - seqsize(2,2)
 21.1327 -  },
 21.1328 -  {
 21.1329 -    #ifdef SCPACK
 21.1330 -      "const.pri %1!load.alt %2!sub.alt!",
 21.1331 -      "load.pri %2!add.c -%1!",
 21.1332 -    #else
 21.1333 -      "\330\362sub\223",
 21.1334 -      "\334\235\242 -\201",
 21.1335 -    #endif
 21.1336 -    seqsize(3,2) - seqsize(2,2)
 21.1337 -  },
 21.1338 -  /* With arrays indexed with constants that come from enumerations, it happens
 21.1339 -   * multiple add.c opcodes follow in sequence.
 21.1340 -   *    add.c n1                add.c n1+n2
 21.1341 -   *    add.c n2                -
 21.1342 -   */
 21.1343 -  {
 21.1344 -    #ifdef SCPACK
 21.1345 -      "add.c %1!add.c %2!",
 21.1346 -      "add.c %1+%2!",
 21.1347 -    #else
 21.1348 -      "\235\242\202\235\242\221",
 21.1349 -      "\235\242\267+%2!",
 21.1350 -    #endif
 21.1351 -    seqsize(2,2) - seqsize(1,1)
 21.1352 -  },
 21.1353 -  /* Compare and jump
 21.1354 -   *    eq                      jneq n1
 21.1355 -   *    jzer n1                 -
 21.1356 -   *    --------------------------------------
 21.1357 -   *    eq                      jeq n1
 21.1358 -   *    jnz n1                  -
 21.1359 -   *    --------------------------------------
 21.1360 -   *    neq                     jeq n1
 21.1361 -   *    jzer n1                 -
 21.1362 -   *    --------------------------------------
 21.1363 -   *    neq                     jneq n1
 21.1364 -   *    jnz n1                  -
 21.1365 -   * Compares followed by jzer occur much more
 21.1366 -   * often than compares followed with jnz. So we
 21.1367 -   * take the easy route here.
 21.1368 -   *    less                    jgeq n1
 21.1369 -   *    jzer n1                 -
 21.1370 -   *    --------------------------------------
 21.1371 -   *    leq                     jgrtr n1
 21.1372 -   *    jzer n1                 -
 21.1373 -   *    --------------------------------------
 21.1374 -   *    grtr                    jleq n1
 21.1375 -   *    jzer n1                 -
 21.1376 -   *    --------------------------------------
 21.1377 -   *    geq                     jless n1
 21.1378 -   *    jzer n1                 -
 21.1379 -   *    --------------------------------------
 21.1380 -   *    sless                   jsgeq n1
 21.1381 -   *    jzer n1                 -
 21.1382 -   *    --------------------------------------
 21.1383 -   *    sleq                    jsgrtr n1
 21.1384 -   *    jzer n1                 -
 21.1385 -   *    --------------------------------------
 21.1386 -   *    sgrtr                   jsleq n1
 21.1387 -   *    jzer n1                 -
 21.1388 -   *    --------------------------------------
 21.1389 -   *    sgeq                    jsless n1
 21.1390 -   *    jzer n1                 -
 21.1391 -   */
 21.1392 -  {
 21.1393 -    #ifdef SCPACK
 21.1394 -      "eq!jzer %1!",
 21.1395 -      "jneq %1!",
 21.1396 -    #else
 21.1397 -      "\325\323",
 21.1398 -      "jn\357",
 21.1399 -    #endif
 21.1400 -    seqsize(2,1) - seqsize(1,1)
 21.1401 -  },
 21.1402 -  {
 21.1403 -    #ifdef SCPACK
 21.1404 -      "eq!jnz %1!",
 21.1405 -      "jeq %1!",
 21.1406 -    #else
 21.1407 -      "\325jnz\202",
 21.1408 -      "j\357",
 21.1409 -    #endif
 21.1410 -    seqsize(2,1) - seqsize(1,1)
 21.1411 -  },
 21.1412 -  {
 21.1413 -    #ifdef SCPACK
 21.1414 -      "neq!jzer %1!",
 21.1415 -      "jeq %1!",
 21.1416 -    #else
 21.1417 -      "n\325\323",
 21.1418 -      "j\357",
 21.1419 -    #endif
 21.1420 -    seqsize(2,1) - seqsize(1,1)
 21.1421 -  },
 21.1422 -  {
 21.1423 -    #ifdef SCPACK
 21.1424 -      "neq!jnz %1!",
 21.1425 -      "jneq %1!",
 21.1426 -    #else
 21.1427 -      "n\325jnz\202",
 21.1428 -      "jn\357",
 21.1429 -    #endif
 21.1430 -    seqsize(2,1) - seqsize(1,1)
 21.1431 -  },
 21.1432 -  {
 21.1433 -    #ifdef SCPACK
 21.1434 -      "less!jzer %1!",
 21.1435 -      "jgeq %1!",
 21.1436 -    #else
 21.1437 -      "l\352!\323",
 21.1438 -      "jg\357",
 21.1439 -    #endif
 21.1440 -    seqsize(2,1) - seqsize(1,1)
 21.1441 -  },
 21.1442 -  {
 21.1443 -    #ifdef SCPACK
 21.1444 -      "leq!jzer %1!",
 21.1445 -      "jgrtr %1!",
 21.1446 -    #else
 21.1447 -      "l\325\323",
 21.1448 -      "jg\353r\202",
 21.1449 -    #endif
 21.1450 -    seqsize(2,1) - seqsize(1,1)
 21.1451 -  },
 21.1452 -  {
 21.1453 -    #ifdef SCPACK
 21.1454 -      "grtr!jzer %1!",
 21.1455 -      "jleq %1!",
 21.1456 -    #else
 21.1457 -      "g\353\237\323",
 21.1458 -      "jl\357",
 21.1459 -    #endif
 21.1460 -    seqsize(2,1) - seqsize(1,1)
 21.1461 -  },
 21.1462 -  {
 21.1463 -    #ifdef SCPACK
 21.1464 -      "geq!jzer %1!",
 21.1465 -      "jless %1!",
 21.1466 -    #else
 21.1467 -      "g\325\323",
 21.1468 -      "jl\352\202",
 21.1469 -    #endif
 21.1470 -    seqsize(2,1) - seqsize(1,1)
 21.1471 -  },
 21.1472 -  {
 21.1473 -    #ifdef SCPACK
 21.1474 -      "sless!jzer %1!",
 21.1475 -      "jsgeq %1!",
 21.1476 -    #else
 21.1477 -      "\372!\323",
 21.1478 -      "j\320\357",
 21.1479 -    #endif
 21.1480 -    seqsize(2,1) - seqsize(1,1)
 21.1481 -  },
 21.1482 -  {
 21.1483 -    #ifdef SCPACK
 21.1484 -      "sleq!jzer %1!",
 21.1485 -      "jsgrtr %1!",
 21.1486 -    #else
 21.1487 -      "\321\325\323",
 21.1488 -      "j\371r\202",
 21.1489 -    #endif
 21.1490 -    seqsize(2,1) - seqsize(1,1)
 21.1491 -  },
 21.1492 -  {
 21.1493 -    #ifdef SCPACK
 21.1494 -      "sgrtr!jzer %1!",
 21.1495 -      "jsleq %1!",
 21.1496 -    #else
 21.1497 -      "\371\237\323",
 21.1498 -      "j\321\357",
 21.1499 -    #endif
 21.1500 -    seqsize(2,1) - seqsize(1,1)
 21.1501 -  },
 21.1502 -  {
 21.1503 -    #ifdef SCPACK
 21.1504 -      "sgeq!jzer %1!",
 21.1505 -      "jsless %1!",
 21.1506 -    #else
 21.1507 -      "\320\325\323",
 21.1508 -      "j\372\202",
 21.1509 -    #endif
 21.1510 -    seqsize(2,1) - seqsize(1,1)
 21.1511 -  },
 21.1512 -  /* Test for zero (common case, especially for strings)
 21.1513 -   * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)"
 21.1514 -   *
 21.1515 -   *    zero.alt                jzer n1
 21.1516 -   *    jeq n1                  -
 21.1517 -   *    --------------------------------------
 21.1518 -   *    zero.alt                jnz n1
 21.1519 -   *    jneq n1                 -
 21.1520 -   */
 21.1521 -  {
 21.1522 -    #ifdef SCPACK
 21.1523 -      "zero.alt!jeq %1!",
 21.1524 -      "jzer %1!",
 21.1525 -    #else
 21.1526 -      "\340\223j\357",
 21.1527 -      "\323",
 21.1528 -    #endif
 21.1529 -    seqsize(2,1) - seqsize(1,1)
 21.1530 -  },
 21.1531 -  {
 21.1532 -    #ifdef SCPACK
 21.1533 -      "zero.alt!jneq %1!",
 21.1534 -      "jnz %1!",
 21.1535 -    #else
 21.1536 -      "\340\223jn\357",
 21.1537 -      "jnz\202",
 21.1538 -    #endif
 21.1539 -    seqsize(2,1) - seqsize(1,1)
 21.1540 -  },
 21.1541 -  /* Incrementing and decrementing leaves a value in
 21.1542 -   * in PRI which may not be used (for example, as the
 21.1543 -   * third expression in a "for" loop).
 21.1544 -   *    inc n1                  inc n1  ; ++n
 21.1545 -   *    load.pri n1             ;$exp
 21.1546 -   *    ;$exp                   -
 21.1547 -   *    --------------------------------------
 21.1548 -   *    load.pri n1             inc n1  ; n++, e.g. "for (n=0; n<10; n++)"
 21.1549 -   *    inc n1                  ;$exp
 21.1550 -   *    ;$exp                   -
 21.1551 -   * Plus the varieties for stack relative increments
 21.1552 -   * and decrements.
 21.1553 -   */
 21.1554 -  {
 21.1555 -    #ifdef SCPACK
 21.1556 -      "inc %1!load.pri %1!;$exp!",
 21.1557 -      "inc %1!;$exp!",
 21.1558 -    #else
 21.1559 -      "inc\202\311\252",
 21.1560 -      "inc\301",
 21.1561 -    #endif
 21.1562 -    seqsize(2,2) - seqsize(1,1)
 21.1563 -  },
 21.1564 -  {
 21.1565 -    #ifdef SCPACK
 21.1566 -      "load.pri %1!inc %1!;$exp!",
 21.1567 -      "inc %1!;$exp!",
 21.1568 -    #else
 21.1569 -      "\311inc\301",
 21.1570 -      "inc\301",
 21.1571 -    #endif
 21.1572 -    seqsize(2,2) - seqsize(1,1)
 21.1573 -  },
 21.1574 -  {
 21.1575 -    #ifdef SCPACK
 21.1576 -      "inc.s %1!load.s.pri %1!;$exp!",
 21.1577 -      "inc.s %1!;$exp!",
 21.1578 -    #else
 21.1579 -      "inc\222\202\333\252",
 21.1580 -      "inc\222\301",
 21.1581 -    #endif
 21.1582 -    seqsize(2,2) - seqsize(1,1)
 21.1583 -  },
 21.1584 -  {
 21.1585 -    #ifdef SCPACK
 21.1586 -      "load.s.pri %1!inc.s %1!;$exp!",
 21.1587 -      "inc.s %1!;$exp!",
 21.1588 -    #else
 21.1589 -      "\333inc\222\301",
 21.1590 -      "inc\222\301",
 21.1591 -    #endif
 21.1592 -    seqsize(2,2) - seqsize(1,1)
 21.1593 -  },
 21.1594 -  {
 21.1595 -    #ifdef SCPACK
 21.1596 -      "dec %1!load.pri %1!;$exp!",
 21.1597 -      "dec %1!;$exp!",
 21.1598 -    #else
 21.1599 -      "dec\202\311\252",
 21.1600 -      "dec\301",
 21.1601 -    #endif
 21.1602 -    seqsize(2,2) - seqsize(1,1)
 21.1603 -  },
 21.1604 -  {
 21.1605 -    #ifdef SCPACK
 21.1606 -      "load.pri %1!dec %1!;$exp!",
 21.1607 -      "dec %1!;$exp!",
 21.1608 -    #else
 21.1609 -      "\311dec\301",
 21.1610 -      "dec\301",
 21.1611 -    #endif
 21.1612 -    seqsize(2,2) - seqsize(1,1)
 21.1613 -  },
 21.1614 -  {
 21.1615 -    #ifdef SCPACK
 21.1616 -      "dec.s %1!load.s.pri %1!;$exp!",
 21.1617 -      "dec.s %1!;$exp!",
 21.1618 -    #else
 21.1619 -      "dec\222\202\333\252",
 21.1620 -      "dec\222\301",
 21.1621 -    #endif
 21.1622 -    seqsize(2,2) - seqsize(1,1)
 21.1623 -  },
 21.1624 -  {
 21.1625 -    #ifdef SCPACK
 21.1626 -      "load.s.pri %1!dec.s %1!;$exp!",
 21.1627 -      "dec.s %1!;$exp!",
 21.1628 -    #else
 21.1629 -      "\333dec\222\301",
 21.1630 -      "dec\222\301",
 21.1631 -    #endif
 21.1632 -    seqsize(2,2) - seqsize(1,1)
 21.1633 -  },
 21.1634 -  /* ??? the same (increments and decrements) for references */
 21.1635 -  /* Loading the constant zero has a special opcode.
 21.1636 -   * When storing zero in memory, the value of PRI must not be later on.
 21.1637 -   *    const.pri 0             zero n1
 21.1638 -   *    stor.pri n1             ;$exp
 21.1639 -   *    ;$exp                   -
 21.1640 -   *    --------------------------------------
 21.1641 -   *    const.pri 0             zero.s n1
 21.1642 -   *    stor.s.pri n1           ;$exp
 21.1643 -   *    ;$exp                   -
 21.1644 -   *    --------------------------------------
 21.1645 -   *    zero.pri                zero n1
 21.1646 -   *    stor.pri n1             ;$exp
 21.1647 -   *    ;$exp                   -
 21.1648 -   *    --------------------------------------
 21.1649 -   *    zero.pri                zero.s n1
 21.1650 -   *    stor.s.pri n1           ;$exp
 21.1651 -   *    ;$exp                   -
 21.1652 -   *    --------------------------------------
 21.1653 -   *    const.pri 0             zero.pri
 21.1654 -   *    --------------------------------------
 21.1655 -   *    const.alt 0             zero.alt
 21.1656 -   * The last two alternatives save more memory than they save
 21.1657 -   * time, but anyway...
 21.1658 -   */
 21.1659 -  {
 21.1660 -    #ifdef SCPACK
 21.1661 -      "const.pri 0!stor.pri %1!;$exp!",
 21.1662 -      "zero %1!;$exp!",
 21.1663 -    #else
 21.1664 -      "\233\206 0!\227or\225\252",
 21.1665 -      "\340\301",
 21.1666 -    #endif
 21.1667 -    seqsize(2,2) - seqsize(1,1)
 21.1668 -  },
 21.1669 -  {
 21.1670 -    #ifdef SCPACK
 21.1671 -      "const.pri 0!stor.s.pri %1!;$exp!",
 21.1672 -      "zero.s %1!;$exp!",
 21.1673 -    #else
 21.1674 -      "\233\206 0!\227or\222\225\252",
 21.1675 -      "\340\222\301",
 21.1676 -    #endif
 21.1677 -    seqsize(2,2) - seqsize(1,1)
 21.1678 -  },
 21.1679 -  {
 21.1680 -    #ifdef SCPACK
 21.1681 -      "zero.pri!stor.pri %1!;$exp!",
 21.1682 -      "zero %1!;$exp!",
 21.1683 -    #else
 21.1684 -      "\373\227or\225\252",
 21.1685 -      "\340\301",
 21.1686 -    #endif
 21.1687 -    seqsize(2,1) - seqsize(1,1)
 21.1688 -  },
 21.1689 -  {
 21.1690 -    #ifdef SCPACK
 21.1691 -      "zero.pri!stor.s.pri %1!;$exp!",
 21.1692 -      "zero.s %1!;$exp!",
 21.1693 -    #else
 21.1694 -      "\373\227or\222\225\252",
 21.1695 -      "\340\222\301",
 21.1696 -    #endif
 21.1697 -    seqsize(2,1) - seqsize(1,1)
 21.1698 -  },
 21.1699 -  {
 21.1700 -    #ifdef SCPACK
 21.1701 -      "const.pri 0!",
 21.1702 -      "zero.pri!",
 21.1703 -    #else
 21.1704 -      "\233\206 0!",
 21.1705 -      "\373",
 21.1706 -    #endif
 21.1707 -    seqsize(1,1) - seqsize(1,0)
 21.1708 -  },
 21.1709 -  {
 21.1710 -    #ifdef SCPACK
 21.1711 -      "const.alt 0!",
 21.1712 -      "zero.alt!",
 21.1713 -    #else
 21.1714 -      "\233\212 0!",
 21.1715 -      "\340\223",
 21.1716 -    #endif
 21.1717 -    seqsize(1,1) - seqsize(1,0)
 21.1718 -  },
 21.1719 -
 21.1720 -  /* ------------------ */
 21.1721 -  /* Macro instructions */
 21.1722 -  /* ------------------ */
 21.1723 -
 21.1724 -  { "", "", 0 },    /* separator, so optimizer can stop before generating macro opcodes */
 21.1725 -
 21.1726 -  /* optimizing the calling of native functions (which always have a parameter
 21.1727 -   * count pushed before, and the stack pointer restored afterwards
 21.1728 -   */
 21.1729 -  {
 21.1730 -    #ifdef SCPACK
 21.1731 -      "push.c %1!sysreq.c %2!stack %3!",        //note: %3 == %1 + 4
 21.1732 -      "sysreq.n %2 %1!",
 21.1733 -    #else
 21.1734 -      "\331\202sysr\262\242\221\227ack\256",
 21.1735 -      "sysr\262.n\220\202",
 21.1736 -    #endif
 21.1737 -    seqsize(3,3) - seqsize(1,2)
 21.1738 -  },
 21.1739 -  /* ----- */
 21.1740 -  /* Functions with many parameters with the same "type" have sequences like:
 21.1741 -   *    push.c n1               push3.c n1 n2 n3
 21.1742 -   *    ;$par                   ;$par
 21.1743 -   *    push.c n2               -
 21.1744 -   *    ;$par                   -
 21.1745 -   *    push.c n3               -
 21.1746 -   *    ;$par                   -
 21.1747 -   *    etc.                    etc.
 21.1748 -   *
 21.1749 -   * Similar sequences occur with PUSH, PUSH.s and PUSHADDR
 21.1750 -   */
 21.1751 -  {
 21.1752 -    #ifdef SCPACK
 21.1753 -      "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!push.c %5!",
 21.1754 -      "push5.c %1 %2 %3 %4 %5!",
 21.1755 -    #else
 21.1756 -      "\331\336\242\345\242\256\257\242\335\257\242\2035!",
 21.1757 -      "\2165\242\343\245\302\2035!",
 21.1758 -    #endif
 21.1759 -    seqsize(5,5) - seqsize(1,5)
 21.1760 -  },
 21.1761 -  {
 21.1762 -    #ifdef SCPACK
 21.1763 -      "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!",
 21.1764 -      "push4.c %1 %2 %3 %4!",
 21.1765 -    #else
 21.1766 -      "\331\336\242\345\242\256\257\242\335",
 21.1767 -      "\2164\242\343\245\335",
 21.1768 -    #endif
 21.1769 -    seqsize(4,4) - seqsize(1,4)
 21.1770 -  },
 21.1771 -  {
 21.1772 -    #ifdef SCPACK
 21.1773 -      "push.c %1!;$par!push.c %2!;$par!push.c %3!",
 21.1774 -      "push3.c %1 %2 %3!",
 21.1775 -    #else
 21.1776 -      "\331\336\242\345\242\256",
 21.1777 -      "\2163\242\343\256",
 21.1778 -    #endif
 21.1779 -    seqsize(3,3) - seqsize(1,3)
 21.1780 -  },
 21.1781 -  {
 21.1782 -    #ifdef SCPACK
 21.1783 -      "push.c %1!;$par!push.c %2!",
 21.1784 -      "push2.c %1 %2!",
 21.1785 -    #else
 21.1786 -      "\331\336\242\221",
 21.1787 -      "\2162\242\332",
 21.1788 -    #endif
 21.1789 -    seqsize(2,2) - seqsize(1,2)
 21.1790 -  },
 21.1791 -  /* ----- */
 21.1792 -  {
 21.1793 -    #ifdef SCPACK
 21.1794 -      "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!push %5!",
 21.1795 -      "push5 %1 %2 %3 %4 %5!",
 21.1796 -    #else
 21.1797 -      "\216\336\345\256\257\335\257\2035!",
 21.1798 -      "\2165\343\245\302\2035!",
 21.1799 -    #endif
 21.1800 -    seqsize(5,5) - seqsize(1,5)
 21.1801 -  },
 21.1802 -  {
 21.1803 -    #ifdef SCPACK
 21.1804 -      "push %1!;$par!push %2!;$par!push %3!;$par!push %4!",
 21.1805 -      "push4 %1 %2 %3 %4!",
 21.1806 -    #else
 21.1807 -      "\216\336\345\256\257\335",
 21.1808 -      "\2164\343\245\335",
 21.1809 -    #endif
 21.1810 -    seqsize(4,4) - seqsize(1,4)
 21.1811 -  },
 21.1812 -  {
 21.1813 -    #ifdef SCPACK
 21.1814 -      "push %1!;$par!push %2!;$par!push %3!",
 21.1815 -      "push3 %1 %2 %3!",
 21.1816 -    #else
 21.1817 -      "\216\336\345\256",
 21.1818 -      "\2163\343\256",
 21.1819 -    #endif
 21.1820 -    seqsize(3,3) - seqsize(1,3)
 21.1821 -  },
 21.1822 -  {
 21.1823 -    #ifdef SCPACK
 21.1824 -      "push %1!;$par!push %2!",
 21.1825 -      "push2 %1 %2!",
 21.1826 -    #else
 21.1827 -      "\216\336\221",
 21.1828 -      "\2162\332",
 21.1829 -    #endif
 21.1830 -    seqsize(2,2) - seqsize(1,2)
 21.1831 -  },
 21.1832 -  /* ----- */
 21.1833 -  {
 21.1834 -    #ifdef SCPACK
 21.1835 -      "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!push.s %5!",
 21.1836 -      "push5.s %1 %2 %3 %4 %5!",
 21.1837 -    #else
 21.1838 -      "\216\222\336\222\345\222\256\257\222\335\257\222\2035!",
 21.1839 -      "\2165\222\343\245\302\2035!",
 21.1840 -    #endif
 21.1841 -    seqsize(5,5) - seqsize(1,5)
 21.1842 -  },
 21.1843 -  {
 21.1844 -    #ifdef SCPACK
 21.1845 -      "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!",
 21.1846 -      "push4.s %1 %2 %3 %4!",
 21.1847 -    #else
 21.1848 -      "\216\222\336\222\345\222\256\257\222\335",
 21.1849 -      "\2164\222\343\245\335",
 21.1850 -    #endif
 21.1851 -    seqsize(4,4) - seqsize(1,4)
 21.1852 -  },
 21.1853 -  {
 21.1854 -    #ifdef SCPACK
 21.1855 -      "push.s %1!;$par!push.s %2!;$par!push.s %3!",
 21.1856 -      "push3.s %1 %2 %3!",
 21.1857 -    #else
 21.1858 -      "\216\222\336\222\345\222\256",
 21.1859 -      "\2163\222\343\256",
 21.1860 -    #endif
 21.1861 -    seqsize(3,3) - seqsize(1,3)
 21.1862 -  },
 21.1863 -  {
 21.1864 -    #ifdef SCPACK
 21.1865 -      "push.s %1!;$par!push.s %2!",
 21.1866 -      "push2.s %1 %2!",
 21.1867 -    #else
 21.1868 -      "\216\222\336\222\221",
 21.1869 -      "\2162\222\332",
 21.1870 -    #endif
 21.1871 -    seqsize(2,2) - seqsize(1,2)
 21.1872 -  },
 21.1873 -  /* ----- */
 21.1874 -  {
 21.1875 -    #ifdef SCPACK
 21.1876 -      "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!push.adr %5!",
 21.1877 -      "push5.adr %1 %2 %3 %4 %5!",
 21.1878 -    #else
 21.1879 -      "\216\326\336\326\345\326\256\257\326\335\257\326\2035!",
 21.1880 -      "\2165\326\343\245\302\2035!",
 21.1881 -    #endif
 21.1882 -    seqsize(5,5) - seqsize(1,5)
 21.1883 -  },
 21.1884 -  {
 21.1885 -    #ifdef SCPACK
 21.1886 -      "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!",
 21.1887 -      "push4.adr %1 %2 %3 %4!",
 21.1888 -    #else
 21.1889 -      "\216\326\336\326\345\326\256\257\326\335",
 21.1890 -      "\2164\326\343\245\335",
 21.1891 -    #endif
 21.1892 -    seqsize(4,4) - seqsize(1,4)
 21.1893 -  },
 21.1894 -  {
 21.1895 -    #ifdef SCPACK
 21.1896 -      "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!",
 21.1897 -      "push3.adr %1 %2 %3!",
 21.1898 -    #else
 21.1899 -      "\216\326\336\326\345\326\256",
 21.1900 -      "\2163\326\343\256",
 21.1901 -    #endif
 21.1902 -    seqsize(3,3) - seqsize(1,3)
 21.1903 -  },
 21.1904 -  {
 21.1905 -    #ifdef SCPACK
 21.1906 -      "push.adr %1!;$par!push.adr %2!",
 21.1907 -      "push2.adr %1 %2!",
 21.1908 -    #else
 21.1909 -      "\216\326\336\326\221",
 21.1910 -      "\2162\326\332",
 21.1911 -    #endif
 21.1912 -    seqsize(2,2) - seqsize(1,2)
 21.1913 -  },
 21.1914 -  /* Loading two registers at a time
 21.1915 -   *    load.pri n1             load.both n1 n2
 21.1916 -   *    load.alt n2             -
 21.1917 -   *    --------------------------------------
 21.1918 -   *    load.alt n2             load.both n1 n2
 21.1919 -   *    load.pri n1             -
 21.1920 -   *    --------------------------------------
 21.1921 -   *    load.s.pri n1           load.s.both n1 n2
 21.1922 -   *    load.s.alt n2           -
 21.1923 -   *    --------------------------------------
 21.1924 -   *    load.s.alt n2           load.s.both n1 n2
 21.1925 -   *    load.s.pri n1           -
 21.1926 -   */
 21.1927 -  {
 21.1928 -    #ifdef SCPACK
 21.1929 -      "load.pri %1!load.alt %2!",
 21.1930 -      "load.both %1 %2!",
 21.1931 -    #else
 21.1932 -      "\311\362",
 21.1933 -      "\342\275th\332",
 21.1934 -    #endif
 21.1935 -    seqsize(2,2) - seqsize(1,2)
 21.1936 -  },
 21.1937 -  {
 21.1938 -    #ifdef SCPACK
 21.1939 -      "load.alt %2!load.pri %1!",
 21.1940 -      "load.both %1 %2!",
 21.1941 -    #else
 21.1942 -      "\362\311",
 21.1943 -      "\342\275th\332",
 21.1944 -    #endif
 21.1945 -    seqsize(2,2) - seqsize(1,2)
 21.1946 -  },
 21.1947 -  {
 21.1948 -    #ifdef SCPACK
 21.1949 -      "load.s.pri %1!load.s.alt %2!",
 21.1950 -      "load.s.both %1 %2!",
 21.1951 -    #else
 21.1952 -      "\333\226\304",
 21.1953 -      "\226.\275th\332",
 21.1954 -    #endif
 21.1955 -    seqsize(2,2) - seqsize(1,2)
 21.1956 -  },
 21.1957 -  {
 21.1958 -    #ifdef SCPACK
 21.1959 -      "load.s.alt %2!load.s.pri %1!",
 21.1960 -      "load.s.both %1 %2!",
 21.1961 -    #else
 21.1962 -      "\226\304\333",
 21.1963 -      "\226.\275th\332",
 21.1964 -    #endif
 21.1965 -    seqsize(2,2) - seqsize(1,2)
 21.1966 -  },
 21.1967 -  /* Loading two registers and then pushing them occurs with user operators
 21.1968 -   *    load.both n1 n2         push2 n1 n2
 21.1969 -   *    push.pri                -
 21.1970 -   *    push.alt                -
 21.1971 -   *    --------------------------------------
 21.1972 -   *    load.s.both n1 n2       push2.s n1 n2
 21.1973 -   *    push.pri                -
 21.1974 -   *    push.alt                -
 21.1975 -   */
 21.1976 -  {
 21.1977 -    #ifdef SCPACK
 21.1978 -      "load.both %1 %2!push.pri!push.alt!",
 21.1979 -      "push2 %1 %2!",
 21.1980 -    #else
 21.1981 -      "\342\275th\332\244\354",
 21.1982 -      "\2162\332",
 21.1983 -    #endif
 21.1984 -    seqsize(3,2) - seqsize(1,2)
 21.1985 -  },
 21.1986 -  {
 21.1987 -    #ifdef SCPACK
 21.1988 -      "load.s.both %1 %2!push.pri!push.alt!",
 21.1989 -      "push2.s %1 %2!",
 21.1990 -    #else
 21.1991 -      "\226.\275th\332\244\354",
 21.1992 -      "\2162\222\332",
 21.1993 -    #endif
 21.1994 -    seqsize(3,2) - seqsize(1,2)
 21.1995 -  },
 21.1996 -  /* Load a constant in a variable
 21.1997 -   *    const.pri n1            const n2 n1
 21.1998 -   *    stor.pri n2             -
 21.1999 -   *    --------------------------------------
 21.2000 -   *    const.pri n1            const.s n2 n1
 21.2001 -   *    stor.s.pri n2           -
 21.2002 -   */
 21.2003 -  {
 21.2004 -    #ifdef SCPACK
 21.2005 -      "const.pri %1!stor.pri %2!",
 21.2006 -      "const %2 %1!",
 21.2007 -    #else
 21.2008 -      "\330\227or\230",
 21.2009 -      "\233\220\202",
 21.2010 -    #endif
 21.2011 -    seqsize(2,2) - seqsize(1,2)
 21.2012 -  },
 21.2013 -  {
 21.2014 -    #ifdef SCPACK
 21.2015 -      "const.pri %1!stor.s.pri %2!",
 21.2016 -      "const.s %2 %1!",
 21.2017 -    #else
 21.2018 -      "\330\227or\222\230",
 21.2019 -      "\233\222\220\202",
 21.2020 -    #endif
 21.2021 -    seqsize(2,2) - seqsize(1,2)
 21.2022 -  },
 21.2023 -  /* ----- */
 21.2024 -  { NULL, NULL, 0 }
 21.2025 -};
    22.1 --- a/compiler-init/scexpand.c	Sat Jul 15 01:36:48 2006 +0000
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,68 +0,0 @@
    22.4 -/* expand.c -- Byte Pair Encoding decompression */
    22.5 -/* Copyright 1996 Philip Gage */
    22.6 -
    22.7 -/* Byte Pair Compression appeared in the September 1997
    22.8 - * issue of C/C++ Users Journal. The original source code
    22.9 - * may still be found at the web site of the magazine
   22.10 - * (www.cuj.com).
   22.11 - *
   22.12 - * The decompressor has been modified by me (Thiadmer
   22.13 - * Riemersma) to accept a string as input, instead of a
   22.14 - * complete file.
   22.15 - */
   22.16 -#include <assert.h>
   22.17 -#include <stdio.h>
   22.18 -#include "sc.h"
   22.19 -
   22.20 -#define STACKSIZE 16
   22.21 -
   22.22 -SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2])
   22.23 -{
   22.24 -  unsigned char stack[STACKSIZE];
   22.25 -  short c, top = 0;
   22.26 -  int len;
   22.27 -
   22.28 -  assert(maxlen > 0);
   22.29 -  len = 1;              /* already 1 byte for '\0' */
   22.30 -  for (;;) {
   22.31 -
   22.32 -    /* Pop byte from stack or read byte from the input string */
   22.33 -    if (top)
   22.34 -      c = stack[--top];
   22.35 -    else if ((c = *(unsigned char *)source++) == '\0')
   22.36 -      break;
   22.37 -
   22.38 -    /* Push pair on stack or output byte to the output string */
   22.39 -    if (c > 127) {
   22.40 -      assert(top+2 <= STACKSIZE);
   22.41 -      stack[top++] = pairtable[c-128][1];
   22.42 -      stack[top++] = pairtable[c-128][0];
   22.43 -    }
   22.44 -    else {
   22.45 -      len++;
   22.46 -      if (maxlen > 1) { /* reserve one byte for the '\0' */
   22.47 -        *dest++ = (char)c;
   22.48 -        maxlen--;
   22.49 -      }
   22.50 -    }
   22.51 -  }
   22.52 -  *dest = '\0';
   22.53 -  return len;           /* return number of bytes decoded */
   22.54 -}
   22.55 -
   22.56 -#if 0 /*for testing*/
   22.57 -#include "sc5.scp"
   22.58 -
   22.59 -int main (int argc, char **argv)
   22.60 -{
   22.61 -  int i;
   22.62 -  char str[128];
   22.63 -
   22.64 -  for (i=0; i<58; i++) {
   22.65 -    strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE);
   22.66 -    printf("%s", str);
   22.67 -  } /* for */
   22.68 -  return 0;
   22.69 -}
   22.70 -#endif
   22.71 -
    23.1 --- a/compiler-init/sci18n.c	Sat Jul 15 01:36:48 2006 +0000
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,428 +0,0 @@
    23.4 -/*  Codepage translation to Unicode, and UTF-8 support
    23.5 - *
    23.6 - *  The translation is based on codepage mapping files that are distributed
    23.7 - *  by the Unicode consortium, see ftp://ftp.unicode.org/Public/MAPPINGS/.
    23.8 - *
    23.9 - *  Character sets with a maximum of 256 codes are translated via a lookup
   23.10 - *  table (these are Single-Byte Character Sets). Character sets like Shift-JIS
   23.11 - *  with single-byte characters and multi-byte characters (introduced by a
   23.12 - *  leader byte) are split into two tables: the 256-entry lookup table for
   23.13 - *  the single-byte characters and an extended table for the multi-byte
   23.14 - *  characters. The extended table is allocated dynamically; the lookup table
   23.15 - *  is allocated statically, so loading SBCS tables cannot fail (if the tables
   23.16 - *  themselves are valid, of course).
   23.17 - *
   23.18 - *  Copyright (c) ITB CompuPhase, 2004-2006
   23.19 - *
   23.20 - *  This software is provided "as-is", without any express or implied warranty.
   23.21 - *  In no event will the authors be held liable for any damages arising from
   23.22 - *  the use of this software.
   23.23 - *
   23.24 - *  Permission is granted to anyone to use this software for any purpose,
   23.25 - *  including commercial applications, and to alter it and redistribute it
   23.26 - *  freely, subject to the following restrictions:
   23.27 - *
   23.28 - *  1.  The origin of this software must not be misrepresented; you must not
   23.29 - *      claim that you wrote the original software. If you use this software in
   23.30 - *      a product, an acknowledgment in the product documentation would be
   23.31 - *      appreciated but is not required.
   23.32 - *  2.  Altered source versions must be plainly marked as such, and must not be
   23.33 - *      misrepresented as being the original software.
   23.34 - *  3.  This notice may not be removed or altered from any source distribution.
   23.35 - *
   23.36 - *  Version: $Id: CODEPAGE.C,v 1.0 2004-02-18 12:13:04+01 thiadmer Exp thiadmer $
   23.37 - */
   23.38 -#include <assert.h>
   23.39 -#include <stdio.h>
   23.40 -#include <stddef.h>
   23.41 -#include <stdlib.h>
   23.42 -#include <string.h>
   23.43 -#include "sc.h"
   23.44 -
   23.45 -#if !defined TRUE
   23.46 -  #define FALSE         0
   23.47 -  #define TRUE          1
   23.48 -#endif
   23.49 -#if !defined _MAX_PATH
   23.50 -  #define _MAX_PATH     250
   23.51 -#endif
   23.52 -#if !defined DIRSEP_CHAR
   23.53 -  #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
   23.54 -    #define DIRSEP_CHAR '/'
   23.55 -  #elif defined macintosh
   23.56 -    #define DIRSEP_CHAR ':'
   23.57 -  #else
   23.58 -    #define DIRSEP_CHAR '\\'
   23.59 -  #endif
   23.60 -#endif
   23.61 -
   23.62 -#if !defined ELEMENTS
   23.63 -  #define ELEMENTS(array)       (sizeof(array) / sizeof(array[0]))
   23.64 -#endif
   23.65 -
   23.66 -#if !defined NO_CODEPAGE
   23.67 -
   23.68 -#if !defined MAXCODEPAGE
   23.69 -  #define MAXCODEPAGE   12      /* typically "cp" + 4 digits + ".txt" */
   23.70 -#endif
   23.71 -#define INVALID         0xffffu /* 0xffff and 0xfffe are invalid Unicode characters */
   23.72 -#define LEADBYTE        0xfffeu
   23.73 -
   23.74 -struct wordpair {
   23.75 -  unsigned short index;
   23.76 -  wchar_t code;
   23.77 -};
   23.78 -static char cprootpath[_MAX_PATH] = { DIRSEP_CHAR, '\0' };
   23.79 -static wchar_t bytetable[256];
   23.80 -static struct wordpair *wordtable = NULL;
   23.81 -static unsigned wordtablesize = 0;
   23.82 -static unsigned wordtabletop = 0;
   23.83 -
   23.84 -
   23.85 -/* read in a line delimited by '\r' or '\n'; do NOT store the '\r' or '\n' into
   23.86 - * the string and ignore empty lines
   23.87 - * returns 1 for success and 0 for failure
   23.88 - */
   23.89 -static int cp_readline(FILE *fp,char *string,size_t size)
   23.90 -{
   23.91 -  size_t count=0;
   23.92 -  int c;
   23.93 -  assert(size>1);
   23.94 -  while ((c=fgetc(fp))!=EOF && count<size-1) {
   23.95 -    if (c=='\r' || c=='\n') {
   23.96 -      if (count>0)  /* '\r' or '\n' ends a string */
   23.97 -        break;
   23.98 -      /* if count==0, the line started with a '\r' or '\n', or perhaps line
   23.99 -       * ends in the file are '\r\n' and we read and stopped on the '\r' of
  23.100 -       * the preceding line
  23.101 -       */
  23.102 -    } else {
  23.103 -      string[count++]=(char)c;
  23.104 -    } /* if */
  23.105 -  } /* while */
  23.106 -  string[count]='\0';
  23.107 -  return count>0;
  23.108 -}
  23.109 -
  23.110 -/* cp_path() sets the directory where all codepage files must be found (if
  23.111 - * the parameter to cp_set() specifies a full path, that is used instead).
  23.112 - * The path is specified into two parts: root and directory; the full path
  23.113 - * for the codepage direcory is just the concatenation of the two, with a
  23.114 - * directory separator in between. The directory is given in two parts,
  23.115 - * because often a program already retrieves its "home" directory and the
  23.116 - * codepages are most conveniently stored in a subdirectory of this home
  23.117 - * directory.
  23.118 - */
  23.119 -SC_FUNC int cp_path(const char *root, const char *directory)
  23.120 -{
  23.121 -  size_t len1,len2;
  23.122 -  int add_slash1,add_slash2;
  23.123 -
  23.124 -  len1= (root!=NULL) ? strlen(root) : 0;
  23.125 -  add_slash1= (len1==0 || root[len1-1]!=DIRSEP_CHAR);
  23.126 -  len2= (directory!=NULL) ? strlen(directory) : 0;
  23.127 -  add_slash2= (len2>0 && root[len2-1]!=DIRSEP_CHAR);
  23.128 -  if (len1+add_slash1+len2+add_slash2>=(_MAX_PATH-MAXCODEPAGE))
  23.129 -    return FALSE;       /* full filename may not fit */
  23.130 -  if (root!=NULL)
  23.131 -    strcpy(cprootpath,root);
  23.132 -  if (add_slash1) {
  23.133 -    assert(len1==0 || cprootpath[len1]=='\0');
  23.134 -    cprootpath[len1]=DIRSEP_CHAR;
  23.135 -    cprootpath[len1+1]='\0';
  23.136 -  } /* if */
  23.137 -  if (directory!=NULL)
  23.138 -    strcat(cprootpath,directory);
  23.139 -  if (add_slash2) {
  23.140 -    assert(cprootpath[len1+add_slash1+len2]=='\0');
  23.141 -    cprootpath[len1+add_slash1+len2]=DIRSEP_CHAR;
  23.142 -    cprootpath[len1+add_slash1+len2+1]='\0';
  23.143 -  } /* if */
  23.144 -  cp_set(NULL);         /* start with a "linear" table (no translation) */
  23.145 -  return TRUE;
  23.146 -}
  23.147 -
  23.148 -/* cp_set() loads a codepage from a file. The name parameter may be a
  23.149 - * filename (including a full path) or it may be a partial codepage name.
  23.150 - * If the name parameter is NULL, the codepage is cleared to be a "linear"
  23.151 - * table (no translation).
  23.152 - * The following files are attempted to open (where <name> specifies the
  23.153 - * value of the parameter):
  23.154 - *    <name>
  23.155 - *    <cprootpath>/<name>
  23.156 - *    <cprootpath>/<name>.txt
  23.157 - *    <cprootpath>/cp<name>
  23.158 - *    <cprootpath>/cp<name>.txt
  23.159 - */
  23.160 -SC_FUNC int cp_set(const char *name)
  23.161 -{
  23.162 -  char filename[_MAX_PATH];
  23.163 -  FILE *fp=NULL;
  23.164 -  unsigned index;
  23.165 -
  23.166 -  /* for name==NULL, set up an identity table */
  23.167 -  if (name==NULL || *name=='\0') {
  23.168 -    if (wordtable!=NULL) {
  23.169 -      free(wordtable);
  23.170 -      wordtable=NULL;
  23.171 -      wordtablesize=0;
  23.172 -      wordtabletop=0;
  23.173 -    } /* if */
  23.174 -    for (index=0; index<ELEMENTS(bytetable); index++)
  23.175 -      bytetable[index]=(wchar_t)index;
  23.176 -    return TRUE;
  23.177 -  } /* if */
  23.178 -
  23.179 -  /* try to open the file as-is */
  23.180 -  if (strchr(name,DIRSEP_CHAR)!=NULL)
  23.181 -    fp=fopen(name,"rt");
  23.182 -  if (fp==NULL) {
  23.183 -    /* try opening the file in the "root path" for codepages */
  23.184 -    if (strlen(name)>MAXCODEPAGE)
  23.185 -      return 0;
  23.186 -    assert(strlen(name)+strlen(cprootpath)<_MAX_PATH);
  23.187 -    strcpy(filename,cprootpath);
  23.188 -    strcat(filename,name);
  23.189 -    fp=fopen(filename,"rt");
  23.190 -  } /* if */
  23.191 -  if (fp==NULL) {
  23.192 -    /* try opening the file in the "root path" for codepages, with a ".txt" extension */
  23.193 -    if (strlen(name)+4>=MAXCODEPAGE)
  23.194 -      return 0;
  23.195 -    assert(strlen(filename)+4<_MAX_PATH);
  23.196 -    strcat(filename,".txt");
  23.197 -    fp=fopen(filename,"rt");
  23.198 -  } /* if */
  23.199 -  if (fp==NULL) {
  23.200 -    /* try opening the file in the "root path" for codepages, with "cp" prefixed before the name */
  23.201 -    if (strlen(name)+2>MAXCODEPAGE)
  23.202 -      return 0;
  23.203 -    assert(2+strlen(name)+strlen(cprootpath)<_MAX_PATH);
  23.204 -    strcpy(filename,cprootpath);
  23.205 -    strcat(filename,"cp");
  23.206 -    strcat(filename,name);
  23.207 -    fp=fopen(filename,"rt");
  23.208 -  } /* if */
  23.209 -  if (fp==NULL) {
  23.210 -    /* try opening the file in the "root path" for codepages, with "cp" prefixed an ".txt" appended */
  23.211 -    if (strlen(name)+2+4>MAXCODEPAGE)
  23.212 -      return 0;
  23.213 -    assert(strlen(filename)+4<_MAX_PATH);
  23.214 -    strcat(filename,".txt");
  23.215 -    fp=fopen(filename,"rt");
  23.216 -  } /* if */
  23.217 -  if (fp==NULL)
  23.218 -    return FALSE;       /* all failed */
  23.219 -
  23.220 -  /* clear the tables */
  23.221 -  for (index=0; index<ELEMENTS(bytetable); index++)
  23.222 -    bytetable[index]=INVALID;   /* special code meaning "not found" */
  23.223 -  assert(wordtablesize==0 && wordtabletop==0 && wordtable==NULL
  23.224 -         || wordtablesize>0 && wordtable!=NULL);
  23.225 -  if (wordtable!=NULL) {
  23.226 -    free(wordtable);
  23.227 -    wordtable=NULL;
  23.228 -    wordtablesize=0;
  23.229 -    wordtabletop=0;
  23.230 -  } /* if */
  23.231 -
  23.232 -  /* read in the table */
  23.233 -  while (cp_readline(fp,filename,sizeof filename)) {
  23.234 -    char *ptr;
  23.235 -    if ((ptr=strchr(filename,'#'))!=NULL)
  23.236 -      *ptr='\0';                /* strip of comment */
  23.237 -    for (ptr=filename; *ptr>0 && *ptr<' '; ptr++)
  23.238 -      /* nothing */;            /* skip leading whitespace */
  23.239 -    if (*ptr!='\0') {
  23.240 -      /* content on line */
  23.241 -      unsigned code=LEADBYTE;
  23.242 -      int num=sscanf(ptr,"%i %i",&index,&code);
  23.243 -      /* if sscanf() returns 1 and the index is in range 0..255, then the
  23.244 -       * code is a DBCS lead byte; if sscanf() returns 2 and index>=256, this
  23.245 -       * is a double byte pair (lead byte + follower)
  23.246 -       */
  23.247 -      if (num>=1 && index<256) {
  23.248 -        bytetable[index]=(wchar_t)code;
  23.249 -      } else if (num==2 && index>=256 && index<LEADBYTE) {
  23.250 -        /* store the DBCS character in wordtable */
  23.251 -        if (wordtabletop>=wordtablesize) {
  23.252 -          /* grow the list */
  23.253 -          int newsize;
  23.254 -          struct wordpair *newblock;
  23.255 -          newsize= (wordtablesize==0) ? 128 : 2*wordtablesize;
  23.256 -          newblock=(struct wordpair *)malloc(newsize*sizeof(*wordtable));
  23.257 -          if (newblock!=NULL) {
  23.258 -            memcpy(newblock,wordtable,wordtabletop*sizeof(*wordtable));
  23.259 -            free(wordtable);
  23.260 -            wordtable=newblock;
  23.261 -            wordtablesize=newsize;
  23.262 -          } /* if */
  23.263 -        } /* if */
  23.264 -        if (wordtabletop<wordtablesize) {
  23.265 -          /* insert at sorted position */
  23.266 -          int pos=wordtabletop;
  23.267 -          assert(wordtable!=NULL);
  23.268 -          while (pos>0 && (unsigned)wordtable[pos-1].index>index) {
  23.269 -            wordtable[pos]=wordtable[pos-1];
  23.270 -            pos--;
  23.271 -          } /* while */
  23.272 -          wordtable[pos].index=(unsigned short)index;
  23.273 -          wordtable[pos].code=(wchar_t)code;
  23.274 -        } /* if */
  23.275 -      } /* if */
  23.276 -    } /* if */
  23.277 -  } /* while */
  23.278 -
  23.279 -  fclose(fp);
  23.280 -  return TRUE;
  23.281 -}
  23.282 -
  23.283 -SC_FUNC cell cp_translate(const unsigned char *string,const unsigned char **endptr)
  23.284 -{
  23.285 -  wchar_t result;
  23.286 -
  23.287 -  result=bytetable[*string++];
  23.288 -  /* check whether this is a leader code */
  23.289 -  if ((unsigned)result==LEADBYTE && wordtable!=NULL) {
  23.290 -    /* look up the code via binary search */
  23.291 -    int low,high,mid;
  23.292 -    unsigned short index=(unsigned short)(((*(string-1)) << 8) | *string);
  23.293 -    string++;
  23.294 -    assert(wordtabletop>0);
  23.295 -    low=0;
  23.296 -    high=wordtabletop-1;
  23.297 -    while (low<high) {
  23.298 -      mid=(low+high)/2;
  23.299 -      assert(low<=mid && mid<high);
  23.300 -      if (index>wordtable[mid].index)
  23.301 -        low=mid+1;
  23.302 -      else
  23.303 -        high=mid;
  23.304 -    } /* while */
  23.305 -    assert(low==high);
  23.306 -    if (wordtable[low].index==index)
  23.307 -      result=wordtable[low].code;
  23.308 -  } /* if */
  23.309 -
  23.310 -  if (endptr!=NULL)
  23.311 -    *endptr=string;
  23.312 -  return (cell)result;
  23.313 -}
  23.314 -
  23.315 -#endif  /* NO_CODEPAGE */
  23.316 -
  23.317 -#if !defined NO_UTF8
  23.318 -SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **endptr)
  23.319 -{
  23.320 -  int follow=0;
  23.321 -  long lowmark=0;
  23.322 -  unsigned char ch;
  23.323 -  cell result=0;
  23.324 -
  23.325 -  if (endptr!=NULL)
  23.326 -    *endptr=string;
  23.327 -
  23.328 -  for ( ;; ) {
  23.329 -    ch=*string++;
  23.330 -
  23.331 -    if (follow>0 && (ch & 0xc0)==0x80) {
  23.332 -      /* leader code is active, combine with earlier code */
  23.333 -      result=(result << 6) | (ch & 0x3f);
  23.334 -      if (--follow==0) {
  23.335 -        /* encoding a character in more bytes than is strictly needed,
  23.336 -         * is not really valid UTF-8; we are strict here to increase
  23.337 -         * the chance of heuristic dectection of non-UTF-8 text
  23.338 -         * (JAVA writes zero bytes as a 2-byte code UTF-8, which is invalid)
  23.339 -         */
  23.340 -        if (result<lowmark)
  23.341 -          return -1;
  23.342 -        /* the code positions 0xd800--0xdfff and 0xfffe & 0xffff do not
  23.343 -         * exist in UCS-4 (and hence, they do not exist in Unicode)
  23.344 -         */
  23.345 -        if (result>=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff)
  23.346 -          return -1;
  23.347 -      } /* if */
  23.348 -      break;
  23.349 -    } else if (follow==0 && (ch & 0x80)==0x80) {
  23.350 -      /* UTF-8 leader code */
  23.351 -      if ((ch & 0xe0)==0xc0) {
  23.352 -        /* 110xxxxx 10xxxxxx */
  23.353 -        follow=1;
  23.354 -        lowmark=0x80L;
  23.355 -        result=ch & 0x1f;
  23.356 -      } else if ((ch & 0xf0)==0xe0) {
  23.357 -        /* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */
  23.358 -        follow=2;
  23.359 -        lowmark=0x800L;
  23.360 -        result=ch & 0x0f;
  23.361 -      } else if ((ch & 0xf8)==0xf0) {
  23.362 -        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  23.363 -        follow=3;
  23.364 -        lowmark=0x10000L;
  23.365 -        result=ch & 0x07;
  23.366 -      } else if ((ch & 0xfc)==0xf8) {
  23.367 -        /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  23.368 -        follow=4;
  23.369 -        lowmark=0x200000L;
  23.370 -        result=ch & 0x03;
  23.371 -      } else if ((ch & 0xfe)==0xfc) {
  23.372 -        /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (32 bits) */
  23.373 -        follow=5;
  23.374 -        lowmark=0x4000000L;
  23.375 -        result=ch & 0x01;
  23.376 -      } else {
  23.377 -        /* this is invalid UTF-8 */
  23.378 -        return -1;
  23.379 -      } /* if */
  23.380 -    } else if (follow==0 && (ch & 0x80)==0x00) {
  23.381 -      /* 0xxxxxxx (US-ASCII) */
  23.382 -      result=ch;
  23.383 -      break;
  23.384 -    } else {
  23.385 -      /* this is invalid UTF-8 */
  23.386 -      return -1;
  23.387 -    } /* if */
  23.388 -
  23.389 -  } /* for */
  23.390 -
  23.391 -  if (endptr!=NULL)
  23.392 -    *endptr=string;
  23.393 -  return result;
  23.394 -}
  23.395 -#endif
  23.396 -
  23.397 -SC_FUNC int scan_utf8(FILE *fp,const char *filename)
  23.398 -{
  23.399 -  #if defined NO_UTF8
  23.400 -    return 0;
  23.401 -  #else
  23.402 -    void *resetpos=pc_getpossrc(fp);
  23.403 -    int utf8=TRUE;
  23.404 -    int firstchar=TRUE,bom_found=FALSE;
  23.405 -    const unsigned char *ptr;
  23.406 -
  23.407 -    while (utf8 && pc_readsrc(fp,pline,sLINEMAX)!=NULL) {
  23.408 -      ptr=pline;
  23.409 -      if (firstchar) {
  23.410 -        /* check whether the very first character on the very first line
  23.411 -         * starts with a BYTE order mark
  23.412 -         */
  23.413 -        cell c=get_utf8_char(ptr,&ptr);
  23.414 -        bom_found= (c==0xfeff);
  23.415 -        utf8= (c>=0);
  23.416 -        firstchar=FALSE;
  23.417 -      } /* if */
  23.418 -      while (utf8 && *ptr!='\0')
  23.419 -        utf8= (get_utf8_char(ptr,&ptr)>=0);
  23.420 -    } /* while */
  23.421 -    pc_resetsrc(fp,resetpos);
  23.422 -    if (bom_found) {
  23.423 -      unsigned char bom[3];
  23.424 -      if (!utf8)
  23.425 -        error(77,filename);     /* malformed UTF-8 encoding */
  23.426 -      pc_readsrc(fp,bom,3);
  23.427 -      assert(bom[0]==0xef && bom[1]==0xbb && bom[2]==0xbf);
  23.428 -    } /* if */
  23.429 -    return utf8;
  23.430 -  #endif  /* NO_UTF8 */
  23.431 -}
    24.1 --- a/compiler-init/sclist.c	Sat Jul 15 01:36:48 2006 +0000
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,486 +0,0 @@
    24.4 -/*  Pawn compiler  - maintenance of various lists
    24.5 - *
    24.6 - *  o  Name list (aliases)
    24.7 - *  o  Include path list
    24.8 - *  o  Macro defintions (text substitutions)
    24.9 - *
   24.10 - *  Copyright (c) ITB CompuPhase, 2001-2006
   24.11 - *
   24.12 - *  This software is provided "as-is", without any express or implied warranty.
   24.13 - *  In no event will the authors be held liable for any damages arising from
   24.14 - *  the use of this software.
   24.15 - *
   24.16 - *  Permission is granted to anyone to use this software for any purpose,
   24.17 - *  including commercial applications, and to alter it and redistribute it
   24.18 - *  freely, subject to the following restrictions:
   24.19 - *
   24.20 - *  1.  The origin of this software must not be misrepresented; you must not
   24.21 - *      claim that you wrote the original software. If you use this software in
   24.22 - *      a product, an acknowledgment in the product documentation would be
   24.23 - *      appreciated but is not required.
   24.24 - *  2.  Altered source versions must be plainly marked as such, and must not be
   24.25 - *      misrepresented as being the original software.
   24.26 - *  3.  This notice may not be removed or altered from any source distribution.
   24.27 - *
   24.28 - *  Version: $Id: sclist.c 3579 2006-06-06 13:35:29Z thiadmer $
   24.29 - */
   24.30 -#include <assert.h>
   24.31 -#include <limits.h>
   24.32 -#include <stdlib.h>
   24.33 -#include <string.h>
   24.34 -#include "sc.h"
   24.35 -
   24.36 -#if defined FORTIFY
   24.37 -  #include <alloc/fortify.h>
   24.38 -#endif
   24.39 -
   24.40 -/* a "private" implementation of strdup(), so that porting
   24.41 - * to other memory allocators becomes easier.
   24.42 - * By S�ren Hannibal.
   24.43 - */
   24.44 -SC_FUNC char* duplicatestring(const char* sourcestring)
   24.45 -{
   24.46 -  char* result=(char*)malloc(strlen(sourcestring)+1);
   24.47 -  strcpy(result,sourcestring);
   24.48 -  return result;
   24.49 -}
   24.50 -
   24.51 -
   24.52 -static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
   24.53 -{
   24.54 -  stringpair *cur,*pred;
   24.55 -
   24.56 -  assert(root!=NULL);
   24.57 -  assert(first!=NULL);
   24.58 -  assert(second!=NULL);
   24.59 -  /* create a new node, and check whether all is okay */
   24.60 -  if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
   24.61 -    return NULL;
   24.62 -  cur->first=duplicatestring(first);
   24.63 -  cur->second=duplicatestring(second);
   24.64 -  cur->matchlength=matchlength;
   24.65 -  if (cur->first==NULL || cur->second==NULL) {
   24.66 -    if (cur->first!=NULL)
   24.67 -      free(cur->first);
   24.68 -    if (cur->second!=NULL)
   24.69 -      free(cur->second);
   24.70 -    free(cur);
   24.71 -    return NULL;
   24.72 -  } /* if */
   24.73 -  /* link the node to the tree, find the position */
   24.74 -  for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
   24.75 -    /* nothing */;
   24.76 -  cur->next=pred->next;
   24.77 -  pred->next=cur;
   24.78 -  return cur;
   24.79 -}
   24.80 -
   24.81 -static void delete_stringpairtable(stringpair *root)
   24.82 -{
   24.83 -  stringpair *cur, *next;
   24.84 -
   24.85 -  assert(root!=NULL);
   24.86 -  cur=root->next;
   24.87 -  while (cur!=NULL) {
   24.88 -    next=cur->next;
   24.89 -    assert(cur->first!=NULL);
   24.90 -    assert(cur->second!=NULL);
   24.91 -    free(cur->first);
   24.92 -    free(cur->second);
   24.93 -    free(cur);
   24.94 -    cur=next;
   24.95 -  } /* while */
   24.96 -  memset(root,0,sizeof(stringpair));
   24.97 -}
   24.98 -
   24.99 -static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
  24.100 -{
  24.101 -  int result=0;
  24.102 -
  24.103 -  assert(matchlength>0);  /* the function cannot handle zero-length comparison */
  24.104 -  assert(first!=NULL);
  24.105 -  while (cur!=NULL && result<=0) {
  24.106 -    result=(int)*cur->first - (int)*first;
  24.107 -    if (result==0 && matchlength==cur->matchlength) {
  24.108 -      result=strncmp(cur->first,first,matchlength);
  24.109 -      if (result==0)
  24.110 -        return cur;
  24.111 -    } /* if */
  24.112 -    cur=cur->next;
  24.113 -  } /* while */
  24.114 -  return NULL;
  24.115 -}
  24.116 -
  24.117 -static int delete_stringpair(stringpair *root,stringpair *item)
  24.118 -{
  24.119 -  stringpair *cur;
  24.120 -
  24.121 -  assert(root!=NULL);
  24.122 -  cur=root;
  24.123 -  while (cur->next!=NULL) {
  24.124 -    if (cur->next==item) {
  24.125 -      cur->next=item->next;     /* unlink from list */
  24.126 -      assert(item->first!=NULL);
  24.127 -      assert(item->second!=NULL);
  24.128 -      free(item->first);
  24.129 -      free(item->second);
  24.130 -      free(item);
  24.131 -      return TRUE;
  24.132 -    } /* if */
  24.133 -    cur=cur->next;
  24.134 -  } /* while */
  24.135 -  return FALSE;
  24.136 -}
  24.137 -
  24.138 -/* ----- string list functions ----------------------------------- */
  24.139 -static stringlist *insert_string(stringlist *root,char *string)
  24.140 -{
  24.141 -  stringlist *cur;
  24.142 -
  24.143 -  assert(string!=NULL);
  24.144 -  if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
  24.145 -    error(103);       /* insufficient memory (fatal error) */
  24.146 -  if ((cur->line=duplicatestring(string))==NULL)
  24.147 -    error(103);       /* insufficient memory (fatal error) */
  24.148 -  /* insert as "last" */
  24.149 -  assert(root!=NULL);
  24.150 -  while (root->next!=NULL)
  24.151 -    root=root->next;
  24.152 -  cur->next=root->next;
  24.153 -  root->next=cur;
  24.154 -  return cur;
  24.155 -}
  24.156 -
  24.157 -static char *get_string(stringlist *root,int index)
  24.158 -{
  24.159 -  stringlist *cur;
  24.160 -
  24.161 -  assert(root!=NULL);
  24.162 -  cur=root->next;
  24.163 -  while (cur!=NULL && index-->0)
  24.164 -    cur=cur->next;
  24.165 -  if (cur!=NULL) {
  24.166 -    assert(cur->line!=NULL);
  24.167 -    return cur->line;
  24.168 -  } /* if */
  24.169 -  return NULL;
  24.170 -}
  24.171 -
  24.172 -static int delete_string(stringlist *root,int index)
  24.173 -{
  24.174 -  stringlist *cur,*item;
  24.175 -
  24.176 -  assert(root!=NULL);
  24.177 -  for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
  24.178 -    /* nothing */;
  24.179 -  if (cur->next!=NULL) {
  24.180 -    item=cur->next;
  24.181 -    cur->next=item->next;       /* unlink from list */
  24.182 -    assert(item->line!=NULL);
  24.183 -    free(item->line);
  24.184 -    free(item);
  24.185 -    return TRUE;
  24.186 -  } /* if */
  24.187 -  return FALSE;
  24.188 -}
  24.189 -
  24.190 -SC_FUNC void delete_stringtable(stringlist *root)
  24.191 -{
  24.192 -  stringlist *cur,*next;
  24.193 -
  24.194 -  assert(root!=NULL);
  24.195 -  cur=root->next;
  24.196 -  while (cur!=NULL) {
  24.197 -    next=cur->next;
  24.198 -    assert(cur->line!=NULL);
  24.199 -    free(cur->line);
  24.200 -    free(cur);
  24.201 -    cur=next;
  24.202 -  } /* while */
  24.203 -  memset(root,0,sizeof(stringlist));
  24.204 -}
  24.205 -
  24.206 -
  24.207 -/* ----- alias table --------------------------------------------- */
  24.208 -static stringpair alias_tab = {NULL, NULL, NULL};   /* alias table */
  24.209 -
  24.210 -SC_FUNC stringpair *insert_alias(char *name,char *alias)
  24.211 -{
  24.212 -  stringpair *cur;
  24.213 -
  24.214 -  assert(name!=NULL);
  24.215 -  assert(strlen(name)<=sNAMEMAX);
  24.216 -  assert(alias!=NULL);
  24.217 -  assert(strlen(alias)<=sNAMEMAX);
  24.218 -  if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
  24.219 -    error(103);       /* insufficient memory (fatal error) */
  24.220 -  return cur;
  24.221 -}
  24.222 -
  24.223 -SC_FUNC int lookup_alias(char *target,char *name)
  24.224 -{
  24.225 -  stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
  24.226 -  if (cur!=NULL) {
  24.227 -    assert(strlen(cur->second)<=sNAMEMAX);
  24.228 -    strcpy(target,cur->second);
  24.229 -  } /* if */
  24.230 -  return cur!=NULL;
  24.231 -}
  24.232 -
  24.233 -SC_FUNC void delete_aliastable(void)
  24.234 -{
  24.235 -  delete_stringpairtable(&alias_tab);
  24.236 -}
  24.237 -
  24.238 -/* ----- include paths list -------------------------------------- */
  24.239 -static stringlist includepaths = {NULL, NULL};  /* directory list for include files */
  24.240 -
  24.241 -SC_FUNC stringlist *insert_path(char *path)
  24.242 -{
  24.243 -  return insert_string(&includepaths,path);
  24.244 -}
  24.245 -
  24.246 -SC_FUNC char *get_path(int index)
  24.247 -{
  24.248 -  return get_string(&includepaths,index);
  24.249 -}
  24.250 -
  24.251 -SC_FUNC void delete_pathtable(void)
  24.252 -{
  24.253 -  delete_stringtable(&includepaths);
  24.254 -  assert(includepaths.next==NULL);
  24.255 -}
  24.256 -
  24.257 -
  24.258 -/* ----- text substitution patterns ------------------------------ */
  24.259 -#if !defined NO_DEFINE
  24.260 -
  24.261 -static stringpair substpair = { NULL, NULL, NULL};  /* list of substitution pairs */
  24.262 -
  24.263 -static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
  24.264 -static void adjustindex(char c)
  24.265 -{
  24.266 -  stringpair *cur;
  24.267 -  assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
  24.268 -  assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
  24.269 -
  24.270 -  for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
  24.271 -    /* nothing */;
  24.272 -  substindex[(int)c-PUBLIC_CHAR]=cur;
  24.273 -}
  24.274 -
  24.275 -SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
  24.276 -{
  24.277 -  stringpair *cur;
  24.278 -
  24.279 -  assert(pattern!=NULL);
  24.280 -  assert(substitution!=NULL);
  24.281 -  if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
  24.282 -    error(103);       /* insufficient memory (fatal error) */
  24.283 -  adjustindex(*pattern);
  24.284 -  return cur;
  24.285 -}
  24.286 -
  24.287 -SC_FUNC stringpair *find_subst(char *name,int length)
  24.288 -{
  24.289 -  stringpair *item;
  24.290 -  assert(name!=NULL);
  24.291 -  assert(length>0);
  24.292 -  assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
  24.293 -  item=substindex[(int)*name-PUBLIC_CHAR];
  24.294 -  if (item!=NULL)
  24.295 -    item=find_stringpair(item,name,length);
  24.296 -  return item;
  24.297 -}
  24.298 -
  24.299 -SC_FUNC int delete_subst(char *name,int length)
  24.300 -{
  24.301 -  stringpair *item;
  24.302 -  assert(name!=NULL);
  24.303 -  assert(length>0);
  24.304 -  assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
  24.305 -  item=substindex[(int)*name-PUBLIC_CHAR];
  24.306 -  if (item!=NULL)
  24.307 -    item=find_stringpair(item,name,length);
  24.308 -  if (item==NULL)
  24.309 -    return FALSE;
  24.310 -  delete_stringpair(&substpair,item);
  24.311 -  adjustindex(*name);
  24.312 -  return TRUE;
  24.313 -}
  24.314 -
  24.315 -SC_FUNC void delete_substtable(void)
  24.316 -{
  24.317 -  int i;
  24.318 -  delete_stringpairtable(&substpair);
  24.319 -  for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
  24.320 -    substindex[i]=NULL;
  24.321 -}
  24.322 -
  24.323 -#endif /* !defined NO_SUBST */
  24.324 -
  24.325 -
  24.326 -/* ----- input file list ----------------------------------------- */
  24.327 -static stringlist sourcefiles = {NULL, NULL};
  24.328 -
  24.329 -SC_FUNC stringlist *insert_sourcefile(char *string)
  24.330 -{
  24.331 -  return insert_string(&sourcefiles,string);
  24.332 -}
  24.333 -
  24.334 -SC_FUNC char *get_sourcefile(int index)
  24.335 -{
  24.336 -  return get_string(&sourcefiles,index);
  24.337 -}
  24.338 -
  24.339 -SC_FUNC void delete_sourcefiletable(void)
  24.340 -{
  24.341 -  delete_stringtable(&sourcefiles);
  24.342 -  assert(sourcefiles.next==NULL);
  24.343 -}
  24.344 -
  24.345 -
  24.346 -/* ----- documentation tags -------------------------------------- */
  24.347 -#if !defined SC_LIGHT
  24.348 -static stringlist docstrings = {NULL, NULL};
  24.349 -
  24.350 -SC_FUNC stringlist *insert_docstring(char *string)
  24.351 -{
  24.352 -  return insert_string(&docstrings,string);
  24.353 -}
  24.354 -
  24.355 -SC_FUNC char *get_docstring(int index)
  24.356 -{
  24.357 -  return get_string(&docstrings,index);
  24.358 -}
  24.359 -
  24.360 -SC_FUNC void delete_docstring(int index)
  24.361 -{
  24.362 -  delete_string(&docstrings,index);
  24.363 -}
  24.364 -
  24.365 -SC_FUNC void delete_docstringtable(void)
  24.366 -{
  24.367 -  delete_stringtable(&docstrings);
  24.368 -  assert(docstrings.next==NULL);
  24.369 -}
  24.370 -#endif /* !defined SC_LIGHT */
  24.371 -
  24.372 -
  24.373 -/* ----- autolisting --------------------------------------------- */
  24.374 -static stringlist autolist = {NULL, NULL};
  24.375 -
  24.376 -SC_FUNC stringlist *insert_autolist(char *string)
  24.377 -{
  24.378 -  return insert_string(&autolist,string);
  24.379 -}
  24.380 -
  24.381 -SC_FUNC char *get_autolist(int index)
  24.382 -{
  24.383 -  return get_string(&autolist,index);
  24.384 -}
  24.385 -
  24.386 -SC_FUNC void delete_autolisttable(void)
  24.387 -{
  24.388 -  delete_stringtable(&autolist);
  24.389 -  assert(autolist.next==NULL);
  24.390 -}
  24.391 -
  24.392 -
  24.393 -/* ----- debug information --------------------------------------- */
  24.394 -
  24.395 -/* These macros are adapted from LibDGG libdgg-int64.h, see
  24.396 - * http://www.dennougedougakkai-ndd.org/pub/libdgg/
  24.397 - */
  24.398 -#if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
  24.399 -  #define __STDC_FORMAT_MACROS
  24.400 -  #define __STDC_CONSTANT_MACROS
  24.401 -  #include <inttypes.h>         /* automatically includes stdint.h */
  24.402 -#elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
  24.403 -  #define PRId64 "I64d"
  24.404 -  #define PRIx64 "I64x"
  24.405 -#else
  24.406 -  #define PRId64 "lld"
  24.407 -  #define PRIx64 "llx"
  24.408 -#endif
  24.409 -#if PAWN_CELL_SIZE==64
  24.410 -  #define PRIdC  PRId64
  24.411 -  #define PRIxC  PRIx64
  24.412 -#elif PAWN_CELL_SIZE==32
  24.413 -  #define PRIdC  "ld"
  24.414 -  #define PRIxC  "lx"
  24.415 -#else
  24.416 -  #define PRIdC  "d"
  24.417 -  #define PRIxC  "x"
  24.418 -#endif
  24.419 -
  24.420 -static stringlist dbgstrings = {NULL, NULL};
  24.421 -
  24.422 -SC_FUNC stringlist *insert_dbgfile(const char *filename)
  24.423 -{
  24.424 -
  24.425 -  if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
  24.426 -    char string[_MAX_PATH+40];
  24.427 -    assert(filename!=NULL);
  24.428 -    assert(strlen(filename)+40<sizeof string);
  24.429 -    sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
  24.430 -    return insert_string(&dbgstrings,string);
  24.431 -  } /* if */
  24.432 -  return NULL;
  24.433 -}
  24.434 -
  24.435 -SC_FUNC stringlist *insert_dbgline(int linenr)
  24.436 -{
  24.437 -  if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
  24.438 -    char string[40];
  24.439 -    if (linenr>0)
  24.440 -      linenr--;         /* line numbers are zero-based in the debug information */
  24.441 -    sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
  24.442 -    return insert_string(&dbgstrings,string);
  24.443 -  } /* if */
  24.444 -  return NULL;
  24.445 -}
  24.446 -
  24.447 -SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
  24.448 -{
  24.449 -  if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
  24.450 -    char string[2*sNAMEMAX+128];
  24.451 -    char symname[2*sNAMEMAX+16];
  24.452 -
  24.453 -    funcdisplayname(symname,sym->name);
  24.454 -    /* address tag:name codestart codeend ident vclass [tag:dim ...] */
  24.455 -    if (sym->ident==iFUNCTN) {
  24.456 -      sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
  24.457 -              sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
  24.458 -    } else {
  24.459 -      sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
  24.460 -              sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
  24.461 -    } /* if */
  24.462 -    if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
  24.463 -      #if !defined NDEBUG
  24.464 -        int count=sym->dim.array.level;
  24.465 -      #endif
  24.466 -      symbol *sub;
  24.467 -      strcat(string," [ ");
  24.468 -      for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
  24.469 -        assert(sub->dim.array.level==count--);
  24.470 -        sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
  24.471 -      } /* for */
  24.472 -      strcat(string,"]");
  24.473 -    } /* if */
  24.474 -
  24.475 -    return insert_string(&dbgstrings,string);
  24.476 -  } /* if */
  24.477 -  return NULL;
  24.478 -}
  24.479 -
  24.480 -SC_FUNC char *get_dbgstring(int index)
  24.481 -{
  24.482 -  return get_string(&dbgstrings,index);
  24.483 -}
  24.484 -
  24.485 -SC_FUNC void delete_dbgstringtable(void)
  24.486 -{
  24.487 -  delete_stringtable(&dbgstrings);
  24.488 -  assert(dbgstrings.next==NULL);
  24.489 -}
    25.1 --- a/compiler-init/scmemfil.c	Sat Jul 15 01:36:48 2006 +0000
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,179 +0,0 @@
    25.4 -/*  Pawn compiler
    25.5 - *
    25.6 - *  Routines to maintain a "text file" in memory.
    25.7 - *
    25.8 - *  Copyright (c) ITB CompuPhase, 2003-2006
    25.9 - *
   25.10 - *  This software is provided 'as-is', without any express or implied warranty.
   25.11 - *  In no event will the authors be held liable for any damages arising from the
   25.12 - *  use of this software.
   25.13 - *
   25.14 - *  Permission is granted to anyone to use this software for any purpose,
   25.15 - *  including commercial applications, and to alter it and redistribute it
   25.16 - *  freely, subject to the following restrictions:
   25.17 - *
   25.18 - *  1. The origin of this software must not be misrepresented; you must not
   25.19 - *     claim that you wrote the original software. If you use this software in
   25.20 - *     a product, an acknowledgment in the product documentation would be
   25.21 - *     appreciated but is not required.
   25.22 - *
   25.23 - *  2. Altered source versions must be plainly marked as such, and must not be
   25.24 - *     misrepresented as being the original software.
   25.25 - *
   25.26 - *  3. This notice may not be removed or altered from any source distribution.
   25.27 - *
   25.28 - *  Version: $Id: scmemfil.c 3579 2006-06-06 13:35:29Z thiadmer $
   25.29 - */
   25.30 -
   25.31 -#include <assert.h>
   25.32 -#include <stdio.h>
   25.33 -#include <stdlib.h>
   25.34 -#include <string.h>
   25.35 -#include "memfile.h"
   25.36 -
   25.37 -#if defined FORTIFY
   25.38 -  #include <alloc/fortify.h>
   25.39 -#endif
   25.40 -
   25.41 -
   25.42 -#define BUFFERSIZE 512u
   25.43 -
   25.44 -/* For every block, except the first:
   25.45 - *   buffer points to a block that is BUFFERSIZE long that holds the data
   25.46 - *   bufpos is the "used size" of the block
   25.47 - * For the first block:
   25.48 - *   buffer points to the "file name"
   25.49 - *   bufpos is the current "file pointer"
   25.50 - */
   25.51 -typedef memfile_t MEMFILE;
   25.52 -#define tMEMFILE  1
   25.53 -
   25.54 -#include "sc.h"
   25.55 -
   25.56 -
   25.57 -MEMFILE *mfcreate(char *filename)
   25.58 -{
   25.59 -  return memfile_creat(filename, 4096);
   25.60 -}
   25.61 -
   25.62 -void mfclose(MEMFILE *mf)
   25.63 -{
   25.64 -  memfile_destroy(mf);
   25.65 -}
   25.66 -
   25.67 -int mfdump(MEMFILE *mf)
   25.68 -{
   25.69 -  FILE *fp;
   25.70 -  int okay;
   25.71 -
   25.72 -  assert(mf!=NULL);
   25.73 -  /* create the file */
   25.74 -  fp=fopen(mf->name, "wb");
   25.75 -  if (fp==NULL)
   25.76 -    return 0;
   25.77 -
   25.78 -  okay=1;
   25.79 -  okay = okay & (fwrite(mf->base, mf->usedoffs, 1, fp)==(size_t)mf->usedoffs);
   25.80 -  
   25.81 -  fclose(fp);
   25.82 -  return okay;
   25.83 -}
   25.84 -
   25.85 -long mflength(MEMFILE *mf)
   25.86 -{
   25.87 -  return mf->usedoffs;
   25.88 -}
   25.89 -
   25.90 -long mfseek(MEMFILE *mf,long offset,int whence)
   25.91 -{
   25.92 -  long length;
   25.93 -
   25.94 -  assert(mf!=NULL);
   25.95 -  if (mf->usedoffs == 0)
   25.96 -    return 0L;          /* early exit: not a single byte in the file */
   25.97 -
   25.98 -  /* find the size of the memory file */
   25.99 -  length=mflength(mf);
  25.100 -
  25.101 -  /* convert the offset to an absolute position */
  25.102 -  switch (whence) {
  25.103 -  case SEEK_SET:
  25.104 -    break;
  25.105 -  case SEEK_CUR:
  25.106 -    offset+=mf->offs;
  25.107 -    break;
  25.108 -  case SEEK_END:
  25.109 -    assert(offset<=0);
  25.110 -    offset+=length;
  25.111 -    break;
  25.112 -  } /* switch */
  25.113 -
  25.114 -  /* clamp to the file length limit */
  25.115 -  if (offset<0)
  25.116 -    offset=0;
  25.117 -  else if (offset>length)
  25.118 -    offset=length;
  25.119 -
  25.120 -  /* set new position and return it */
  25.121 -  memfile_seek(mf, offset);
  25.122 -
  25.123 -  return offset;
  25.124 -}
  25.125 -
  25.126 -unsigned int mfwrite(MEMFILE *mf,unsigned char *buffer,unsigned int size)
  25.127 -{
  25.128 -  return (memfile_write(mf, buffer, size) ? size : 0);
  25.129 -}
  25.130 -
  25.131 -unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size)
  25.132 -{
  25.133 -  return memfile_read(mf, buffer, size);
  25.134 -}
  25.135 -
  25.136 -char *mfgets(MEMFILE *mf,char *string,unsigned int size)
  25.137 -{
  25.138 -  char *ptr;
  25.139 -  unsigned int read;
  25.140 -  long seek;
  25.141 -
  25.142 -  assert(mf!=NULL);
  25.143 -
  25.144 -  read=mfread(mf,(unsigned char *)string,size);
  25.145 -  if (read==0)
  25.146 -    return NULL;
  25.147 -  seek=0L;
  25.148 -
  25.149 -  /* make sure that the string is zero-terminated */
  25.150 -  assert(read<=size);
  25.151 -  if (read<size) {
  25.152 -    string[read]='\0';
  25.153 -  } else {
  25.154 -    string[size-1]='\0';
  25.155 -    seek=-1;            /* undo reading the character that gets overwritten */
  25.156 -  } /* if */
  25.157 -
  25.158 -  /* find the first '\n' */
  25.159 -  ptr=strchr(string,'\n');
  25.160 -  if (ptr!=NULL) {
  25.161 -    *(ptr+1)='\0';
  25.162 -    seek=(long)(ptr-string)+1-(long)read;
  25.163 -  } /* if */
  25.164 -
  25.165 -  /* undo over-read */
  25.166 -  assert(seek<=0);      /* should seek backward only */
  25.167 -  if (seek!=0)
  25.168 -    mfseek(mf,seek,SEEK_CUR);
  25.169 -
  25.170 -  return string;
  25.171 -}
  25.172 -
  25.173 -int mfputs(MEMFILE *mf,char *string)
  25.174 -{
  25.175 -  unsigned int written,length;
  25.176 -
  25.177 -  assert(mf!=NULL);
  25.178 -
  25.179 -  length=strlen(string);
  25.180 -  written=mfwrite(mf,(unsigned char *)string,length);
  25.181 -  return written==length;
  25.182 -}
    26.1 --- a/compiler-init/scstate.c	Sat Jul 15 01:36:48 2006 +0000
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,375 +0,0 @@
    26.4 -/*  Pawn compiler
    26.5 - *
    26.6 - *  Machine and state maintenance.
    26.7 - *
    26.8 - *  Three lists are maintained here:
    26.9 - *  - A list of automatons (state machines): these hold a name, a unique id
   26.10 - *    (in the "index" field) and the memory address of a cell that holds the
   26.11 - *    current state of the automaton (in the "value" field).
   26.12 - *  - A list of states for each automaton: a name, an automaton id (in the
   26.13 - *    "index" field) and a unique id for the state (unique in the automaton;
   26.14 - *    states belonging to different automatons may have the same id).
   26.15 - *  - A list of state combinations. Each function may belong to a set of states.
   26.16 - *    This list assigns a unique id to the combination of the automaton and all
   26.17 - *    states.
   26.18 - *
   26.19 - *  For a function/variable that has states, there is a fourth list, which is
   26.20 - *  attached to the "symbol" structure. This list contains the code label (in
   26.21 - *  the "name" field, only for functions), the id of the state combinations (the
   26.22 - *  state list id; it is stored in the "index" field) and the code address at
   26.23 - *  which the function starts. The latter is currently unused.
   26.24 - *
   26.25 - *  At the start of the compiled code, a set of stub functions is generated.
   26.26 - *  Each stub function looks up the value of the "state selector" value for the
   26.27 - *  automaton, and goes with a "switch" instruction to the start address of the
   26.28 - *  function. This happens in SC4.C.
   26.29 - *
   26.30 - *
   26.31 - *  Copyright (c) ITB CompuPhase, 2005-2006
   26.32 - *
   26.33 - *  This software is provided "as-is", without any express or implied warranty.
   26.34 - *  In no event will the authors be held liable for any damages arising from
   26.35 - *  the use of this software.
   26.36 - *
   26.37 - *  Permission is granted to anyone to use this software for any purpose,
   26.38 - *  including commercial applications, and to alter it and redistribute it
   26.39 - *  freely, subject to the following restrictions:
   26.40 - *
   26.41 - *  1.  The origin of this software must not be misrepresented; you must not
   26.42 - *      claim that you wrote the original software. If you use this software in
   26.43 - *      a product, an acknowledgment in the product documentation would be
   26.44 - *      appreciated but is not required.
   26.45 - *  2.  Altered source versions must be plainly marked as such, and must not be
   26.46 - *      misrepresented as being the original software.
   26.47 - *  3.  This notice may not be removed or altered from any source distribution.
   26.48 - *
   26.49 - *  Version: $Id: scstate.c 3579 2006-06-06 13:35:29Z thiadmer $
   26.50 - */
   26.51 -#include <assert.h>
   26.52 -#include <limits.h>
   26.53 -#include <stdio.h>
   26.54 -#include <stdlib.h>
   26.55 -#include <string.h>
   26.56 -#include "sc.h"
   26.57 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
   26.58 -  #include <sclinux.h>
   26.59 -#endif
   26.60 -
   26.61 -#if defined FORTIFY
   26.62 -  #include <alloc/fortify.h>
   26.63 -#endif
   26.64 -
   26.65 -typedef struct s_statelist {
   26.66 -  struct s_statelist *next;
   26.67 -  int *states;          /* list of states in this combination */
   26.68 -  int numstates;        /* number of items in the above list */
   26.69 -  int fsa;              /* automaton id */
   26.70 -  int listid;           /* unique id for this combination list */
   26.71 -} statelist;
   26.72 -
   26.73 -static statelist statelist_tab = { NULL, NULL, 0, 0, 0};   /* state combinations table */
   26.74 -
   26.75 -
   26.76 -static constvalue *find_automaton(const char *name,int *last)
   26.77 -{
   26.78 -  constvalue *ptr;
   26.79 -
   26.80 -  assert(last!=NULL);
   26.81 -  *last=0;
   26.82 -  ptr=sc_automaton_tab.next;
   26.83 -  while (ptr!=NULL) {
   26.84 -    if (strcmp(name,ptr->name)==0)
   26.85 -      return ptr;
   26.86 -    if (ptr->index>*last)
   26.87 -      *last=ptr->index;
   26.88 -    ptr=ptr->next;
   26.89 -  } /* while */
   26.90 -  return NULL;
   26.91 -}
   26.92 -
   26.93 -SC_FUNC constvalue *automaton_add(const char *name)
   26.94 -{
   26.95 -  constvalue *ptr;
   26.96 -  int last;
   26.97 -
   26.98 -  assert(strlen(name)<sizeof(ptr->name));
   26.99 -  ptr=find_automaton(name,&last);
  26.100 -  if (ptr==NULL) {
  26.101 -    assert(last+1 <= SHRT_MAX);
  26.102 -    ptr=append_constval(&sc_automaton_tab,name,(cell)0,(short)(last+1));
  26.103 -  } /* if */
  26.104 -  return ptr;
  26.105 -}
  26.106 -
  26.107 -SC_FUNC constvalue *automaton_find(const char *name)
  26.108 -{
  26.109 -  int last;
  26.110 -  return find_automaton(name,&last);
  26.111 -}
  26.112 -
  26.113 -SC_FUNC constvalue *automaton_findid(int id)
  26.114 -{
  26.115 -  constvalue *ptr;
  26.116 -  for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next)
  26.117 -    /* nothing */;
  26.118 -  return ptr;
  26.119 -}
  26.120 -
  26.121 -
  26.122 -static constvalue *find_state(const char *name,int fsa,int *last)
  26.123 -{
  26.124 -  constvalue *ptr;
  26.125 -
  26.126 -  assert(last!=NULL);
  26.127 -  *last=0;
  26.128 -  ptr=sc_state_tab.next;
  26.129 -  while (ptr!=NULL) {
  26.130 -    if (ptr->index==fsa) {
  26.131 -      if (strcmp(name,ptr->name)==0)
  26.132 -        return ptr;
  26.133 -      if ((int)ptr->value>*last)
  26.134 -        *last=(int)ptr->value;
  26.135 -    } /* if */
  26.136 -    ptr=ptr->next;
  26.137 -  } /* while */
  26.138 -  return NULL;
  26.139 -}
  26.140 -
  26.141 -SC_FUNC constvalue *state_add(const char *name,int fsa)
  26.142 -{
  26.143 -  constvalue *ptr;
  26.144 -  int last;
  26.145 -
  26.146 -  assert(strlen(name)<sizeof(ptr->name));
  26.147 -  ptr=find_state(name,fsa,&last);
  26.148 -  if (ptr==NULL) {
  26.149 -    assert(fsa <= SHRT_MAX);
  26.150 -    ptr=append_constval(&sc_state_tab,name,(cell)(last+1),(short)fsa);
  26.151 -  } /* if */
  26.152 -  return ptr;
  26.153 -}
  26.154 -
  26.155 -SC_FUNC constvalue *state_find(const char *name,int fsa_id)
  26.156 -{
  26.157 -  int last;     /* dummy */
  26.158 -  return find_state(name,fsa_id,&last);
  26.159 -}
  26.160 -
  26.161 -SC_FUNC constvalue *state_findid(int id)
  26.162 -{
  26.163 -  constvalue *ptr;
  26.164 -  for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next)
  26.165 -    /* nothing */;
  26.166 -  return ptr;
  26.167 -}
  26.168 -
  26.169 -SC_FUNC void state_buildlist(int **list,int *listsize,int *count,int stateid)
  26.170 -{
  26.171 -  int idx;
  26.172 -
  26.173 -  assert(list!=NULL);
  26.174 -  assert(listsize!=NULL);
  26.175 -  assert(*listsize>=0);
  26.176 -  assert(count!=NULL);
  26.177 -  assert(*count>=0);
  26.178 -  assert(*count<=*listsize);
  26.179 -
  26.180 -  if (*count==*listsize) {
  26.181 -    /* To avoid constantly calling malloc(), the list is grown by 4 states at
  26.182 -     * a time.
  26.183 -     */
  26.184 -    *listsize+=4;
  26.185 -    *list=(int*)realloc(*list,*listsize*sizeof(int));
  26.186 -    if (*list==NULL)
  26.187 -      error(103);               /* insufficient memory */
  26.188 -  } /* if */
  26.189 -
  26.190 -  /* find the insertion point (the list has to stay sorted) */
  26.191 -  for (idx=0; idx<*count && *list[idx]<stateid; idx++)
  26.192 -    /* nothing */;
  26.193 -  if (idx<*count)
  26.194 -    memmove(&(*list)[idx+1],&(*list)[idx],(int)((*count-idx+1)*sizeof(int)));
  26.195 -  (*list)[idx]=stateid;
  26.196 -  *count+=1;
  26.197 -}
  26.198 -
  26.199 -static statelist *state_findlist(int *list,int count,int fsa,int *last)
  26.200 -{
  26.201 -  statelist *ptr;
  26.202 -  int i;
  26.203 -
  26.204 -  assert(count>0);
  26.205 -  assert(last!=NULL);
  26.206 -  *last=0;
  26.207 -  ptr=statelist_tab.next;
  26.208 -  while (ptr!=NULL) {
  26.209 -    if (ptr->listid>*last)
  26.210 -      *last=ptr->listid;
  26.211 -    if (ptr->fsa==fsa && ptr->numstates==count) {
  26.212 -      /* compare all states */
  26.213 -      for (i=0; i<count && ptr->states[i]==list[i]; i++)
  26.214 -        /* nothing */;
  26.215 -      if (i==count)
  26.216 -        return ptr;
  26.217 -    } /* if */
  26.218 -    ptr=ptr->next;
  26.219 -  } /* while */
  26.220 -  return NULL;
  26.221 -}
  26.222 -
  26.223 -static statelist *state_getlist_ptr(int listid)
  26.224 -{
  26.225 -  statelist *ptr;
  26.226 -
  26.227 -  assert(listid>0);
  26.228 -  for (ptr=statelist_tab.next; ptr!=NULL && ptr->listid!=listid; ptr=ptr->next)
  26.229 -    /* nothing */;
  26.230 -  return ptr;
  26.231 -}
  26.232 -
  26.233 -SC_FUNC int state_addlist(int *list,int count,int fsa)
  26.234 -{
  26.235 -  statelist *ptr;
  26.236 -  int last;
  26.237 -
  26.238 -  assert(list!=NULL);
  26.239 -  assert(count>0);
  26.240 -  ptr=state_findlist(list,count,fsa,&last);
  26.241 -  if (ptr==NULL) {
  26.242 -    if ((ptr=(statelist*)malloc(sizeof(statelist)))==NULL)
  26.243 -      error(103);       /* insufficient memory */
  26.244 -    if ((ptr->states=(int*)malloc(count*sizeof(int)))==NULL) {
  26.245 -      free(ptr);
  26.246 -      error(103);       /* insufficient memory */
  26.247 -    } /* if */
  26.248 -    memcpy(ptr->states,list,count*sizeof(int));
  26.249 -    ptr->numstates=count;
  26.250 -    ptr->fsa=fsa;
  26.251 -    ptr->listid=last+1;
  26.252 -    ptr->next=statelist_tab.next;
  26.253 -    statelist_tab.next=ptr;
  26.254 -  } /* if */
  26.255 -  assert(ptr!=NULL);
  26.256 -  return ptr->listid;
  26.257 -}
  26.258 -
  26.259 -SC_FUNC void state_deletetable(void)
  26.260 -{
  26.261 -  statelist *ptr;
  26.262 -
  26.263 -  while (statelist_tab.next!=NULL) {
  26.264 -    ptr=statelist_tab.next;
  26.265 -    /* unlink first */
  26.266 -    statelist_tab.next=ptr->next;
  26.267 -    /* then delete */
  26.268 -    assert(ptr->states!=NULL);
  26.269 -    free(ptr->states);
  26.270 -    free(ptr);
  26.271 -  } /* while */
  26.272 -}
  26.273 -
  26.274 -SC_FUNC int state_getfsa(int listid)
  26.275 -{
  26.276 -  statelist *ptr;
  26.277 -
  26.278 -  assert(listid>=0);
  26.279 -  if (listid==0)
  26.280 -    return -1;
  26.281 -
  26.282 -  ptr=state_getlist_ptr(listid);
  26.283 -  return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */
  26.284 -}
  26.285 -
  26.286 -SC_FUNC int state_count(int listid)
  26.287 -{
  26.288 -  statelist *ptr=state_getlist_ptr(listid);
  26.289 -  if (ptr==NULL)
  26.290 -    return 0;           /* unknown list, no states in it */
  26.291 -  return ptr->numstates;
  26.292 -}
  26.293 -
  26.294 -SC_FUNC int state_inlist(int listid,int state)
  26.295 -{
  26.296 -  statelist *ptr;
  26.297 -  int i;
  26.298 -
  26.299 -  ptr=state_getlist_ptr(listid);
  26.300 -  if (ptr==NULL)
  26.301 -    return FALSE;       /* unknown list, state not in it */
  26.302 -  for (i=0; i<ptr->numstates; i++)
  26.303 -    if (ptr->states[i]==state)
  26.304 -      return TRUE;
  26.305 -  return FALSE;
  26.306 -}
  26.307 -
  26.308 -SC_FUNC int state_listitem(int listid,int index)
  26.309 -{
  26.310 -  statelist *ptr;
  26.311 -
  26.312 -  ptr=state_getlist_ptr(listid);
  26.313 -  assert(ptr!=NULL);
  26.314 -  assert(index>=0 && index<ptr->numstates);
  26.315 -  return ptr->states[index];
  26.316 -}
  26.317 -
  26.318 -static int checkconflict(statelist *psrc,statelist *ptgt)
  26.319 -{
  26.320 -  int s,t;
  26.321 -
  26.322 -  assert(psrc!=NULL);
  26.323 -  assert(ptgt!=NULL);
  26.324 -  for (s=0; s<psrc->numstates; s++)
  26.325 -    for (t=0; t<ptgt->numstates; t++)
  26.326 -      if (psrc->states[s]==ptgt->states[t])
  26.327 -        return 1;       /* state conflict */
  26.328 -  return 0;
  26.329 -}
  26.330 -
  26.331 -/* This function searches whether one of the states in the list of statelist id's
  26.332 - * of a symbol exists in any other statelist id's of the same function; it also
  26.333 - * verifies that all definitions of the symbol are in the same automaton.
  26.334 - */
  26.335 -SC_FUNC void state_conflict(symbol *root)
  26.336 -{
  26.337 -  statelist *psrc,*ptgt;
  26.338 -  constvalue *srcptr,*tgtptr;
  26.339 -  symbol *sym;
  26.340 -
  26.341 -  assert(root!=NULL);
  26.342 -  for (sym=root->next; sym!=NULL; sym=sym->next) {
  26.343 -    if (sym->parent!=NULL || sym->ident!=iFUNCTN)
  26.344 -      continue;                 /* hierarchical data type or no function */
  26.345 -    if (sym->states==NULL)
  26.346 -      continue;                 /* this function has no states */
  26.347 -    for (srcptr=sym->states->next; srcptr!=NULL; srcptr=srcptr->next) {
  26.348 -      if (srcptr->index==-1)
  26.349 -        continue;               /* state list id -1 is a special case */
  26.350 -      psrc=state_getlist_ptr(srcptr->index);
  26.351 -      assert(psrc!=NULL);
  26.352 -      for (tgtptr=srcptr->next; tgtptr!=NULL; tgtptr=tgtptr->next) {
  26.353 -        if (tgtptr->index==-1)
  26.354 -          continue;             /* state list id -1 is a special case */
  26.355 -        ptgt=state_getlist_ptr(tgtptr->index);
  26.356 -        assert(ptgt!=NULL);
  26.357 -        if (psrc->fsa!=ptgt->fsa && strcmp(sym->name,uENTRYFUNC)!=0)
  26.358 -          error(83,sym->name);  /* this function is part of another machine */
  26.359 -        if (checkconflict(psrc,ptgt))
  26.360 -          error(84,sym->name);  /* state conflict */
  26.361 -      } /* for (tgtptr) */
  26.362 -    } /* for (srcptr) */
  26.363 -  } /* for (sym) */
  26.364 -}
  26.365 -
  26.366 -/* check whether the two state lists (whose ids are passed in) share any
  26.367 - * states
  26.368 - */
  26.369 -SC_FUNC int state_conflict_id(int listid1,int listid2)
  26.370 -{
  26.371 -  statelist *psrc,*ptgt;
  26.372 -
  26.373 -  psrc=state_getlist_ptr(listid1);
  26.374 -  assert(psrc!=NULL);
  26.375 -  ptgt=state_getlist_ptr(listid2);
  26.376 -  assert(ptgt!=NULL);
  26.377 -  return checkconflict(psrc,ptgt);
  26.378 -}
    27.1 --- a/compiler-init/scvars.c	Sat Jul 15 01:36:48 2006 +0000
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,113 +0,0 @@
    27.4 -/*  Pawn compiler
    27.5 - *
    27.6 - *  Global (cross-module) variables.
    27.7 - *
    27.8 - *  Copyright (c) ITB CompuPhase, 1997-2006
    27.9 - *
   27.10 - *  This software is provided "as-is", without any express or implied warranty.
   27.11 - *  In no event will the authors be held liable for any damages arising from
   27.12 - *  the use of this software.
   27.13 - *
   27.14 - *  Permission is granted to anyone to use this software for any purpose,
   27.15 - *  including commercial applications, and to alter it and redistribute it
   27.16 - *  freely, subject to the following restrictions:
   27.17 - *
   27.18 - *  1.  The origin of this software must not be misrepresented; you must not
   27.19 - *      claim that you wrote the original software. If you use this software in
   27.20 - *      a product, an acknowledgment in the product documentation would be
   27.21 - *      appreciated but is not required.
   27.22 - *  2.  Altered source versions must be plainly marked as such, and must not be
   27.23 - *      misrepresented as being the original software.
   27.24 - *  3.  This notice may not be removed or altered from any source distribution.
   27.25 - *
   27.26 - *  Version: $Id: scvars.c 3577 2006-06-02 16:22:52Z thiadmer $
   27.27 - */
   27.28 -#include <stdio.h>
   27.29 -#include <stdlib.h>     /* for _MAX_PATH */
   27.30 -#include "sc.h"
   27.31 -
   27.32 -/*  global variables
   27.33 - *
   27.34 - *  All global variables that are shared amongst the compiler files are
   27.35 - *  declared here.
   27.36 - */
   27.37 -SC_VDEFINE symbol loctab;                   /* local symbol table */
   27.38 -SC_VDEFINE symbol glbtab;                   /* global symbol table */
   27.39 -SC_VDEFINE cell *litq;                      /* the literal queue */
   27.40 -SC_VDEFINE unsigned char pline[sLINEMAX+1]; /* the line read from the input file */
   27.41 -SC_VDEFINE const unsigned char *lptr;       /* points to the current position in "pline" */
   27.42 -SC_VDEFINE constvalue tagname_tab = { NULL, "", 0, 0};  /* tagname table */
   27.43 -SC_VDEFINE constvalue libname_tab = { NULL, "", 0, 0};  /* library table (#pragma library "..." syntax) */
   27.44 -SC_VDEFINE constvalue *curlibrary = NULL;   /* current library */
   27.45 -SC_VDEFINE int pc_addlibtable = TRUE;       /* is the library table added to the AMX file? */
   27.46 -SC_VDEFINE symbol *curfunc;                 /* pointer to current function */
   27.47 -SC_VDEFINE char *inpfname;                  /* pointer to name of the file currently read from */
   27.48 -SC_VDEFINE char outfname[_MAX_PATH];        /* intermediate (assembler) file name */
   27.49 -SC_VDEFINE char binfname[_MAX_PATH];        /* binary file name */
   27.50 -SC_VDEFINE char errfname[_MAX_PATH];        /* error file name */
   27.51 -SC_VDEFINE char sc_ctrlchar = CTRL_CHAR;    /* the control character (or escape character)*/
   27.52 -SC_VDEFINE char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */
   27.53 -SC_VDEFINE int litidx    = 0;               /* index to literal table */
   27.54 -SC_VDEFINE int litmax    = sDEF_LITMAX;     /* current size of the literal table */
   27.55 -SC_VDEFINE int stgidx    = 0;      /* index to the staging buffer */
   27.56 -SC_VDEFINE int sc_labnum = 0;      /* number of (internal) labels */
   27.57 -SC_VDEFINE int staging   = 0;      /* true if staging output */
   27.58 -SC_VDEFINE cell declared = 0;      /* number of local cells declared */
   27.59 -SC_VDEFINE cell glb_declared=0;    /* number of global cells declared */
   27.60 -SC_VDEFINE cell code_idx = 0;      /* number of bytes with generated code */
   27.61 -SC_VDEFINE int ntv_funcid= 0;      /* incremental number of native function */
   27.62 -SC_VDEFINE int errnum    = 0;      /* number of errors */
   27.63 -SC_VDEFINE int warnnum   = 0;      /* number of warnings */
   27.64 -SC_VDEFINE int sc_debug  = sCHKBOUNDS; /* by default: bounds checking+assertions */
   27.65 -SC_VDEFINE int sc_packstr= FALSE;  /* strings are packed by default? */
   27.66 -SC_VDEFINE int sc_asmfile= FALSE;  /* create .ASM file? */
   27.67 -SC_VDEFINE int sc_listing= FALSE;  /* create .LST file? */
   27.68 -SC_VDEFINE int sc_compress=TRUE;   /* compress bytecode? */
   27.69 -SC_VDEFINE int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
   27.70 -SC_VDEFINE int sc_dataalign=sizeof(cell);/* data alignment value */
   27.71 -SC_VDEFINE int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
   27.72 -SC_VDEFINE int pc_docexpr=FALSE;   /* must expression be attached to documentation comment? */
   27.73 -SC_VDEFINE int curseg    = 0;      /* 1 if currently parsing CODE, 2 if parsing DATA */
   27.74 -SC_VDEFINE cell pc_stksize=sDEF_AMXSTACK;/* default stack size */
   27.75 -SC_VDEFINE cell pc_amxlimit=0;     /* default abstract machine size limit = none */
   27.76 -SC_VDEFINE cell pc_amxram=0;       /* default abstract machine data size limit = none */
   27.77 -SC_VDEFINE int freading  = FALSE;  /* Is there an input file ready for reading? */
   27.78 -SC_VDEFINE int fline     = 0;      /* the line number in the current file */
   27.79 -SC_VDEFINE short fnumber = 0;      /* the file number in the file table (debugging) */
   27.80 -SC_VDEFINE short fcurrent= 0;      /* current file being processed (debugging) */
   27.81 -SC_VDEFINE short sc_intest=FALSE;  /* true if inside a test */
   27.82 -SC_VDEFINE int sideeffect= 0;      /* true if an expression causes a side-effect */
   27.83 -SC_VDEFINE int stmtindent= 0;      /* current indent of the statement */
   27.84 -SC_VDEFINE int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
   27.85 -SC_VDEFINE int sc_tabsize=8;       /* number of spaces that a TAB represents */
   27.86 -SC_VDEFINE short sc_allowtags=TRUE;  /* allow/detect tagnames in lex() */
   27.87 -SC_VDEFINE int sc_status;          /* read/write status */
   27.88 -SC_VDEFINE int sc_rationaltag=0;   /* tag for rational numbers */
   27.89 -SC_VDEFINE int rational_digits=0;  /* number of fractional digits */
   27.90 -SC_VDEFINE int sc_allowproccall=0; /* allow/detect tagnames in lex() */
   27.91 -SC_VDEFINE short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
   27.92 -SC_VDEFINE char *pc_depricate=NULL;/* if non-null, mark next declaration as depricated */
   27.93 -SC_VDEFINE int sc_curstates=0;     /* ID of the current state list */
   27.94 -SC_VDEFINE int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
   27.95 -SC_VDEFINE int pc_memflags=0;      /* special flags for the stack/heap usage */
   27.96 -
   27.97 -SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
   27.98 -SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0};   /* state table */
   27.99 -
  27.100 -SC_VDEFINE FILE *inpf    = NULL;   /* file read from (source or include) */
  27.101 -SC_VDEFINE FILE *inpf_org= NULL;   /* main source file */
  27.102 -SC_VDEFINE FILE *outf    = NULL;   /* (intermediate) text file written to */
  27.103 -
  27.104 -SC_VDEFINE jmp_buf errbuf;
  27.105 -
  27.106 -#if !defined SC_LIGHT
  27.107 -  SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */
  27.108 -#endif
  27.109 -
  27.110 -#if defined __WATCOMC__ && !defined NDEBUG
  27.111 -  /* Watcom's CVPACK dislikes .OBJ files without functions */
  27.112 -  static int dummyfunc(void)
  27.113 -  {
  27.114 -    return 0;
  27.115 -  }
  27.116 -#endif
    28.1 --- a/compiler-init/spcomp.sln	Sat Jul 15 01:36:48 2006 +0000
    28.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3 @@ -1,21 +0,0 @@
    28.4 -Microsoft Visual Studio Solution File, Format Version 8.00
    28.5 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spcomp", "spcomp.vcproj", "{B4C844FF-008D-4BD5-B82F-DC06E706C64B}"
    28.6 -	ProjectSection(ProjectDependencies) = postProject
    28.7 -	EndProjectSection
    28.8 -EndProject
    28.9 -Global
   28.10 -	GlobalSection(SolutionConfiguration) = preSolution
   28.11 -		Debug = Debug
   28.12 -		Release = Release
   28.13 -	EndGlobalSection
   28.14 -	GlobalSection(ProjectConfiguration) = postSolution
   28.15 -		{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Debug.ActiveCfg = Debug|Win32
   28.16 -		{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Debug.Build.0 = Debug|Win32
   28.17 -		{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Release.ActiveCfg = Release|Win32
   28.18 -		{B4C844FF-008D-4BD5-B82F-DC06E706C64B}.Release.Build.0 = Release|Win32
   28.19 -	EndGlobalSection
   28.20 -	GlobalSection(ExtensibilityGlobals) = postSolution
   28.21 -	EndGlobalSection
   28.22 -	GlobalSection(ExtensibilityAddIns) = postSolution
   28.23 -	EndGlobalSection
   28.24 -EndGlobal
    29.1 --- a/compiler-init/spcomp.vcproj	Sat Jul 15 01:36:48 2006 +0000
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,305 +0,0 @@
    29.4 -<?xml version="1.0" encoding="Windows-1252"?>
    29.5 -<VisualStudioProject
    29.6 -	ProjectType="Visual C++"
    29.7 -	Version="7.10"
    29.8 -	Name="spcomp"
    29.9 -	ProjectGUID="{B4C844FF-008D-4BD5-B82F-DC06E706C64B}"
   29.10 -	RootNamespace="spcomp"
   29.11 -	Keyword="Win32Proj"
   29.12 -	>
   29.13 -	<Platforms>
   29.14 -		<Platform
   29.15 -			Name="Win32"
   29.16 -		/>
   29.17 -	</Platforms>
   29.18 -	<ToolFiles>
   29.19 -	</ToolFiles>
   29.20 -	<Configurations>
   29.21 -		<Configuration
   29.22 -			Name="Debug|Win32"
   29.23 -			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
   29.24 -			IntermediateDirectory="$(ConfigurationName)"
   29.25 -			ConfigurationType="1"
   29.26 -			CharacterSet="1"
   29.27 -			>
   29.28 -			<Tool
   29.29 -				Name="VCPreBuildEventTool"
   29.30 -			/>
   29.31 -			<Tool
   29.32 -				Name="VCCustomBuildTool"
   29.33 -			/>
   29.34 -			<Tool
   29.35 -				Name="VCXMLDataGeneratorTool"
   29.36 -			/>
   29.37 -			<Tool
   29.38 -				Name="VCWebServiceProxyGeneratorTool"
   29.39 -			/>
   29.40 -			<Tool
   29.41 -				Name="VCMIDLTool"
   29.42 -			/>
   29.43 -			<Tool
   29.44 -				Name="VCCLCompilerTool"
   29.45 -				Optimization="0"
   29.46 -				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
   29.47 -				MinimalRebuild="true"
   29.48 -				BasicRuntimeChecks="3"
   29.49 -				RuntimeLibrary="3"
   29.50 -				UsePrecompiledHeader="0"
   29.51 -				WarningLevel="3"
   29.52 -				Detect64BitPortabilityProblems="false"
   29.53 -				DebugInformationFormat="4"
   29.54 -			/>
   29.55 -			<Tool
   29.56 -				Name="VCManagedResourceCompilerTool"
   29.57 -			/>
   29.58 -			<Tool
   29.59 -				Name="VCResourceCompilerTool"
   29.60 -			/>
   29.61 -			<Tool
   29.62 -				Name="VCPreLinkEventTool"
   29.63 -			/>
   29.64 -			<Tool
   29.65 -				Name="VCLinkerTool"
   29.66 -				LinkIncremental="2"
   29.67 -				GenerateDebugInformation="true"
   29.68 -				SubSystem="1"
   29.69 -				TargetMachine="1"
   29.70 -			/>
   29.71 -			<Tool
   29.72 -				Name="VCALinkTool"
   29.73 -			/>
   29.74 -			<Tool
   29.75 -				Name="VCManifestTool"
   29.76 -			/>
   29.77 -			<Tool
   29.78 -				Name="VCXDCMakeTool"
   29.79 -			/>
   29.80 -			<Tool
   29.81 -				Name="VCBscMakeTool"
   29.82 -			/>
   29.83 -			<Tool
   29.84 -				Name="VCFxCopTool"
   29.85 -			/>
   29.86 -			<Tool
   29.87 -				Name="VCAppVerifierTool"
   29.88 -			/>
   29.89 -			<Tool
   29.90 -				Name="VCWebDeploymentTool"
   29.91 -			/>
   29.92 -			<Tool
   29.93 -				Name="VCPostBuildEventTool"
   29.94 -			/>
   29.95 -		</Configuration>
   29.96 -		<Configuration
   29.97 -			Name="Release|Win32"
   29.98 -			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
   29.99 -			IntermediateDirectory="$(ConfigurationName)"
  29.100 -			ConfigurationType="1"
  29.101 -			CharacterSet="1"
  29.102 -			WholeProgramOptimization="1"
  29.103 -			>
  29.104 -			<Tool
  29.105 -				Name="VCPreBuildEventTool"
  29.106 -			/>
  29.107 -			<Tool
  29.108 -				Name="VCCustomBuildTool"
  29.109 -			/>
  29.110 -			<Tool
  29.111 -				Name="VCXMLDataGeneratorTool"
  29.112 -			/>
  29.113 -			<Tool
  29.114 -				Name="VCWebServiceProxyGeneratorTool"
  29.115 -			/>
  29.116 -			<Tool
  29.117 -				Name="VCMIDLTool"
  29.118 -			/>
  29.119 -			<Tool
  29.120 -				Name="VCCLCompilerTool"
  29.121 -				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
  29.122 -				RuntimeLibrary="2"
  29.123 -				UsePrecompiledHeader="0"
  29.124 -				WarningLevel="3"
  29.125 -				Detect64BitPortabilityProblems="false"
  29.126 -				DebugInformationFormat="3"
  29.127 -			/>
  29.128 -			<Tool
  29.129 -				Name="VCManagedResourceCompilerTool"
  29.130 -			/>
  29.131 -			<Tool
  29.132 -				Name="VCResourceCompilerTool"
  29.133 -			/>
  29.134 -			<Tool
  29.135 -				Name="VCPreLinkEventTool"
  29.136 -			/>
  29.137 -			<Tool
  29.138 -				Name="VCLinkerTool"
  29.139 -				LinkIncremental="1"
  29.140 -				GenerateDebugInformation="true"
  29.141 -				SubSystem="1"
  29.142 -				OptimizeReferences="2"
  29.143 -				EnableCOMDATFolding="2"
  29.144 -				TargetMachine="1"
  29.145 -			/>
  29.146 -			<Tool
  29.147 -				Name="VCALinkTool"
  29.148 -			/>
  29.149 -			<Tool
  29.150 -				Name="VCManifestTool"
  29.151 -			/>
  29.152 -			<Tool
  29.153 -				Name="VCXDCMakeTool"
  29.154 -			/>
  29.155 -			<Tool
  29.156 -				Name="VCBscMakeTool"
  29.157 -			/>
  29.158 -			<Tool
  29.159 -				Name="VCFxCopTool"
  29.160 -			/>
  29.161 -			<Tool
  29.162 -				Name="VCAppVerifierTool"
  29.163 -			/>
  29.164 -			<Tool
  29.165 -				Name="VCWebDeploymentTool"
  29.166 -			/>
  29.167 -			<Tool
  29.168 -				Name="VCPostBuildEventTool"
  29.169 -			/>
  29.170 -		</Configuration>
  29.171 -	</Configurations>
  29.172 -	<References>
  29.173 -	</References>
  29.174 -	<Files>
  29.175 -		<Filter
  29.176 -			Name="Source Files"
  29.177 -			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
  29.178 -			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
  29.179 -			>
  29.180 -			<File
  29.181 -				RelativePath=".\libpawnc.c"
  29.182 -				>
  29.183 -			</File>
  29.184 -			<File
  29.185 -				RelativePath=".\lstring.c"
  29.186 -				>
  29.187 -			</File>
  29.188 -			<File
  29.189 -				RelativePath=".\memfile.c"
  29.190 -				>
  29.191 -			</File>
  29.192 -			<File
  29.193 -				RelativePath=".\pawncc.c"
  29.194 -				>
  29.195 -			</File>
  29.196 -			<File
  29.197 -				RelativePath=".\sc1.c"
  29.198 -				>
  29.199 -			</File>
  29.200 -			<File
  29.201 -				RelativePath=".\sc2.c"
  29.202 -				>
  29.203 -			</File>
  29.204 -			<File
  29.205 -				RelativePath=".\sc3.c"
  29.206 -				>
  29.207 -			</File>
  29.208 -			<File
  29.209 -				RelativePath=".\sc4.c"
  29.210 -				>
  29.211 -			</File>
  29.212 -			<File
  29.213 -				RelativePath=".\sc5.c"
  29.214 -				>
  29.215 -			</File>
  29.216 -			<File
  29.217 -				RelativePath=".\sc6.c"
  29.218 -				>
  29.219 -			</File>
  29.220 -			<File
  29.221 -				RelativePath=".\sc7.c"
  29.222 -				>
  29.223 -			</File>
  29.224 -			<File
  29.225 -				RelativePath=".\scexpand.c"
  29.226 -				>
  29.227 -			</File>
  29.228 -			<File
  29.229 -				RelativePath=".\sci18n.c"
  29.230 -				>
  29.231 -			</File>
  29.232 -			<File
  29.233 -				RelativePath=".\sclist.c"
  29.234 -				>
  29.235 -			</File>
  29.236 -			<File
  29.237 -				RelativePath=".\scmemfil.c"
  29.238 -				>
  29.239 -				<FileConfiguration
  29.240 -					Name="Debug|Win32"
  29.241 -					>
  29.242 -					<Tool
  29.243 -						Name="VCCLCompilerTool"
  29.244 -						Detect64BitPortabilityProblems="false"
  29.245 -					/>
  29.246 -				</FileConfiguration>
  29.247 -			</File>
  29.248 -			<File
  29.249 -				RelativePath=".\scstate.c"
  29.250 -				>
  29.251 -			</File>
  29.252 -			<File
  29.253 -				RelativePath=".\scvars.c"
  29.254 -				>
  29.255 -			</File>
  29.256 -		</Filter>
  29.257 -		<Filter
  29.258 -			Name="Header Files"
  29.259 -			Filter="h;hpp;hxx;hm;inl;inc;xsd"
  29.260 -			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
  29.261 -			>
  29.262 -			<File
  29.263 -				RelativePath=".\amx.h"
  29.264 -				>
  29.265 -			</File>
  29.266 -			<File
  29.267 -				RelativePath=".\lstring.h"
  29.268 -				>
  29.269 -			</File>
  29.270 -			<File
  29.271 -				RelativePath=".\memfile.h"
  29.272 -				>
  29.273 -			</File>
  29.274 -			<File
  29.275 -				RelativePath=".\osdefs.h"
  29.276 -				>
  29.277 -			</File>
  29.278 -			<File
  29.279 -				RelativePath=".\sc.h"
  29.280 -				>
  29.281 -			</File>
  29.282 -			<File
  29.283 -				RelativePath=".\svnrev.h"
  29.284 -				>
  29.285 -			</File>
  29.286 -		</Filter>
  29.287 -		<Filter
  29.288 -			Name="Resource Files"
  29.289 -			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
  29.290 -			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
  29.291 -			>
  29.292 -			<File
  29.293 -				RelativePath=".\libpawnc.rc"
  29.294 -				>
  29.295 -			</File>
  29.296 -			<File
  29.297 -				RelativePath=".\sc5.scp"
  29.298 -				>
  29.299 -			</File>
  29.300 -			<File
  29.301 -				RelativePath=".\sc7.scp"
  29.302 -				>
  29.303 -			</File>
  29.304 -		</Filter>
  29.305 -	</Files>
  29.306 -	<Globals>
  29.307 -	</Globals>
  29.308 -</VisualStudioProject>
    30.1 --- a/compiler-init/svnrev.h	Sat Jul 15 01:36:48 2006 +0000
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,9 +0,0 @@
    30.4 -#define SMC_VERSION		1
    30.5 -#define SMC_REVISION	0
    30.6 -#define SMC_BUILD		1
    30.7 -#define SMC_VERSTRING	"1.0.1.3599"
    30.8 -
    30.9 -#define SVN_REV		3599
   30.10 -#define SVN_REVSTR	"3599"
   30.11 -#define SVN_REVDATE	"2006-07-05"
   30.12 -#define SVN_REVSTAMP	20060705L