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 < 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,"<");
13.3828 - ptr+=4;
13.3829 - break;
13.3830 - case '>':
13.3831 - strcpy(ptr,">");
13.3832 - ptr+=4;
13.3833 - break;
13.3834 - case '&':
13.3835 - strcpy(ptr,"&");
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,"&%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," &");
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,¶ms);
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,¶ms);
19.301 - ucell p2=getparam(params,¶ms);
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,¶ms);
19.315 - ucell p2=getparam(params,¶ms);
19.316 - ucell p3=getparam(params,¶ms);
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,¶ms);
19.331 - ucell p2=getparam(params,¶ms);
19.332 - ucell p3=getparam(params,¶ms);
19.333 - ucell p4=getparam(params,¶ms);
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,¶ms);
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,¶ms);
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