sourcemod/sourcepawn/compiler/sc.h
David Anderson c4056aea5d Rewrite the assembly pipeline.
This patch uses SmxBuilder from spcomp2 to replace the old assemble()
pipeline. Instead of generating into an old AMX structure, and then
decoding that into SMX, we now directly generate into SMX. This greatly
simplifies code generation and smx building.
2014-08-23 13:25:58 -07:00

942 lines
37 KiB
C

// vim: set sts=2 ts=8 sw=2 tw=99 et:
/* Pawn compiler
*
* Drafted after the Small-C compiler Version 2.01, originally created
* by Ron Cain, july 1980, and enhanced by James E. Hendrix.
*
* This version comes close to a complete rewrite.
*
* Copyright R. Cain, 1980
* Copyright J.E. Hendrix, 1982, 1983
* Copyright ITB CompuPhase, 1997-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#ifndef SC_H_INCLUDED
#define SC_H_INCLUDED
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#if defined __BORLANDC__ && defined _Windows && !(defined __32BIT__ || defined __WIN32__)
/* setjmp() and longjmp() not well supported in 16-bit windows */
#include <windows.h>
typedef int jmp_buf[9];
#define setjmp(b) Catch(b)
#define longjmp(b,e) Throw(b,e)
#else
#include <setjmp.h>
#endif
#include "osdefs.h"
#include "amx.h"
/* Note: the "cell" and "ucell" types are defined in AMX.H */
#define PUBLIC_CHAR '@' /* character that defines a function "public" */
#define CTRL_CHAR '\\' /* default control character */
#define sCHARBITS 8 /* size of a packed character */
#define MAXTAGS 16
#define sDIMEN_MAX 4 /* maximum number of array dimensions */
#define sLINEMAX 4095 /* input line length (in characters) */
#define sCOMP_STACK 32 /* maximum nesting of #if .. #endif sections */
#define sDEF_LITMAX 500 /* initial size of the literal pool, in "cells" */
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
#define sDEF_PREFIX "sourcemod.inc" /* default prefix filename */
#define sARGS_MAX 32 /* number of arguments a function can have, max */
#define sTAGS_MAX 16 /* maximum number of tags on an argument */
typedef union {
void *pv; /* e.g. a name */
int i;
} stkitem; /* type of items stored on the compiler stack */
typedef struct s_arginfo { /* function argument info */
char name[sNAMEMAX+1];
char ident; /* iVARIABLE, iREFERENCE, iREFARRAY or iVARARGS */
char usage; /* uCONST */
int *tags; /* argument tag id. list */
int numtags; /* number of tags in the tag list */
int dim[sDIMEN_MAX];
int idxtag[sDIMEN_MAX];
int numdim; /* number of dimensions */
unsigned char hasdefault; /* bit0: is there a default value? bit6: "tagof"; bit7: "sizeof" */
union {
cell val; /* default value */
struct {
char *symname; /* name of another symbol */
short level; /* indirection level for that symbol */
} size; /* used for "sizeof" default value */
struct {
cell *data; /* values of default array */
int size; /* complete length of default array */
int arraysize; /* size to reserve on the heap */
cell addr; /* address of the default array in the data segment */
} array;
} defvalue; /* default value, or pointer to default array */
int defvalue_tag; /* tag of the default value */
} arginfo;
/* Equate table, tagname table, library table */
typedef struct s_constvalue {
struct s_constvalue *next;
char name[sNAMEMAX+1];
cell value;
int index; /* index level, for constants referring to array sizes/tags
* automaton id. for states and automatons
* tag for enumeration lists */
} constvalue;
/* Symbol table format
*
* The symbol name read from the input file is stored in "name", the
* value of "addr" is written to the output file. The address in "addr"
* depends on the class of the symbol:
* global offset into the data segment
* local offset relative to the stack frame
* label generated hexadecimal number
* function offset into code segment
*/
typedef struct s_symbol {
struct s_symbol *next;
struct s_symbol *parent; /* hierarchical types */
struct s_symbol *target; /* proxy target */
char name[sNAMEMAX+1];
uint32_t hash; /* value derived from name, for quicker searching */
cell addr; /* address or offset (or value for constant, index for native function) */
cell codeaddr; /* address (in the code segment) where the symbol declaration starts */
char vclass; /* sLOCAL if "addr" refers to a local symbol */
char ident; /* see below for possible values */
short usage; /* see below for possible values */
char flags; /* see below for possible values */
int compound; /* compound level (braces nesting level) */
int tag; /* tagname id */
union {
int declared; /* label: how many local variables are declared */
struct {
int index; /* array & enum: tag of array indices or the enum item */
int field; /* enumeration fields, where a size is attached to the field */
} tags; /* extra tags */
constvalue *lib; /* native function: library it is part of */
long stacksize; /* normal/public function: stack requirements */
} x; /* 'x' for 'extra' */
union {
arginfo *arglist; /* types of all parameters for functions */
constvalue *enumlist;/* list of names for the "root" of an enumeration */
struct {
cell length; /* arrays: length (size) */
cell slength; /* if a string index, this will be set to the original size */
short level; /* number of dimensions below this level */
} array;
} dim; /* for 'dimension', both functions and arrays */
constvalue *states; /* list of state function/state variable ids + addresses */
int fnumber; /* static global variables: file number in which the declaration is visible */
int lnumber; /* line number (in the current source file) for the declaration */
struct s_symbol **refer; /* referrer list, functions that "use" this symbol */
int numrefers; /* number of entries in the referrer list */
char *documentation; /* optional documentation string */
} symbol;
/* Possible entries for "ident". These are used in the "symbol", "value"
* and arginfo structures. Not every constant is valid for every use.
* In an argument list, the list is terminated with a "zero" ident; labels
* cannot be passed as function arguments, so the value 0 is overloaded.
*/
#define iLABEL 0
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
#define iARRAY 3
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
#define iARRAYCELL 5 /* array element, cell that must be fetched indirectly */
#define iARRAYCHAR 6 /* array element, character from cell from array */
#define iEXPRESSION 7 /* expression result, has no address (rvalue) */
#define iCONSTEXPR 8 /* constant expression (or constant symbol) */
#define iFUNCTN 9
#define iREFFUNC 10
#define iVARARGS 11 /* function specified ... as argument(s) */
#define iPROXY 12 /* proxies to another symbol. */
#define iACCESSOR 13 /* property accessor via a methodmap_method_t */
/* Possible entries for "usage"
*
* This byte is used as a serie of bits, the syntax is different for
* functions and other symbols:
*
* VARIABLE
* bits: 0 (uDEFINE) the variable is defined in the source file
* 1 (uREAD) the variable is "read" (accessed) in the source file
* 2 (uWRITTEN) the variable is altered (assigned a value)
* 3 (uCONST) the variable is constant (may not be assigned to)
* 4 (uPUBLIC) the variable is public
* 6 (uSTOCK) the variable is discardable (without warning)
*
* FUNCTION
* bits: 0 (uDEFINE) the function is defined ("implemented") in the source file
* 1 (uREAD) the function is invoked in the source file
* 2 (uRETVALUE) the function returns a value (or should return a value)
* 3 (uPROTOTYPED) the function was prototyped (implicitly via a definition or explicitly)
* 4 (uPUBLIC) the function is public
* 5 (uNATIVE) the function is native
* 6 (uSTOCK) the function is discardable (without warning)
* 7 (uMISSING) the function is not implemented in this source file
* 8 (uFORWARD) the function is explicitly forwardly declared
*
* CONSTANT
* bits: 0 (uDEFINE) the symbol is defined in the source file
* 1 (uREAD) the constant is "read" (accessed) in the source file
* 2 (uWRITTEN) redundant, but may be set for constants passed by reference
* 3 (uPREDEF) the constant is pre-defined and should be kept between passes
* 5 (uENUMROOT) the constant is the "root" of an enumeration
* 6 (uENUMFIELD) the constant is a field in a named enumeration
*/
#define uDEFINE 0x001
#define uREAD 0x002
#define uWRITTEN 0x004
#define uRETVALUE 0x004 /* function returns (or should return) a value */
#define uCONST 0x008
#define uPROTOTYPED 0x008
#define uPREDEF 0x008 /* constant is pre-defined */
#define uPUBLIC 0x010
#define uNATIVE 0x020
#define uENUMROOT 0x020
#define uSTOCK 0x040
#define uENUMFIELD 0x040
#define uMISSING 0x080
#define uFORWARD 0x100
#define uSTRUCT 0x200 /* :TODO: make this an ident */
/* uRETNONE is not stored in the "usage" field of a symbol. It is
* used during parsing a function, to detect a mix of "return;" and
* "return value;" in a few special cases.
*/
#define uRETNONE 0x10
#define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */
#define uCOUNTOF 0x20 /* set in the "hasdefault" field of the arginfo struct */
#define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
#define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
#define uMAINFUNC "main"
#define uENTRYFUNC "entry"
#define sGLOBAL 0 /* global variable/constant class (no states) */
#define sLOCAL 1 /* local variable/constant */
#define sSTATIC 2 /* global life, local scope */
#define sSTATEVAR 3 /* criterion to find variables (sSTATEVAR implies a global variable) */
struct methodmap_method_s;
typedef struct value_s {
symbol *sym; /* symbol in symbol table, NULL for (constant) expression */
cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
* also used for the size of a literal array */
int tag; /* tag (of the expression) */
int cmptag; /* for searching symbols: choose the one with the matching tag */
char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
* iEXPRESSION or iREFERENCE */
char boolresult; /* boolean result for relational operators */
cell *arrayidx; /* last used array indices, for checking self assignment */
/* when ident == iACCESSOR */
struct methodmap_method_s *accessor;
} value;
/* Wrapper around value + l/rvalue bit. */
typedef struct svalue_s {
value val;
int lvalue;
} svalue;
#define DECLFLAG_ARGUMENT 0x02 // The declaration is for an argument.
#define DECLFLAG_VARIABLE 0x04 // The declaration is for a variable.
#define DECLFLAG_ENUMROOT 0x08 // Multi-dimensional arrays should have an enumroot.
#define DECLFLAG_MAYBE_FUNCTION 0x10 // Might be a named function.
#define DECLFLAG_DYNAMIC_ARRAYS 0x20 // Dynamic arrays are allowed.
#define DECLFLAG_OLD 0x40 // Known old-style declaration.
#define DECLFLAG_FIELD 0x80 // Struct field.
#define DECLMASK_NAMED_DECL (DECLFLAG_ARGUMENT | DECLFLAG_VARIABLE | DECLFLAG_MAYBE_FUNCTION | DECLFLAG_FIELD)
typedef struct {
// Array information.
int numdim;
int dim[sDIMEN_MAX];
int idxtag[sDIMEN_MAX];
cell size;
constvalue *enumroot;
// Type information.
int tag; // Same as tags[0].
int tags[MAXTAGS]; // List of tags if multi-tagged.
int numtags; // Number of tags found.
int ident; // Either iREFERENCE, iARRAY, or iVARIABLE.
char usage; // Usage flags.
} typeinfo_t;
/* For parsing declarations. */
typedef struct {
char name[sNAMEMAX + 1];
typeinfo_t type;
int is_new; // New-style declaration.
int has_postdims; // Dimensions, if present, were in postfix position.
int opertok; // Operator token, if applicable.
} declinfo_t;
/* "while" statement queue (also used for "for" and "do - while" loops) */
enum {
wqBRK, /* used to restore stack for "break" */
wqCONT, /* used to restore stack for "continue" */
wqLOOP, /* loop start label number */
wqEXIT, /* loop exit label number (jump if false) */
/* --- */
wqSIZE /* "while queue" size */
};
#define wqTABSZ (24*wqSIZE) /* 24 nested loop statements */
enum {
statIDLE, /* not compiling yet */
statFIRST, /* first pass */
statWRITE, /* writing output */
statSKIP, /* skipping output */
};
typedef struct s_stringlist {
struct s_stringlist *next;
union {
char *line;
struct s_stringlist *tail;
};
} stringlist;
typedef struct s_stringpair {
struct s_stringpair *next;
char *first;
char *second;
int matchlength;
char flags;
char *documentation;
} stringpair;
// Helper for token info.
typedef struct {
int id;
cell val;
char *str;
} token_t;
// The method name buffer is larger since we can include our parent class's
// name, a "." to separate it, a "~" for constructors, or a ".get/.set" for
// accessors.
#define METHOD_NAMEMAX sNAMEMAX * 2 + 6
typedef struct {
token_t tok;
char name[METHOD_NAMEMAX + 1];
} token_ident_t;
/* macros for code generation */
#define opcodes(n) ((n)*sizeof(cell)) /* opcode size */
#define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */
/* Tokens recognized by lex()
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
*/
enum TokenKind {
/* value of first multi-character operator */
tFIRST = 256,
/* multi-character operators */
taMULT = tFIRST, /* *= */
taDIV, /* /= */
taMOD, /* %= */
taADD, /* += */
taSUB, /* -= */
taSHL, /* <<= */
taSHRU, /* >>>= */
taSHR, /* >>= */
taAND, /* &= */
taXOR, /* ^= */
taOR, /* |= */
tlOR, /* || */
tlAND, /* && */
tlEQ, /* == */
tlNE, /* != */
tlLE, /* <= */
tlGE, /* >= */
tSHL, /* << */
tSHRU, /* >>> */
tSHR, /* >> */
tINC, /* ++ */
tDEC, /* -- */
tELLIPS, /* ... */
tDBLDOT, /* .. */
tDBLCOLON, /* :: */
/* value of last multi-character operator */
tMIDDLE = tDBLCOLON,
/* reserved words (statements) */
tASSERT,
tBEGIN,
tBREAK,
tCASE,
tCELLSOF,
tCHAR,
tCONST,
tCONTINUE,
tDECL,
tDEFAULT,
tDEFINED,
tDELETE,
tDO,
tELSE,
tEND,
tENUM,
tEXIT,
tFOR,
tFORWARD,
tFUNCENUM,
tFUNCTAG,
tFUNCTION,
tGOTO,
tIF,
tINT,
tMETHODMAP,
tNATIVE,
tNEW,
tNULL,
tNULLABLE,
tOBJECT,
tOPERATOR,
tPUBLIC,
tRETURN,
tSIZEOF,
tSLEEP,
tSTATIC,
tSTOCK,
tSTRUCT,
tSWITCH,
tTAGOF,
tTHEN,
tTYPEDEF,
tVOID,
tWHILE,
/* compiler directives */
tpASSERT, /* #assert */
tpDEFINE,
tpELSE, /* #else */
tpELSEIF, /* #elseif */
tpEMIT,
tpENDIF,
tpENDINPUT,
tpENDSCRPT,
tpERROR,
tpFILE,
tpIF, /* #if */
tINCLUDE,
tpLINE,
tpPRAGMA,
tpTRYINCLUDE,
tpUNDEF,
tLAST = tpUNDEF, /* value of last multi-character match-able token */
/* semicolon is a special case, because it can be optional */
tTERM, /* semicolon or newline */
tENDEXPR, /* forced end of expression */
/* other recognized tokens */
tNUMBER, /* integer number */
tRATIONAL, /* rational number */
tSYMBOL,
tLABEL,
tSTRING,
tEXPR, /* for assigment to "lastst" only (see SC1.C) */
tENDLESS, /* endless loop, for assigment to "lastst" only */
tEMPTYBLOCK, /* empty blocks for AM bug 4825 */
tEOL, /* newline, only returned by peek_new_line() */
tLAST_TOKEN_ID
};
/* (reversed) evaluation of staging buffer */
#define sSTARTREORDER 0x01
#define sENDREORDER 0x02
#define sEXPRSTART 0x80 /* top bit set, rest is free */
#define sMAXARGS 127 /* relates to the bit pattern of sEXPRSTART */
#define sDOCSEP 0x01 /* to separate documentation comments between functions */
/* codes for ffabort() */
#define xEXIT 1 /* exit code in PRI */
#define xASSERTION 2 /* abort caused by failing assertion */
#define xSTACKERROR 3 /* stack/heap overflow */
#define xBOUNDSERROR 4 /* array index out of bounds */
#define xMEMACCESS 5 /* data access error */
#define xINVINSTR 6 /* invalid instruction */
#define xSTACKUNDERFLOW 7 /* stack underflow */
#define xHEAPUNDERFLOW 8 /* heap underflow */
#define xCALLBACKERR 9 /* no, or invalid, callback */
#define xSLEEP 12 /* sleep, exit code in PRI, tag in ALT */
/* Miscellaneous */
#if !defined TRUE
#define FALSE 0
#define TRUE 1
#endif
#define sIN_CSEG 1 /* if parsing CODE */
#define sIN_DSEG 2 /* if parsing DATA */
#define sCHKBOUNDS 1 /* bit position in "debug" variable: check bounds */
#define sSYMBOLIC 2 /* bit position in "debug" variable: symbolic info */
#define sRESET 0 /* reset error flag */
#define sFORCESET 1 /* force error flag on */
#define sEXPRMARK 2 /* mark start of expression */
#define sEXPRRELEASE 3 /* mark end of expression */
#define sSETPOS 4 /* set line number for the error */
enum {
sOPTIMIZE_NONE, /* no optimization */
sOPTIMIZE_NOMACRO, /* no macro instructions */
sOPTIMIZE_DEFAULT, /* full optimization */
/* ----- */
sOPTIMIZE_NUMBER
};
typedef enum s_regid {
sPRI, /* indicates the primary register */
sALT, /* indicates the secundary register */
} regid;
typedef enum s_optmark {
sEXPR, /* end of expression (for expressions that form a statement) */
sPARM, /* end of parameter (in a function parameter list) */
sLDECL, /* start of local declaration (variable) */
} optmark;
#define suSLEEP_INSTR 0x01 /* the "sleep" instruction was used */
#define PUBLICTAG 0x80000000Lu
#define FIXEDTAG 0x40000000Lu
#define FUNCTAG 0x20000000Lu
#define OBJECTTAG 0x10000000Lu
#define ENUMTAG 0x08000000Lu
#define METHODMAPTAG 0x04000000Lu
#define STRUCTTAG 0x02000000Lu
#define TAGMASK (~PUBLICTAG)
#define TAGTYPEMASK (FUNCTAG | OBJECTTAG | ENUMTAG | METHODMAPTAG | STRUCTTAG)
#define TAGFLAGMASK (FIXEDTAG | TAGTYPEMASK)
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
/*
* Functions you call from the "driver" program
*/
int pc_compile(int argc, char **argv);
int pc_addconstant(const char *name,cell value,int tag);
int pc_addtag(const char *name);
int pc_addtag_flags(const char *name, int flags);
int pc_findtag(const char *name);
constvalue *pc_tagptr(const char *name);
int pc_enablewarning(int number,int enable);
const char *pc_tagname(int tag);
int parse_decl(declinfo_t *decl, int flags);
const char *type_to_name(int tag);
/*
* Functions called from the compiler (to be implemented by you)
*/
/* general console output */
int pc_printf(const char *message,...);
/* error report function */
int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr);
/* input from source file */
void *pc_opensrc(char *filename); /* reading only */
void *pc_createsrc(char *filename);
void pc_closesrc(void *handle); /* never delete */
char *pc_readsrc(void *handle,unsigned char *target,int maxchars);
int pc_writesrc(void *handle,unsigned char *source);
void *pc_getpossrc(void *handle,void *position); /* mark the current position */
void pc_resetsrc(void *handle,void *position); /* reset to a position marked earlier */
int pc_eofsrc(void *handle);
/* output to intermediate (.ASM) file */
void *pc_openasm(char *filename); /* read/write */
void pc_closeasm(void *handle,int deletefile);
void pc_resetasm(void *handle);
int pc_writeasm(void *handle,const char *str);
char *pc_readasm(void *handle,char *target,int maxchars);
void sp_fdbg_ntv_start(int num_natives);
void sp_fdbg_ntv_hook(int index, symbol *sym);
/* function prototypes in SC1.C */
void set_extension(char *filename,const char *extension,int force);
symbol *fetchfunc(char *name);
char *operator_symname(char *symname,const char *opername,int tag1,int tag2,int numtags,int resulttag);
char *funcdisplayname(char *dest,char *funcname);
int exprconst(cell *val,int *tag,symbol **symptr);
constvalue *append_constval(constvalue *table,const char *name,cell val,int index);
constvalue *find_constval(constvalue *table,char *name,int index);
void delete_consttable(constvalue *table);
symbol *add_constant(const char *name,cell val,int vclass,int tag);
void exporttag(int tag);
void sc_attachdocumentation(symbol *sym);
constvalue *find_tag_byval(int tag);
int get_actual_compound(symbol *sym);
/* function prototypes in SC2.C */
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
#define PUSHSTK_I(v) { stkitem s_; s_.i=(v); pushstk(s_); }
#define POPSTK_P() (popstk().pv)
#define POPSTK_I() (popstk().i)
void pushstk(stkitem val);
stkitem popstk(void);
void clearstk(void);
int plungequalifiedfile(char *name); /* explicit path included */
int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
void preprocess(void);
void lexinit(void);
int lex(cell *lexvalue,char **lexsym);
int lextok(token_t *tok);
int lexpeek(int id);
void lexpush(void);
void lexclr(int clreol);
int matchtoken(int token);
int tokeninfo(cell *val,char **str);
int needtoken(int token);
int matchtoken2(int id, token_t *tok);
int expecttoken(int id, token_t *tok);
int matchsymbol(token_ident_t *ident);
int needsymbol(token_ident_t *ident);
int peek_same_line();
int require_newline(int allow_semi);
void litadd(cell value);
void litinsert(cell value,int pos);
int alphanum(char c);
int ishex(char c);
void delete_symbol(symbol *root,symbol *sym);
void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
int refer_symbol(symbol *entry,symbol *bywhom);
void markusage(symbol *sym,int usage);
symbol *findglb(const char *name,int filter);
symbol *findloc(const char *name);
symbol *findconst(const char *name,int *matchtag);
symbol *finddepend(const symbol *parent);
symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage);
symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
int dim[],int numdim,int idxtag[]);
symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
int dim[],int numdim,int idxtag[],int slength);
symbol *addvariable3(declinfo_t *decl,cell addr,int vclass,int slength);
int getlabel(void);
char *itoh(ucell val);
#define MATCHTAG_COERCE 0x1 // allow coercion
#define MATCHTAG_SILENT 0x2 // silence the error(213) warning
#define MATCHTAG_COMMUTATIVE 0x4 // order does not matter
/* function prototypes in SC3.C */
int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
value *lval,int *resulttag);
int matchtag(int formaltag,int actualtag,int allowcoerce);
int checktag(int tags[],int numtags,int exprtag);
int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult,value *_lval);
int sc_getstateid(constvalue **automaton,constvalue **state);
cell array_totalsize(symbol *sym);
int matchtag_string(int ident, int tag);
int checktag_string(value *sym1, value *sym2);
int checktags_string(int tags[], int numtags, value *sym1);
int lvalexpr(svalue *sval);
/* function prototypes in SC4.C */
void writeleader(symbol *root);
void writetrailer(void);
void begcseg(void);
void begdseg(void);
void setline(int chkbounds);
void setfiledirect(char *name);
void setlinedirect(int line);
void setlabel(int index);
void markexpr(optmark type,const char *name,cell offset);
void startfunc(char *fname);
void endfunc(void);
void alignframe(int numbytes);
void rvalue(value *lval);
void address(symbol *ptr,regid reg);
void store(value *lval);
void loadreg(cell address,regid reg);
void storereg(cell address,regid reg);
void memcopy(cell size);
void copyarray(symbol *sym,cell size);
void fillarray(symbol *sym,cell size,cell value);
void ldconst(cell val,regid reg);
void moveto1(void);
void move_alt(void);
void pushreg(regid reg);
void pushval(cell val);
void popreg(regid reg);
void genarray(int dims, int _autozero);
void swap1(void);
void ffswitch(int label);
void ffcase(cell value,char *labelname,int newtable);
void ffcall(symbol *sym,const char *label,int numargs);
void ffret(int remparams);
void ffabort(int reason);
void ffbounds(cell size);
void jumplabel(int number);
void defstorage(void);
void modstk(int delta);
void setstk(cell value);
void modheap(int delta);
void modheap_i();
void setheap_pri(void);
void setheap(cell value);
void cell2addr(void);
void cell2addr_alt(void);
void addr2cell(void);
void char2addr(void);
void charalign(void);
void addconst(cell value);
void setheap_save(cell value);
void stradjust(regid reg);
void invoke_getter(struct methodmap_method_s *method);
void invoke_setter(struct methodmap_method_s *method, int save);
void inc_pri();
void dec_pri();
void load_hidden_arg();
/* Code generation functions for arithmetic operators.
*
* Syntax: o[u|s|b]_name
* | | | +--- name of operator
* | | +----- underscore
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
* +------------- "o"perator
*/
void os_mult(void); /* multiplication (signed) */
void os_div(void); /* division (signed) */
void os_mod(void); /* modulus (signed) */
void ob_add(void); /* addition */
void ob_sub(void); /* subtraction */
void ob_sal(void); /* shift left (arithmetic) */
void os_sar(void); /* shift right (arithmetic, signed) */
void ou_sar(void); /* shift right (logical, unsigned) */
void ob_or(void); /* bitwise or */
void ob_xor(void); /* bitwise xor */
void ob_and(void); /* bitwise and */
void ob_eq(void); /* equality */
void ob_ne(void); /* inequality */
void relop_prefix(void);
void relop_suffix(void);
void os_le(void); /* less or equal (signed) */
void os_ge(void); /* greater or equal (signed) */
void os_lt(void); /* less (signed) */
void os_gt(void); /* greater (signed) */
void lneg(void);
void neg(void);
void invert(void);
void nooperation(void);
void inc(value *lval);
void dec(value *lval);
void jmp_ne0(int number);
void jmp_eq0(int number);
void outval(cell val,int newline);
/* function prototypes in SC5.C */
int error(int number,...);
void errorset(int code,int line);
/* function prototypes in SC6.C */
void assemble(const char *outname, void *fin);
/* function prototypes in SC7.C */
void stgbuffer_cleanup(void);
void stgmark(char mark);
void stgwrite(const char *st);
void stgout(int index);
void stgdel(int index,cell code_index);
int stgget(int *index,cell *code_index);
void stgset(int onoff);
int phopt_init(void);
int phopt_cleanup(void);
/* function prototypes in SCLIST.C */
char* duplicatestring(const char* sourcestring);
stringpair *insert_alias(char *name,char *alias);
stringpair *find_alias(char *name);
int lookup_alias(char *target,char *name);
void delete_aliastable(void);
stringlist *insert_path(char *path);
char *get_path(int index);
void delete_pathtable(void);
stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen);
int get_subst(int index,char **pattern,char **substitution);
stringpair *find_subst(char *name,int length);
int delete_subst(char *name,int length);
void delete_substtable(void);
stringlist *insert_sourcefile(char *string);
char *get_sourcefile(int index);
void delete_sourcefiletable(void);
stringlist *insert_docstring(char *string);
char *get_docstring(int index);
void delete_docstring(int index);
void delete_docstringtable(void);
stringlist *insert_autolist(const char *string);
char *get_autolist(int index);
void delete_autolisttable(void);
stringlist *insert_dbgfile(const char *filename);
stringlist *insert_dbgline(int linenr);
stringlist *insert_dbgsymbol(symbol *sym);
char *get_dbgstring(int index);
void delete_dbgstringtable(void);
stringlist *get_dbgstrings();
/* function prototypes in SCI18N.C */
#define MAXCODEPAGE 12
int cp_path(const char *root,const char *directory);
int cp_set(const char *name);
cell cp_translate(const unsigned char *string,const unsigned char **endptr);
cell get_utf8_char(const unsigned char *string,const unsigned char **endptr);
int scan_utf8(void *fp,const char *filename);
/* function prototypes in SCSTATE.C */
constvalue *automaton_add(const char *name);
constvalue *automaton_find(const char *name);
constvalue *automaton_findid(int id);
constvalue *state_add(const char *name,int fsa_id);
constvalue *state_find(const char *name,int fsa_id);
constvalue *state_findid(int id);
void state_buildlist(int **list,int *listsize,int *count,int stateid);
int state_addlist(int *list,int count,int fsa_id);
void state_deletetable(void);
int state_getfsa(int listid);
int state_count(int listid);
int state_inlist(int listid,int state);
int state_listitem(int listid,int index);
void state_conflict(symbol *root);
int state_conflict_id(int listid1,int listid2);
/* external variables (defined in scvars.c) */
#if !defined SC_SKIP_VDECL
typedef struct HashTable HashTable;
extern struct HashTable *sp_Globals;
extern symbol loctab; /* local symbol table */
extern symbol glbtab; /* global symbol table */
extern cell *litq; /* the literal queue */
extern unsigned char pline[]; /* the line read from the input file */
extern const unsigned char *lptr;/* points to the current position in "pline" */
extern constvalue tagname_tab;/* tagname table */
extern constvalue libname_tab;/* library table (#pragma library "..." syntax) */
extern constvalue *curlibrary;/* current library */
extern int pc_addlibtable; /* is the library table added to the AMX file? */
extern symbol *curfunc; /* pointer to current function */
extern char *inpfname; /* name of the file currently read from */
extern char outfname[]; /* intermediate (assembler) file name */
extern char binfname[]; /* binary file name */
extern char errfname[]; /* error file name */
extern char sc_ctrlchar; /* the control character (or escape character) */
extern char sc_ctrlchar_org;/* the default control character */
extern int litidx; /* index to literal table */
extern int litmax; /* current size of the literal table */
extern int stgidx; /* index to the staging buffer */
extern int sc_labnum; /* number of (internal) labels */
extern int staging; /* true if staging output */
extern cell declared; /* number of local cells declared */
extern cell glb_declared; /* number of global cells declared */
extern cell code_idx; /* number of bytes with generated code */
extern int ntv_funcid; /* incremental number of native function */
extern int errnum; /* number of errors */
extern int warnnum; /* number of warnings */
extern int sc_debug; /* debug/optimization options (bit field) */
extern int sc_packstr; /* strings are packed by default? */
extern int sc_asmfile; /* create .ASM file? */
extern int sc_listing; /* create .LST file? */
extern int sc_compress; /* compress bytecode? */
extern int sc_needsemicolon;/* semicolon required to terminate expressions? */
extern int sc_dataalign; /* data alignment value */
extern int sc_alignnext; /* must frame of the next function be aligned? */
extern int pc_docexpr; /* must expression be attached to documentation comment? */
extern int sc_showincludes; /* show include files? */
extern int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
extern cell pc_stksize; /* stack size */
extern cell pc_amxlimit; /* abstract machine size limit (code + data, or only code) */
extern cell pc_amxram; /* abstract machine data size limit */
extern int freading; /* is there an input file ready for reading? */
extern int fline; /* the line number in the current file */
extern short fnumber; /* number of files in the file table (debugging) */
extern short fcurrent; /* current file being processed (debugging) */
extern short sc_intest; /* true if inside a test */
extern int sideeffect; /* true if an expression causes a side-effect */
extern int stmtindent; /* current indent of the statement */
extern int indent_nowarn; /* skip warning "217 loose indentation" */
extern int sc_tabsize; /* number of spaces that a TAB represents */
extern short sc_allowtags; /* allow/detect tagnames in lex() */
extern int sc_status; /* read/write status */
extern int sc_err_status; /* TRUE if errors should be generated even if sc_status = SKIP */
extern int sc_rationaltag; /* tag for rational numbers */
extern int rational_digits; /* number of fractional digits */
extern int sc_allowproccall;/* allow/detect tagnames in lex() */
extern short sc_is_utf8; /* is this source file in UTF-8 encoding */
extern char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
extern int sc_curstates; /* ID of the current state list */
extern int pc_optimize; /* (peephole) optimization level */
extern int pc_memflags; /* special flags for the stack/heap usage */
extern int pc_functag; /* global function tag */
extern int pc_tag_string; /* global String tag */
extern int pc_tag_void; /* global void tag */
extern int pc_tag_object; /* root object tag */
extern int pc_tag_bool; /* global bool tag */
extern int pc_tag_null_t; /* the null type */
extern int pc_tag_nullfunc_t; /* the null function type */
extern int pc_anytag; /* global any tag */
extern int glbstringread; /* last global string read */
extern int sc_require_newdecls; /* only newdecls are allowed */
extern constvalue sc_automaton_tab; /* automaton table */
extern constvalue sc_state_tab; /* state table */
extern void *inpf; /* file read from (source or include) */
extern void *inpf_org; /* main source file */
extern void *outf; /* file written to */
extern jmp_buf errbuf; /* target of longjmp() on a fatal error */
#if !defined SC_LIGHT
extern int sc_makereport; /* generate a cross-reference report */
#endif
#if defined WIN32
# if !defined snprintf
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# endif
#endif
#endif /* SC_SKIP_VDECL */
typedef struct array_info_s
{
const int *dim_list; /* Dimension sizes */
int dim_count; /* Number of dimensions */
const int *lastdim_list; /* Sizes of last dimensions, if variable */
const cell *dim_offs_precalc; /* Cached calculations into the lastdim_list array */
cell *data_offs; /* Current offset AFTER the indirection vectors (data) */
int *cur_dims; /* Current dimensions the recursion is at */
cell *base; /* &litq[startlit] */
} array_info_t;
#endif /* SC_H_INCLUDED */