Introduce basic methodmaps (PR #38).

commit 1e5213d43fdd170bb0c30af914a4e40610014b2b
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 04:09:27 2014 -0700

    Quell MSVC C99 bugs.

commit f2e166c5925fda49b5abeadc0aa0f9156b99cf11
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:59:23 2014 -0700

    Fix varying levels of stupid memory errors.

commit b0773d7be45345351ab1c1738681d5215a97f3f3
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:36:39 2014 -0700

    Fix memory leak in parsing some control flow structures.

commit 5aca55713cfc2dd09c5900132fc4a6be51e3e309
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:35:17 2014 -0700

    Fix memory leak in struct parsing.

commit b46ec5cd281b46177e83c4f0a4acac9cc1065c53
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:32:03 2014 -0700

    Fix build.

commit 17bbbb9a46bfc00862adca7d3e15369a48e9ac0f
Merge: c083409 2107599
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 01:26:27 2014 -0700

    Merge branch 'master' into methodmaps

commit c083409b569abff13f24d3b8c47f8ff199036840
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 23:49:36 2014 -0700

    Add VS2k13 support.

commit b7993778494d538cb1c1965116030142a7f7765b
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 01:28:08 2014 -0700

    Implement destructors.

commit 1a340dec260d079ed1b79351ed7b50b58a997cea
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 00:08:04 2014 -0700

    Add some tests.

commit 12db52ee64eb009ead9294495e9034c63ab75b09
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 00:05:49 2014 -0700

    Initial implementation of constructors.

commit 074669a658caa2822aa864164b615a244c00a0bc
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:42:35 2014 -0700

    Add simple test harness.

commit 27c1e3cf14e1e6c5cf35c80c792cce2744b804d7
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:15:42 2014 -0700

    Big refactoring for new syntax.

commit f3c37fdc919e76ee0815e2394cbe8d221f9fc0ca
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:12:54 2014 -0700

    Refactor tests for the new syntax.

commit 6211f392f8e722b907474cf380cfac4347e46b8e
Author: David Anderson <dvander@alliedmods.net>
Date:   Wed Jun 18 22:25:48 2014 -0700

    Make lexer tokens an enum.

commit 5210b013756b0b00de3a61c6490685c768ff8cbd
Author: David Anderson <dvander@alliedmods.net>
Date:   Tue Jun 17 06:48:15 2014 -0700

    Add comment.

commit 06688ff4aced14077dd21a9cc1db4c26c7420ff3
Author: David Anderson <dvander@alliedmods.net>
Date:   Tue Jun 17 06:46:10 2014 -0700

    Allow |this| to be a base type of the methodmap.

commit 05cf3682020e0e6d9f47b1a0a6727b9edbfe7622
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 22:11:58 2014 -0700

    Unify duplicate typesymbol checking.

commit 09161bf2691c8c1ed25b9b70fda01c336f21aa0b
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 19:53:36 2014 -0700

    Close loophole that allowed methodmaps for enums.

commit 5bb4aeba89fec47a4de7a7532d27830999d1fcb4
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:50:42 2014 -0700

    Add tests and dbi/handle changes.

commit b9203e2491daec2a8073874d6375949483778d14
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:38:29 2014 -0700

    Ensure methodmap tags are fixed.

commit 878b80fd87a2ea500d3a28ce2d53f616d1efe5e8
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:36:04 2014 -0700

    Implement inheritance.

commit 6ba9e004fbae18ad68056368ddd0affdc78659f1
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:31:00 2014 -0700

    Refactor matchtag() to not be insane.

commit 4ede6343b0682c6df98fa869153828e92f891bcc
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:20:50 2014 -0700

    Fix indenting.

commit e3ddef8916e3dd5f4ff0fe571d6e1c3acd163352
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:20:27 2014 -0700

    Initial prototype.
This commit is contained in:
David Anderson 2014-06-21 04:10:15 -07:00
parent 210759907d
commit 63ad5eff18
47 changed files with 1956 additions and 731 deletions

View File

@ -701,18 +701,7 @@ native SQL_TQuery(Handle:database, SQLTCallback:callback, const String:query[],
*
* @return A transaction handle.
*/
native Handle:SQL_CreateTransaction();
/**
* Adds a query to a transaction object.
*
* @param txn A transaction handle.
* @param query Query string.
* @param data Extra data value to pass to the final callback.
* @return The index of the query in the transaction's query list.
* @error Invalid transaction handle.
*/
native SQL_AddQuery(Handle:txn, const String:query[], any:data=0);
native Transaction:SQL_CreateTransaction();
/**
* Callback for a successful transaction.
@ -739,6 +728,23 @@ functag public SQLTxnSuccess(Handle:db, any:data, numQueries, Handle:results[],
*/
functag public SQLTxnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[]);
/**
* Adds a query to a transaction object.
*
* @param txn A transaction handle.
* @param query Query string.
* @param data Extra data value to pass to the final callback.
* @return The index of the query in the transaction's query list.
* @error Invalid transaction handle.
*/
native SQL_AddQuery(Transaction:txn, const String:query[], any:data=0);
methodmap Transaction < Handle
{
public Transaction() = SQL_CreateTransaction;
public AddQuery() = SQL_AddQuery;
};
/**
* Sends a transaction to the database thread. The transaction handle is
* automatically closed. When the transaction completes, the optional
@ -755,7 +761,7 @@ functag public SQLTxnFailure(Handle:db, any:data, numQueries, const String:error
*/
native SQL_ExecuteTransaction(
Handle:db,
Handle:txn,
Transaction:txn,
SQLTxnSuccess:onSuccess=SQLTxnSuccess:-1,
SQLTxnFailure:onError=SQLTxnFailure:-1,
any:data=0,

View File

@ -36,9 +36,9 @@
#define _handles_included
/**
* Handle helper macros.
* Preset Handle values.
*/
enum Handle
enum Handle: // Tag disables introducing "Handle" as a symbol.
{
INVALID_HANDLE = 0,
};
@ -52,10 +52,9 @@ enum Handle
* sure you read the documentation on whatever provided the Handle.
*
* @param hndl Handle to close.
* @return True if successful, false if not closeable.
* @error Invalid handles will cause a run time error.
*/
native bool:CloseHandle(Handle:hndl);
native CloseHandle(Handle:hndl);
/**
* Clones a Handle. When passing handles in between plugins, caching handles
@ -76,6 +75,15 @@ native bool:CloseHandle(Handle:hndl);
*/
native Handle:CloneHandle(Handle:hndl, Handle:plugin=INVALID_HANDLE);
/**
* Helper for object-oriented syntax.
*/
methodmap Handle
{
public Clone() = CloneHandle;
public ~Handle() = CloseHandle;
};
/**
* Do not use this function. Returns if a Handle and its contents
* are readable, whereas INVALID_HANDLE only checks for the absence

View File

@ -279,10 +279,10 @@ public Action:Command_TestTxn(args)
SetTestContext("CreateTransaction");
new Handle:txn = SQL_CreateTransaction();
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (4)", 50), 0);
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (5)", 60), 1);
AssertEq("AddQuery", SQL_AddQuery(txn, "SELECT COUNT(id) FROM egg", 70), 2);
new Transaction:txn = SQL_CreateTransaction();
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (4)", 50), 0);
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (5)", 60), 1);
AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2);
SQL_ExecuteTransaction(
db,
txn,
@ -292,9 +292,9 @@ public Action:Command_TestTxn(args)
);
txn = SQL_CreateTransaction();
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (6)", 50), 0);
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (6)", 60), 1);
AssertEq("AddQuery", SQL_AddQuery(txn, "SELECT COUNT(id) FROM egg", 70), 2);
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 50), 0);
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 60), 1);
AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2);
SQL_ExecuteTransaction(
db,
txn,
@ -306,13 +306,13 @@ public Action:Command_TestTxn(args)
// Make sure the transaction was rolled back - COUNT should be 5.
txn = SQL_CreateTransaction();
AssertEq("CloneHandle", _:CloneHandle(txn), _:INVALID_HANDLE);
SQL_AddQuery(txn, "SELECT COUNT(id) FROM egg");
txn.AddQuery("SELECT COUNT(id) FROM egg");
SQL_ExecuteTransaction(
db,
txn,
Txn_Test3_OnSuccess
);
CloseHandle(db);
db.Close();
return Plugin_Handled;
}

View File

@ -11,7 +11,7 @@ compiler.includes += [
]
if compiler.cc.behavior == 'gcc':
compiler.cflags += ['-Wno-format']
compiler.cflags += ['-std=c99', '-Wno-format']
if builder.target_platform == 'linux':
compiler.postlink += ['-lgcc', '-lm']
elif compiler.cc.behavior == 'msvc':

View File

@ -113,7 +113,8 @@ typedef struct s_constvalue {
*/
typedef struct s_symbol {
struct s_symbol *next;
struct s_symbol *parent; /* hierarchical types (multi-dimensional arrays) */
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) */
@ -150,7 +151,6 @@ typedef struct s_symbol {
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
@ -168,6 +168,7 @@ typedef struct s_symbol {
#define iFUNCTN 9
#define iREFFUNC 10
#define iVARARGS 11 /* function specified ... as argument(s) */
#define iPROXY 12 /* proxies to another symbol. */
/* Possible entries for "usage"
*
@ -237,7 +238,7 @@ typedef struct s_symbol {
#define sSTATEVAR 3 /* criterion to find variables (sSTATEVAR implies a global variable) */
typedef struct s_value {
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 */
@ -249,6 +250,20 @@ typedef struct s_value {
cell *arrayidx; /* last used array indices, for checking self assignment */
} value;
/* Wrapper around value + l/rvalue bit. */
typedef struct svalue_s {
value val;
int lvalue;
} svalue;
/* For parsing declarations. */
typedef struct {
char type[sNAMEMAX + 1];
constvalue *enumroot;
int tag;
char usage;
} declinfo_t;
/* "while" statement queue (also used for "for" and "do - while" loops) */
enum {
wqBRK, /* used to restore stack for "break" */
@ -284,6 +299,13 @@ typedef struct s_stringpair {
char *documentation;
} stringpair;
// Helper for token info.
typedef struct {
int id;
cell val;
char *str;
} token_t;
/* macros for code generation */
#define opcodes(n) ((n)*sizeof(cell)) /* opcode size */
#define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */
@ -291,101 +313,110 @@ typedef struct s_stringpair {
/* Tokens recognized by lex()
* Some of these constants are assigned as well to the variable "lastst" (see SC1.C)
*/
#define tFIRST 256 /* value of first multi-character operator */
#define tMIDDLE 280 /* value of last multi-character operator */
#define tLAST 332 /* value of last multi-character match-able token */
enum {
/* value of first multi-character operator */
tFIRST = 256,
/* multi-character operators */
#define taMULT 256 /* *= */
#define taDIV 257 /* /= */
#define taMOD 258 /* %= */
#define taADD 259 /* += */
#define taSUB 260 /* -= */
#define taSHL 261 /* <<= */
#define taSHRU 262 /* >>>= */
#define taSHR 263 /* >>= */
#define taAND 264 /* &= */
#define taXOR 265 /* ^= */
#define taOR 266 /* |= */
#define tlOR 267 /* || */
#define tlAND 268 /* && */
#define tlEQ 269 /* == */
#define tlNE 270 /* != */
#define tlLE 271 /* <= */
#define tlGE 272 /* >= */
#define tSHL 273 /* << */
#define tSHRU 274 /* >>> */
#define tSHR 275 /* >> */
#define tINC 276 /* ++ */
#define tDEC 277 /* -- */
#define tELLIPS 278 /* ... */
#define tDBLDOT 279 /* .. */
#define tDBLCOLON 280 /* :: */
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) */
#define tASSERT 281
#define tBEGIN 282
#define tBREAK 283
#define tCASE 284
#define tCELLSOF 285
#define tCHAR 286
#define tCONST 287
#define tCONTINUE 288
#define tDEFAULT 289
#define tDEFINED 290
#define tDO 291
#define tELSE 292
#define tEND 293
#define tENUM 294
#define tEXIT 295
#define tFOR 296
#define tFORWARD 297
#define tFUNCENUM 298
#define tFUNCTAG 299
#define tGOTO 300
#define tIF 301
#define tNATIVE 302
#define tNEW 303
#define tDECL 304
#define tOPERATOR 305
#define tPUBLIC 306
#define tRETURN 307
#define tSIZEOF 308
#define tSLEEP 309
#define tSTATIC 310
#define tSTOCK 311
#define tSTRUCT 312
#define tSWITCH 313
#define tTAGOF 314
#define tTHEN 315
#define tWHILE 316
tASSERT,
tBEGIN,
tBREAK,
tCASE,
tCELLSOF,
tCHAR,
tCONST,
tCONTINUE,
tDEFAULT,
tDEFINED,
tDELETE,
tDO,
tELSE,
tEND,
tENUM,
tEXIT,
tFOR,
tFORWARD,
tFUNCENUM,
tFUNCTAG,
tGOTO,
tIF,
tINT,
tMETHODMAP,
tNATIVE,
tNEW,
tDECL,
tOPERATOR,
tPUBLIC,
tRETURN,
tSIZEOF,
tSLEEP,
tSTATIC,
tSTOCK,
tSTRUCT,
tSWITCH,
tTAGOF,
tTHEN,
tVOID,
tWHILE,
/* compiler directives */
#define tpASSERT 317 /* #assert */
#define tpDEFINE 318
#define tpELSE 319 /* #else */
#define tpELSEIF 320 /* #elseif */
#define tpEMIT 321
#define tpENDIF 322
#define tpENDINPUT 323
#define tpENDSCRPT 324
#define tpERROR 325
#define tpFILE 326
#define tpIF 327 /* #if */
#define tINCLUDE 328
#define tpLINE 329
#define tpPRAGMA 330
#define tpTRYINCLUDE 331
#define tpUNDEF 332
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 */
#define tTERM 333 /* semicolon or newline */
#define tENDEXPR 334 /* forced end of expression */
tTERM, /* semicolon or newline */
tENDEXPR, /* forced end of expression */
/* other recognized tokens */
#define tNUMBER 335 /* integer number */
#define tRATIONAL 336 /* rational number */
#define tSYMBOL 337
#define tLABEL 338
#define tSTRING 339
#define tEXPR 341 /* for assigment to "lastst" only (see SC1.C) */
#define tENDLESS 342 /* endless loop, for assigment to "lastst" only */
#define tEMPTYBLOCK 343 /* empty blocks for AM bug 4825 */
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 */
tLAST_TOKEN_ID
};
/* (reversed) evaluation of staging buffer */
#define sSTARTREORDER 0x01
@ -467,8 +498,12 @@ typedef enum s_optmark {
int pc_compile(int argc, char **argv);
int pc_addconstant(char *name,cell value,int tag);
int pc_addtag(char *name);
int pc_addtag_flags(char *name, int flags);
int pc_findtag(const char *name);
int pc_addfunctag(char *name);
int pc_enablewarning(int number,int enable);
const char *pc_tagname(int tag);
int parse_decl(declinfo_t *decl, const token_t *first, int flags);
/*
* Functions called from the compiler (to be implemented by you)
@ -553,11 +588,13 @@ SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /
SC_FUNC void preprocess(void);
SC_FUNC void lexinit(void);
SC_FUNC int lex(cell *lexvalue,char **lexsym);
SC_FUNC int lextok(token_t *tok);
SC_FUNC void lexpush(void);
SC_FUNC void lexclr(int clreol);
SC_FUNC int matchtoken(int token);
SC_FUNC int tokeninfo(cell *val,char **str);
SC_FUNC int needtoken(int token);
SC_FUNC int expecttoken(int id, token_t *tok);
SC_FUNC void litadd(cell value);
SC_FUNC void litinsert(cell value,int pos);
SC_FUNC int alphanum(char c);
@ -570,8 +607,7 @@ SC_FUNC symbol *findglb(const char *name,int filter);
SC_FUNC symbol *findloc(const char *name);
SC_FUNC symbol *findconst(const char *name,int *matchtag);
SC_FUNC symbol *finddepend(const symbol *parent);
SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,
int usage);
SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag, int usage);
SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
int dim[],int numdim,int idxtag[]);
SC_FUNC symbol *addvariable2(const char *name,cell addr,int ident,int vclass,int tag,
@ -834,7 +870,8 @@ SC_VDECL int sc_curstates; /* ID of the current state list */
SC_VDECL int pc_optimize; /* (peephole) optimization level */
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
SC_VDECL int pc_functag; /* global function tag */
SC_VDECL int pc_tag_string; /* global string tag */
SC_VDECL int pc_tag_string; /* global String tag */
SC_VDECL int pc_tag_void; /* global void tag */
SC_VDECL int pc_anytag; /* global any tag */
SC_VDECL int glbstringread; /* last global string read */

View File

@ -1,3 +1,4 @@
/* vim: set sts=2 ts=8 sw=2 tw=99 et: */
/* Pawn compiler
*
* Function and variable definition and declaration, statement parser.
@ -75,6 +76,7 @@
int pc_anytag = 0;
int pc_functag = 0;
int pc_tag_string = 0;
int pc_tag_void = 0;
static void resetglobals(void);
static void initglobals(void);
@ -93,6 +95,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,
int stock,int fconst);
static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct);
static int declloc(int fstatic);
static void dodelete();
static void decl_const(int table);
static void declstruct();
static void decl_enum(int table);
@ -107,7 +110,7 @@ static cell initvector(int ident,int tag,cell size,int fillzero,
static cell init(int ident,int *tag,int *errorfound);
static int getstates(const char *funcname);
static void attachstatelist(symbol *sym, int state_id);
static void funcstub(int fnative);
static symbol *funcstub(int fnative);
static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stock);
static int declargs(symbol *sym,int chkshadow);
static void doarg(char *name,int ident,int offset,int tags[],int numtags,
@ -137,6 +140,7 @@ static void dogoto(void);
static void dolabel(void);
static void doreturn(void);
static void dofuncenum(int listmode);
static void domethodmap(LayoutSpec spec);
static void dobreak(void);
static void docont(void);
static void dosleep(void);
@ -346,6 +350,7 @@ int pc_compile(int argc, char *argv[])
resetglobals();
pstructs_free();
funcenums_free();
methodmaps_free();
sc_ctrlchar=sc_ctrlchar_org;
sc_packstr=lcl_packstr;
sc_needsemicolon=lcl_needsemicolon;
@ -407,6 +412,7 @@ int pc_compile(int argc, char *argv[])
reduce_referrers(&glbtab);
delete_symbols(&glbtab,0,TRUE,FALSE);
funcenums_free();
methodmaps_free();
pstructs_free();
#if !defined NO_DEFINE
delete_substtable();
@ -529,6 +535,7 @@ cleanup:
delete_sourcefiletable();
delete_dbgstringtable();
funcenums_free();
methodmaps_free();
pstructs_free();
#if !defined NO_DEFINE
delete_substtable();
@ -628,14 +635,33 @@ static void inst_datetime_defines(void)
insert_subst("__TIME__", ltime, 8);
}
const char *pc_tagname(int tag)
{
constvalue *ptr=tagname_tab.next;
for (; ptr; ptr=ptr->next) {
if ((int)(ptr->value & TAGMASK) == (tag & TAGMASK))
return ptr->name;
}
return "<unknown>";
}
int pc_findtag(const char *name)
{
constvalue *ptr=tagname_tab.next;
for (; ptr; ptr=ptr->next) {
if (strcmp(name,ptr->name)==0)
return (int)(ptr->value & TAGMASK);
}
return -1;
}
#if defined __cplusplus
extern "C"
#endif
int pc_addtag(char *name)
{
cell val;
constvalue *ptr;
int last,tag;
int val;
int flags = 0;
if (name==NULL) {
/* no tagname was given, check for one */
@ -645,6 +671,17 @@ int pc_addtag(char *name)
} /* if */
} /* if */
if (isupper(*name))
flags |= FIXEDTAG;
return pc_addtag_flags(name, flags);
}
int pc_addtag_flags(char *name, int flags)
{
constvalue *ptr;
int last,tag;
assert(strchr(name,':')==NULL); /* colon should already have been stripped */
last=0;
ptr=tagname_tab.next;
@ -661,8 +698,7 @@ int pc_addtag(char *name)
/* tagname currently unknown, add it */
tag=last+1; /* guaranteed not to exist already */
if (isupper(*name))
tag |= (int)FIXEDTAG;
tag|=flags;
append_constval(&tagname_tab,name,(cell)tag,0);
return tag;
}
@ -1326,6 +1362,8 @@ static void setconstants(void)
pc_anytag = pc_addtag("any");
pc_functag = pc_addfunctag("Function");
pc_tag_string = pc_addtag("String");
pc_tag_void = pc_addtag_flags("void", FIXEDTAG);
sc_rationaltag = pc_addtag("Float");
add_constant("true",1,sGLOBAL,1); /* boolean flags */
add_constant("false",0,sGLOBAL,1);
@ -1488,6 +1526,9 @@ static void parse(void)
case tFUNCENUM:
dofuncenum(TRUE);
break;
case tMETHODMAP:
domethodmap(Layout_MethodMap);
break;
case tFUNCTAG:
dofuncenum(FALSE);
break;
@ -1826,6 +1867,8 @@ static void declstructvar(char *firstname,int fpublic, pstruct_t *pstruct)
matchtoken(';');
/* Mark it as undefined instead */
mysym->usage = uSTOCK|uSTRUCT;
free(found);
free(values);
return;
} else {
mysym->usage = usage;
@ -3110,6 +3153,13 @@ static void decl_const(int vclass)
needtoken(tTERM);
}
static void check_struct_name(const char *name)
{
LayoutSpec spec = deduce_layout_spec_by_name(name);
if (!can_redef_layout_spec(spec, Layout_PawnStruct))
error(110, name, layout_spec_name(spec));
}
/*
* declstruct - declare a struct type
*/
@ -3128,10 +3178,7 @@ static void declstruct(void)
error(93);
}
if (pstructs_find(str) != NULL)
{
error(98);
}
check_struct_name(str);
pstruct = pstructs_add(str);
@ -3202,13 +3249,423 @@ static void declstruct(void)
}
if (pstructs_addarg(pstruct, &arg) == NULL)
{
error(99, arg.name, pstruct->name);
error(103, arg.name, layout_spec_name(Layout_PawnStruct));
}
} while (matchtoken(','));
needtoken('}');
matchtoken(';'); /* eat up optional semicolon */
}
int parse_typeexpr(declinfo_t *decl, const token_t *first, int flags)
{
token_t tok;
if (first) {
tok = *first;
} else {
lextok(&tok);
}
if (tok.id == tCONST) {
decl->usage |= uCONST;
lextok(&tok);
}
if (tok.id == tLABEL || tok.id == '[')
return FALSE;
switch (tok.id) {
case tINT:
strcpy(decl->type, "int");
decl->tag = 0;
break;
case tCHAR:
strcpy(decl->type, "char");
decl->tag = pc_tag_string;
break;
case tVOID:
strcpy(decl->type, "void");
decl->tag = pc_tag_void;
break;
case tSYMBOL:
strcpy(decl->type, tok.str);
if (strcmp(decl->type, "float") == 0) {
decl->tag = sc_rationaltag;
} else {
decl->tag = pc_findtag(decl->type);
if (decl->tag == sc_rationaltag)
error(98, "Float", "float");
else if (decl->tag == pc_tag_string)
error(98, "String", "char");
else if (decl->tag == 0)
error(98, "_", "int");
}
default:
return FALSE;
}
return TRUE;
}
// Parse a new-style declaration. If the name was already fetched (because we
// didn't have enough lookahead), it can be given ahead of time.
int parse_decl(declinfo_t *decl, const token_t *first, int flags)
{
memset(decl, 0, sizeof(*decl));
if (!parse_typeexpr(decl, first, flags))
return FALSE;
return TRUE;
}
void define_constructor(methodmap_t *map, methodmap_method_t *method)
{
symbol *sym = findglb(map->name, sGLOBAL);
if (sym && sym->ident == iPROXY && sym->parent == method->target)
return;
if (sym) {
const char *type = "<unknown>";
switch (sym->ident) {
case iVARIABLE:
case iARRAY:
case iARRAYCELL:
case iARRAYCHAR:
type = "variable";
break;
case iFUNCTN:
type = "function";
break;
}
error(113, map->name, type);
return;
}
sym = addsym(map->name, 0, iPROXY, sGLOBAL, 0, 0);
sym->target = method->target;
}
methodmap_method_t *parse_method(methodmap_t *map)
{
int is_dtor = 0;
int is_bind = 0;
int is_native = 0;
const char *spectype = layout_spec_name(map->spec);
// We keep a wider buffer since we do name munging.
char ident[sNAMEMAX * 3 + 1] = "<unknown>";
char bindname[sNAMEMAX * 3 + 1] = "<unknown>";
needtoken(tPUBLIC);
token_t tok;
declinfo_t decl;
if (matchtoken('~')) {
// We got something like "public ~Blah = X"
is_bind = 1;
is_dtor = 1;
if (needtoken(tSYMBOL)) {
tokeninfo(&tok.val, &tok.str);
strcpy(ident, tok.str);
}
needtoken('(');
needtoken(')');
needtoken('=');
if (!expecttoken(tSYMBOL, &tok))
return NULL;
strcpy(bindname, tok.str);
} else {
is_native = matchtoken(tNATIVE);
if (is_native) {
// If we have a native, we should always get a type expression next.
parse_decl(&decl, NULL, 0);
} else {
// Parsing "public Clone =" and "public Handle Clone = " requires two tokens
// of lookahead. By the time we see the '=' in the first example, we'd have
// expected a function name, but it's too late to back up - _lexpush is only
// one token deep.
//
// If we see a symbol and a '=', we know it's a simple binding. Otherwise,
// we have to take the token we got from lextok() and ask parse_decl() to
// start parsing it as a type expression.
int is_symbol = (lextok(&tok) == tSYMBOL);
if (is_symbol) {
// Save the string because matchtoken() will overwrite the token buffer.
// Note we also have to repoint tok so parse_decl will point at our
// local copy.
strcpy(ident, tok.str);
tok.str = ident;
if (matchtoken('(')) {
needtoken(')');
needtoken('=');
// Grab the name we're binding to.
is_bind = 1;
if (!expecttoken(tSYMBOL, &tok))
return NULL;
strcpy(bindname, tok.str);
}
}
if (!is_bind) {
// We didn't find an '=', so proceed with a normal function signature.
parse_decl(&decl, &tok, 0);
is_dtor = matchtoken('~');
if (lextok(&tok) != tSYMBOL) {
// Error, and if EOF, return. The lexpush is so we don't accidentally
// skip over a terminator or something, since we scan to the end of the
// line.
lexpush();
error(111);
if (tok.id == 0)
return NULL;
}
strcpy(ident, tok.str);
} // if (tok == symbol && matchtoken('='))
} // if (is_native)
} // if (matchtoken('~'))
symbol *target = NULL;
if (is_bind) {
target = findglb(bindname, sGLOBAL);
if (!target)
error(17, ident);
else if (target->ident != iFUNCTN)
error(10);
} else {
error(10);
}
if (!target)
return NULL;
if (is_dtor) {
// Make sure the dtor has the right name.
if (strcmp(ident, map->name) != 0)
error(114, spectype, map->name);
if (!(target->usage & uNATIVE)) {
// Must be a native.
error(118);
return NULL;
}
if (target->tag != 0 && target->tag != pc_tag_void) {
// Cannot return a value.
error(99);
return NULL;
}
if (target->dim.arglist[0].ident && target->dim.arglist[1].ident) {
// Cannot have extra arguments.
error(119);
return NULL;
}
// Make sure the final name includes the ~.
strcpy(ident, "~");
strcat(ident, map->name);
}
// Check that a method with this name doesn't already exist.
for (size_t i = 0; i < map->nummethods; i++) {
if (strcmp(map->methods[i]->name, ident) == 0) {
error(103, ident, spectype);
return NULL;
}
}
methodmap_method_t *method = (methodmap_method_t *)calloc(1, sizeof(methodmap_method_t));
strcpy(method->name, ident);
method->target = target;
if (is_dtor)
map->dtor = method;
// If the symbol is a constructor, we bypass the initial argument checks,
// and instead require that it returns something with the same tag.
if (strcmp(ident, map->name) == 0) {
if (target->tag != map->tag)
error(112, map->name);
define_constructor(map, method);
return method;
}
// Check the implicit this parameter. Currently we only allow scalars. As
// to not encourage enum-structs, we will not allow those either.
const arginfo *first_arg = &target->dim.arglist[0];
if (first_arg->ident == 0 ||
first_arg->ident != iVARIABLE ||
(first_arg->usage & uCONST) ||
first_arg->hasdefault ||
first_arg->numtags != 1)
{
free(method);
error(108, spectype, map->name);
return NULL;
}
// Ensure the methodmap tag is compatible with |this|.
int ok = 0;
for (methodmap_t *mapptr = map; mapptr; mapptr = mapptr->parent) {
if (first_arg->tags[0] == mapptr->tag) {
ok = 1;
break;
}
}
if (!ok)
error(108, spectype, map->name);
return method;
}
static int consume_line()
{
int val;
char *str;
// First check for EOF.
if (lex(&val, &str) == 0)
return FALSE;
lexpush();
while (!matchtoken(tTERM)) {
// Check for EOF.
if (lex(&val, &str) == 0)
return FALSE;
}
return TRUE;
}
/**
* domethodmap - declare a method map for OO-ish syntax.
*
*/
static void domethodmap(LayoutSpec spec)
{
int val;
char *str;
LayoutSpec old_spec;
methodmap_t *parent = NULL;
const char *spectype = layout_spec_name(spec);
// methodmap ::= "methodmap" symbol ("<" symbol)? "{" methodmap-body "}"
char mapname[sNAMEMAX + 1];
if (lex(&val, &str) != tSYMBOL)
error(93);
strcpy(mapname, str);
if (!isupper(*mapname))
error(109, spectype);
old_spec = deduce_layout_spec_by_name(mapname);
if (!can_redef_layout_spec(spec, old_spec))
error(110, mapname, layout_spec_name(old_spec));
if (matchtoken('<')) {
if (lex(&val, &str) != tSYMBOL) {
error(93);
return;
}
if ((parent = methodmap_find_by_name(str)) == NULL) {
error(102, str);
}
}
methodmap_t *map = (methodmap_t *)calloc(1, sizeof(methodmap_t));
map->parent = parent;
map->tag = pc_addtag(mapname);
map->spec = spec;
strcpy(map->name, mapname);
methodmap_add(map);
needtoken('{');
while (!matchtoken('}')) {
methodmap_method_t *method;
methodmap_method_t **methods;
if ((method = parse_method(map)) == NULL) {
if (!consume_line())
return;
continue;
}
needtoken(tTERM);
methods = (methodmap_method_t **)realloc(map->methods, sizeof(methodmap_method_t *) * (map->nummethods + 1));
if (!methods) {
error(123);
return;
}
map->methods = methods;
map->methods[map->nummethods++] = method;
}
needtoken(tTERM);
}
// delete ::= "delete" expr
static void dodelete()
{
int tag;
symbol *sym;
int ident = doexpr(TRUE, FALSE, TRUE, FALSE, &tag, &sym, TRUE);
needtoken(tTERM);
switch (ident) {
case iFUNCTN:
case iREFFUNC:
error(115, "functions");
return;
case iARRAY:
case iREFARRAY:
case iARRAYCELL:
case iARRAYCHAR:
error(115, "arrays");
return;
}
if (tag == 0) {
error(115, "primitive types or enums");
return;
}
methodmap_t *map = methodmap_find_by_tag(tag);
if (!map) {
error(115, pc_tagname(tag));
return;
}
if (!map->dtor) {
error(115, layout_spec_name(map->spec), map->name);
return;
}
// For some reason, we don't get a sysreq.n once this passes through the
// peephole optimizer. I can't tell why. -dvander
//
// push pri
// push.c 1
// sysreq.c N 1
// stack 8
pushreg(sPRI);
markexpr(sPARM,NULL,0);
{
pushval(1);
ffcall(map->dtor->target, NULL, 1);
map->dtor->target->usage |= uREAD;
}
markexpr(sEXPR,NULL,0);
}
/**
* dofuncenum - declare function enumerations
@ -3449,6 +3906,7 @@ static void decl_enum(int vclass)
cell increment,multiplier;
constvalue *enumroot;
symbol *enumsym;
LayoutSpec spec;
/* get an explicit tag, if any (we need to remember whether an explicit
* tag was passed, even if that explicit tag was "_:", so we cannot call
@ -3456,6 +3914,9 @@ static void decl_enum(int vclass)
*/
if (lex(&val,&str)==tLABEL) {
tag = pc_addtag(str);
spec = deduce_layout_spec_by_tag(tag);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, str, layout_spec_name(spec));
explicittag=TRUE;
} else {
lexpush();
@ -3466,8 +3927,16 @@ static void decl_enum(int vclass)
/* get optional enum name (also serves as a tag if no explicit tag was set) */
if (lex(&val,&str)==tSYMBOL) { /* read in (new) token */
strcpy(enumname,str); /* save enum name (last constant) */
if (!explicittag)
if (!explicittag) {
tag=pc_addtag(enumname);
spec = deduce_layout_spec_by_tag(tag);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, enumname, layout_spec_name(spec));
} else {
spec = deduce_layout_spec_by_name(enumname);
if (!can_redef_layout_spec(spec, Layout_Enum))
error(110, enumname, layout_spec_name(spec));
}
} else {
lexpush(); /* analyze again */
enumname[0]='\0';
@ -3997,7 +4466,7 @@ SC_FUNC char *funcdisplayname(char *dest,char *funcname)
return dest;
}
static void funcstub(int fnative)
static symbol *funcstub(int fnative)
{
int tok,tag,fpublic;
char *str;
@ -4022,7 +4491,7 @@ static void funcstub(int fnative)
*/
if (numdim == sDIMEN_MAX) {
error(53); /* exceeding maximum number of dimensions */
return;
return NULL;
} /* if */
size=needsub(&idxtag[numdim],NULL); /* get size; size==0 for "var[]" */
if (size==0)
@ -4050,12 +4519,12 @@ static void funcstub(int fnative)
if (tok==tOPERATOR) {
opertok=operatorname(symbolname);
if (opertok==0)
return; /* error message already given */
return NULL; /* error message already given */
check_operatortag(opertok,tag,symbolname);
} else {
if (tok!=tSYMBOL && freading) {
error(10); /* illegal function or declaration */
return;
return NULL;
} /* if */
strcpy(symbolname,str);
} /* if */
@ -4063,7 +4532,7 @@ static void funcstub(int fnative)
sym=fetchfunc(symbolname,tag);/* get a pointer to the function entry */
if (sym==NULL)
return;
return NULL;
if (fnative) {
sym->usage=(char)(uNATIVE | uRETVALUE | uDEFINE | (sym->usage & uPROTOTYPED));
sym->x.lib=curlibrary;
@ -4122,6 +4591,8 @@ static void funcstub(int fnative)
litidx=0; /* clear the literal pool */
delete_symbols(&loctab,0,TRUE,TRUE);/* clear local variables queue */
return sym;
}
/* newfunc - begin a function
@ -5364,6 +5835,9 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
error(203,sym->name); /* symbol isn't used: ... */
} /* if */
break;
case iPROXY:
// Ignore usage on proxies.
break;
default:
/* a variable */
if (sym->parent!=NULL)
@ -5651,6 +6125,10 @@ static void statement(int *lastindent,int allow_decl)
error(3); /* declaration only valid in a block */
} /* if */
break;
case tDELETE:
dodelete();
lastst=tDELETE;
break;
case tDECL:
if (allow_decl) {
autozero=0;

View File

@ -242,8 +242,6 @@ static void check_empty(const unsigned char *lptr)
static void doinclude(int silent)
{
char name[_MAX_PATH];
char symname[sNAMEMAX+1];
char *ptr;
char c;
int i, result;
@ -1927,9 +1925,10 @@ char *sc_tokens[] = {
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
"...", "..", "::",
"assert", "*begin", "break", "case", "cellsof", "chars", "const", "continue", "default",
"defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "functag", "goto",
"if", "native", "new", "decl", "operator", "public", "return", "sizeof",
"sleep", "static", "stock", "struct", "switch", "tagof", "*then", "while",
"defined", "delete", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum",
"functag", "goto",
"if", "int", "methodmap", "native", "new", "decl", "operator", "public", "return", "sizeof",
"sleep", "static", "stock", "struct", "switch", "tagof", "*then", "void", "while",
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
"#endscript", "#error", "#file", "#if", "#include", "#line", "#pragma",
"#tryinclude", "#undef",
@ -2611,6 +2610,29 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
constvalue *stateptr;
int mustdelete;
// Hack - proxies have a "target" pointer, but the target could be deleted
// already if done inside the main loop below. To get around this we do a
// precursor pass. Note that proxies can only be at the global scope.
if (origRoot == &glbtab) {
symbol *iter = root;
while (iter->next) {
sym = iter->next;
if (sym->ident != iPROXY) {
iter = sym;
continue;
}
if (delete_functions || (sym->target->usage & uNATIVE) != 0) {
RemoveFromHashTable(sp_Globals, sym);
iter->next = sym->next;
free_symbol(sym);
} else {
iter = sym;
}
}
}
/* erase only the symbols with a deeper nesting level than the
* specified nesting level */
while (root->next!=NULL) {
@ -2653,6 +2675,10 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
mustdelete=delete_functions || (sym->usage & uNATIVE)!=0;
assert(sym->parent==NULL);
break;
case iPROXY:
// Original loop determined it was okay to keep.
mustdelete=FALSE;
break;
case iARRAYCELL:
case iARRAYCHAR:
case iEXPRESSION:
@ -2831,6 +2857,10 @@ SC_FUNC symbol *findglb(const char *name,int filter)
*/
if (sym==NULL)
sym=FindInHashTable(sp_Globals,name,fcurrent);
if (sym && sym->ident == iPROXY)
return sym->target;
return sym;
}
@ -3012,3 +3042,18 @@ static char itohstr[30];
return itohstr;
}
SC_FUNC int lextok(token_t *tok)
{
tok->id = lex(&tok->val, &tok->str);
return tok->id;
}
SC_FUNC int expecttoken(int id, token_t *tok)
{
int rval = needtoken(id);
if (rval) {
tok->id = tokeninfo(&tok->val, &tok->str);
return rval;
}
return FALSE;
}

View File

@ -1,3 +1,4 @@
/* vim: set ts=8 sts=2 sw=2 tw=99 et: */
/* Pawn compiler - Recursive descend expresion parser
*
* Copyright (c) ITB CompuPhase, 1997-2005
@ -56,7 +57,7 @@ static int hier2(value *lval);
static int hier1(value *lval1);
static int primary(value *lval);
static void clear_value(value *lval);
static void callfunction(symbol *sym,value *lval_result,int matchparanthesis);
static void callfunction(symbol *sym, const svalue *implicitthis, value *lval_result, int matchparanthesis);
static int dbltest(void (*oper)(),value *lval1,value *lval2);
static int commutative(void (*oper)());
static int constant(value *lval);
@ -299,13 +300,13 @@ SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
SC_FUNC int checktag_string(value *sym1, value *sym2)
{
if (sym1->ident == iARRAY || sym2->ident == iARRAY
|| sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
if (sym1->ident == iARRAY || sym2->ident == iARRAY ||
sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
{
return FALSE;
}
if ((sym1->tag == pc_tag_string && sym2->tag == 0)
|| (sym1->tag == 0 && sym2->tag == pc_tag_string))
if ((sym1->tag == pc_tag_string && sym2->tag == 0) ||
(sym1->tag == 0 && sym2->tag == pc_tag_string))
{
return TRUE;
}
@ -322,22 +323,23 @@ SC_FUNC int matchtag_string(int ident, int tag)
SC_FUNC int matchtag(int formaltag, int actualtag, int allowcoerce)
{
if (formaltag != actualtag) {
if (formaltag == actualtag)
return TRUE;
/* if the formal tag is zero and the actual tag is not "fixed", the actual
* tag is "coerced" to zero
*/
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0) {
if (formaltag == pc_anytag || actualtag == pc_anytag)
{
if (allowcoerce && !formaltag && !(actualtag & FIXEDTAG))
return TRUE;
}
if (formaltag & FUNCTAG)
{
if (actualtag == pc_functag || (formaltag == pc_functag && actualtag & FUNCTAG))
{
if (formaltag == pc_anytag || actualtag == pc_anytag)
return TRUE;
} else if (actualtag & FUNCTAG) {
if (formaltag & FUNCTAG) {
if (actualtag == pc_functag || (formaltag == pc_functag && actualtag & FUNCTAG))
return TRUE;
if (actualtag & FUNCTAG) {
constvalue *v = find_tag_byval(actualtag);
int index;
short usage = uPUBLIC;
@ -346,16 +348,12 @@ SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
functag_t *t;
if (strncmp(v->name, "$Func", 5) != 0)
{
return FALSE;
}
/* Now we have to go about looking up each function in this enum. WHICH IS IT. */
e = funcenums_find_byval(formaltag);
if (!e)
{
return FALSE;
}
assert(v->name[5] == '@' || v->name[5] == '!');
@ -465,10 +463,8 @@ SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
}
}
if (skip)
{
break;
}
}
/* Lastly, check the tags */
if (enum_arg->tagcount != func_arg->numtags)
{
@ -485,27 +481,31 @@ SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
}
}
if (skip)
{
break;
}
}
if (!skip)
{
/* Make sure there are no trailing arguments */
if (sym->dim.arglist[curarg].ident == 0)
{
return TRUE;
}
}
t = t->next;
}
}
}
return FALSE;
}
} /* if */
// See if the tag has a methodmap associated with it. If so, see if the given
// tag is anywhere on the inheritance chain.
methodmap_t *map = methodmap_find_by_tag(actualtag);
if (map) {
for (; map; map = map->parent) {
if (map->tag == formaltag)
return TRUE;
}
}
return FALSE;
}
/*
* The AMX pseudo-processor has no direct support for logical (boolean)
@ -1812,7 +1812,7 @@ static int hier1(value *lval1)
cursym=lval1->sym;
restart:
sym=cursym;
if (matchtoken('[') || matchtoken('{') || matchtoken('(')) {
if (matchtoken('[') || matchtoken('{') || matchtoken('(') || matchtoken('.')) {
tok=tokeninfo(&val,&st); /* get token read by matchtoken() */
magic_string = (sym && (sym->tag == pc_tag_string && sym->dim.array.level == 0));
if (sym==NULL && symtok!=tSYMBOL) {
@ -1974,14 +1974,66 @@ restart:
lval1->tag=sym->tag;
lval1->constval=0;
} /* if */
// If there's a call coming up, keep parsing.
if (matchtoken('.')) {
lexpush();
goto restart;
}
/* a cell in an array is an lvalue, a character in an array is not
* always a *valid* lvalue */
return TRUE;
} else { /* tok=='(' -> function(...) */
svalue thisval;
thisval.val = *lval1;
thisval.lvalue = lvalue;
svalue *implicitthis = NULL;
if (tok == '.') {
methodmap_t *map;
/* Catch invalid calls early so we don't compile with a tag mismatch. */
switch (thisval.val.ident) {
case iARRAY:
case iREFARRAY:
error(106);
break;
case iFUNCTN:
case iREFFUNC:
error(107);
break;
}
if ((map = methodmap_find_by_tag(thisval.val.tag)) == NULL) {
error(104, pc_tagname(thisval.val.tag));
}
if (needtoken(tSYMBOL) && map) {
cell lexval;
char *lexstr;
methodmap_method_t *method;
tokeninfo(&lexval, &lexstr);
if ((method = methodmap_find_method(map, lexstr)) == NULL)
error(105, map->name, lexstr);
if (method) {
implicitthis = &thisval;
sym = method->target;
}
}
// If we don't find a '(' next, just fail to compile for now -- and
// don't even try to do a function call, just restart the parse loop.
if (!needtoken('('))
goto restart;
tok = '(';
}
assert(tok=='(');
if (sym==NULL
|| (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC))
{
if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC)) {
if (sym==NULL && sc_status==statFIRST) {
/* could be a "use before declaration"; in that case, create a stub
* function so that the usage can be marked.
@ -1998,14 +2050,14 @@ restart:
funcdisplayname(symname,sym->name);
error(4,symname); /* function not defined */
} /* if */
callfunction(sym,lval1,TRUE);
callfunction(sym,implicitthis,lval1,TRUE);
return FALSE; /* result of function call is no lvalue */
} /* if */
} /* if */
if (sym!=NULL && lval1->ident==iFUNCTN) {
assert(sym->ident==iFUNCTN);
if (sc_allowproccall) {
callfunction(sym,lval1,FALSE);
callfunction(sym,NULL,lval1,FALSE);
} else if ((sym->usage & uNATIVE) != uNATIVE) {
symbol *oldsym=sym;
int n=-1,iter=0;
@ -2243,7 +2295,7 @@ enum {
* Generates code to call a function. This routine handles default arguments
* and positional as well as named parameters.
*/
static void callfunction(symbol *sym,value *lval_result,int matchparanthesis)
static void callfunction(symbol *sym, const svalue *implicitthis, value *lval_result, int matchparanthesis)
{
static long nest_stkusage=0L;
static int nesting=0;
@ -2261,6 +2313,7 @@ static int nesting=0;
symbol *symret;
cell lexval;
char *lexstr;
int pending_this = (implicitthis ? TRUE : FALSE);
assert(sym!=NULL);
lval_result->ident=iEXPRESSION; /* preset, may be changed later */
@ -2321,9 +2374,9 @@ static int nesting=0;
lexpush(); /* reset the '.' */
} /* if */
} /* if */
if (!close) {
if (pending_this || !close) {
do {
if (matchtoken('.')) {
if (!pending_this && matchtoken('.')) {
namedparams=TRUE;
if (needtoken(tSYMBOL))
tokeninfo(&lexval,&lexstr);
@ -2350,7 +2403,7 @@ static int nesting=0;
stgmark((char)(sEXPRSTART+argpos));/* mark beginning of new expression in stage */
if (arglist[argpos]!=ARG_UNHANDLED)
error(58); /* argument already set */
if (matchtoken('_')) {
if (!pending_this && matchtoken('_')) {
arglist[argpos]=ARG_IGNORED; /* flag argument as "present, but ignored" */
if (arg[argidx].ident==0 || arg[argidx].ident==iVARARGS) {
error(92); /* argument count mismatch */
@ -2368,7 +2421,12 @@ static int nesting=0;
arglist[argpos]=ARG_DONE; /* flag argument as "present" */
if (arg[argidx].ident!=0 && arg[argidx].numtags==1) /* set the expected tag, if any */
lval.cmptag=arg[argidx].tags[0];
if (pending_this) {
lval = implicitthis->val;
lvalue = implicitthis->lvalue;
} else {
lvalue = hier14(&lval);
}
assert(sc_status==statFIRST || arg[argidx].ident == 0 || arg[argidx].tags!=NULL);
switch (arg[argidx].ident) {
case 0:
@ -2428,8 +2486,8 @@ static int nesting=0;
/* otherwise, the expression result is already in PRI */
assert(arg[argidx].numtags>0);
check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
&& !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval) &&
!checktag(arg[argidx].tags, arg[argidx].numtags, lval.tag))
{
if (arg[argidx].numtags == 1 && arg[argidx].tags[0] & FUNCTAG)
error(100); /* error - function prototypes do not match */
@ -2547,18 +2605,32 @@ static int nesting=0;
} /* if */
assert(arglist[argpos]!=ARG_UNHANDLED);
nargs++;
/**
* We can already have decided it was time to close because of pending_this.
* If that's the case, then bail out now.
*/
if (pending_this && close) {
pending_this = FALSE;
break;
}
if (matchparanthesis) {
close=matchtoken(')');
if (!close) /* if not paranthese... */
if (!needtoken(',')) /* ...should be comma... */
/* Not expecting comma if the first argument was implicit. */
if (!pending_this && !needtoken(','))
break; /* ...but abort loop if neither */
} else {
close=!matchtoken(',');
/* Not expecting comma if the first argument was implicit. */
close = (!pending_this && !matchtoken(','));
if (close) { /* if not comma... */
if (needtoken(tTERM)==1)/* ...must be end of statement */
lexpush(); /* push again, because end of statement is analised later */
} /* if */
} /* if */
pending_this = FALSE;
} while (!close && freading && !matchtoken(tENDEXPR)); /* do */
} /* if */
/* check remaining function arguments (they may have default values) */

View File

@ -53,7 +53,7 @@ static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char *
static int errflag;
static int errstart; /* line number at which the instruction started */
static int errline; /* forced line number for the error message */
static int sErrLine; /* forced line number for the error message */
/* error
*
@ -75,6 +75,12 @@ static short lastfile;
char *msg,*pre;
va_list argptr;
// sErrLine is used to temporarily change the line number of reported errors.
// Pawn has an upstream bug where this is not reset on early-return, which
// can lead to broken line numbers in error messages.
int errline = sErrLine;
sErrLine = -1;
/* errflag is reset on each semicolon.
* In a two-pass compiler, an error should not be reported twice. Therefore
* the error reporting is enabled only in the second pass (and only when
@ -148,7 +154,6 @@ static short lastfile;
longjmp(errbuf,2); /* fatal error, quit */
} /* if */
errline=-1;
/* check whether we are seeing many errors on the same line */
if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
errorcount=0;
@ -176,10 +181,10 @@ SC_FUNC void errorset(int code,int line)
break;
case sEXPRRELEASE:
errstart=-1; /* forget start line number */
errline=-1;
sErrLine=-1;
break;
case sSETPOS:
errline=line;
sErrLine=line;
break;
} /* switch */
}

View File

@ -23,22 +23,27 @@
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
#ifndef SCPACK
# define SCPACK
# define SCPACK_PUSH
#endif
#define SCPACK_TABLE errstr_table
/*-*SCPACK start of pair table, do not change or remove this line */
unsigned char errstr_table[][2] = {
{101,32}, {111,110}, {116,32}, {105,110}, {97,114}, {115,32}, {116,105}, {100,32}, {101,114}, {37,115}, {101,110}, {134,129}, {34,137}, {140,34}, {97,108}, {117,110},
{114,101}, {110,111}, {97,116}, {115,105}, {121,32}, {97,110}, {111,114}, {109,98}, {115,116}, {32,141}, {100,101}, {41,10}, {109,138}, {145,130}, {101,135}, {139,32},
{98,108}, {111,108}, {114,97}, {143,99}, {118,142}, {102,163}, {115,121}, {166,151}, {167,161}, {97,32}, {117,115}, {103,32}, {115,147}, {132,162}, {97,160}, {136,32},
{150,32}, {99,104}, {103,117}, {105,135}, {178,156}, {164,179}, {132,180}, {111,102}, {116,104}, {101,120}, {165,159}, {131,181}, {101,100}, {101,133}, {105,133}, {168,153},
{154,102}, {118,132}, {183,32}, {105,174}, {193,195}, {116,111}, {173,148}, {109,97}, {99,129}, {101,10}, {115,10}, {112,144}, {116,97}, {182,130}, {98,128}, {152,146},
{44,32}, {132,97}, {192,131}, {170,130}, {153,10}, {109,146}, {191,155}, {109,211}, {40,214}, {104,97}, {196,128}, {34,32}, {129,32}, {142,32}, {105,99}, {117,108},
{99,111}, {147,122}, {110,32}, {100,105}, {101,108}, {108,111}, {111,112}, {116,136}, {200,152}, {131,32}, {149,32}, {131,171}, {213,177}, {58,212}, {109,101}, {102,105},
{100,111}, {97,115}, {108,128}, {118,128}, {230,136}, {232,149}, {204,171}, {203,172}, {215,206}, {119,105}, {109,112}, {110,117}, {185,247}, {165,139}, {251,151}
{101,32}, {116,32}, {111,110}, {105,110}, {115,32}, {97,114}, {100,32}, {116,105}, {37,115}, {101,114}, {101,110}, {97,108}, {135,130}, {110,111}, {34,136}, {142,34},
{117,110}, {114,101}, {111,114}, {97,110}, {121,32}, {115,116}, {100,101}, {115,105}, {97,116}, {141,129}, {32,143}, {109,98}, {109,138}, {41,10}, {101,134}, {140,32},
{116,104}, {98,108}, {144,99}, {102,162}, {114,97}, {111,108}, {117,115}, {146,32}, {118,139}, {97,32}, {115,121}, {170,155}, {171,165}, {103,32}, {137,32}, {103,117},
{101,120}, {175,156}, {133,164}, {133,177}, {102,131}, {105,134}, {115,151}, {97,161}, {99,104}, {163,159}, {168,181}, {111,102}, {105,132}, {115,10}, {131,186}, {101,100},
{166,129}, {101,132}, {172,154}, {109,192}, {98,128}, {99,130}, {118,133}, {99,147}, {187,32}, {105,183}, {198,201}, {104,97}, {109,97}, {116,111}, {112,145}, {178,148},
{199,153}, {150,180}, {116,97}, {109,101}, {99,116}, {179,129}, {130,32}, {133,97}, {149,152}, {44,32}, {102,105}, {118,128}, {154,10}, {101,10}, {109,152}, {194,157},
{110,32}, {40,223}, {100,105}, {119,105}, {117,108}, {99,111}, {97,115}, {202,128}, {136,10}, {197,149}, {34,32}, {139,32}, {151,122}, {98,101}, {108,111}, {111,112},
{108,128}, {163,140}, {102,146}, {131,32}, {147,32}, {160,32}, {210,173}, {131,173}, {222,184}, {195,196}, {203,219}, {58,220}, {100,111}, {109,112}, {160,128}
};
/*-*SCPACK end of pair table, do not change or remove this line */
static char *errmsg[] = {
#if 1
#ifdef SCPACK
/*001*/ "expected token: \"%s\", but found \"%s\"\n",
/*002*/ "only a single statement (or expression) can follow each \"case\"\n",
/*003*/ "declaration of a local variable must appear in a compound block\n",
@ -136,116 +141,153 @@ static char *errmsg[] = {
/*095*/ "cannot have required parameters after optional parameters\n",
/*096*/ "could not find member \"%s\" in struct \"%s\"\n",
/*097*/ "symbol \"%s\" does not have a matching type\n",
/*098*/ "struct requires unique struct name\n",
/*099*/ "member \"%s\" appears more than once in struct \"%s\"\n",
/*098*/ "type \"%s\" should be \"%s\" in new-style declarations\n",
/*099*/ "destructors cannot return values\n",
/*100*/ "function prototypes do not match\n",
/*101*/ "specify either all dimensions or only the last dimension\n"
/*101*/ "specify either all dimensions or only the last dimension\n",
/*102*/ "cannot find %s %s\n",
/*103*/ "%s was already defined on this %s\n",
/*104*/ "cannot find any methods for %s\n",
/*105*/ "cannot find method %s.%s\n",
/*106*/ "cannot call methods on an array\n",
/*107*/ "cannot call methods on a function\n",
/*108*/ "method must have a first argument compatible with the %s type (%s)\n",
/*109*/ "%s name must start with an uppercase letter\n",
/*110*/ "%s has already been defined (previously seen as %s)\n",
/*111*/ "expected identifier - did you forget a type?\n",
/*112*/ "constructor function must return tag %s\n",
/*113*/ "cannot define constructor for \"%s\"; already exists as a %s\n",
/*114*/ "destructor must have the same name as %s \"%s\"\n",
/*115*/ "delete cannot be used with %s\n",
/*116*/ "no methodmap or class was found for %s\n",
/*117*/ "no destructor was found for %s %s\n",
/*118*/ "destructors must be native functions\n",
/*119*/ "destructors cannot have extra arguments\n",
#else
"\271pect\236\305k\212:\231\320bu\202fo\217\207\215\012",
"\201l\224\251s\203g\362\317e\234\202(\260\374\201) c\352f\241\345w ea\261 \042c\361e\042\012",
"\232cl\321\237\302\251\345c\335\332\327appe\204 \351\251\340\372o\217\207\240ock\012",
"\375\231 \276\235i\372le\234t\274\012",
"\272\307\224\235\331\363\266t\312",
"\370a\254gn\236\305 \352\255y\012",
"\364\222\260c\225\235\316\220\322\274\012",
"\370\251\365\202\374\201; \361sum\236z\210o\012",
"\273\306\341\200(nega\206ve\320z\210o \260ou\202\302bo\217ds\233",
"\273\272\260\232cl\321\213\012",
"\273out\223d\200\375\312",
"\273\272c\216l\320\235\251\265add\220s\312",
"\221 \212tr\224po\203\202(\221 pu\240\336 \375s\233",
"\273\317e\234t; \235\351s\371t\261\012",
"\042\300a\337t\333c\361\200\370\270\200l\361\202c\361\200\351s\371t\261 \317e\234t\012",
"m\337\206p\362\300a\337t\205\351\042s\371t\261\042\012",
"\217\322\236\277\012",
"\203i\206\216iza\237d\222\251\271ce\274\205\232cl\204\236\341\311",
"\235\251lab\344\355",
"\273\250 nam\200\215\012",
"\250 \216\220ad\224\322\274\355",
"\370l\244u\200(n\201-\365t\233",
"\306a\254gn\234\202\370\223\372\362a\254gn\234t\012",
"\042b\220ak\333\260\042\310t\203ue\333\276ou\202\302\310t\271t\012",
"\272head\353\343ff\210\205from pro\305typ\311",
"\221 \354\353\042#if...\042\012",
"\273\261\321ct\257\365t\012",
"\273subscrip\202(\235\352\306\260\305o m\225\224subscripts)\355",
"\273\374\201\320\361sum\236z\210o\012",
"\340\372o\217\207\317e\234\202\235c\345s\236a\202\270\200\212\207\302\357\362(\230\204t\236a\202l\203\200%d\233",
"\217k\221w\342\343\220c\206v\311",
"\306\203\232x ou\202\302bo\217d\205(\332\215\233",
"\306\370\203\232x\236(\332\215\233",
"\315\360\275\235\331\363\251\300a\337\202\244u\200(\315%d\233",
"\315typ\200mis\354 (\315%d\233",
"e\372t\224\317e\234t\012",
"\273\230r\353(po\254\240\224n\201-\347m\203\222\236\230r\203g\233",
"\271t\242 \261\321c\347\205\334l\203\311",
"\365\202\250 \331\205\221 \341\311",
"dupl\336\222\200\042c\361e\333lab\344 (\244u\200%d\233",
"\273\344lip\223s\320\306\341\200\276\235k\221wn\012",
"\273\340\227\203a\237\302cl\361\205speci\357\210\312",
"\261\321ct\257\365\202\271ce\274\205r\225g\200f\260pack\236\230r\203g\012",
"po\223\213\335p\321\356\347\205\327\313c\274\200\216l nam\236p\321\356\347\312",
"\305o m\225\224\272\266t\312",
"\217k\221w\342\306\341\200(\332\215\233",
"\306\341\275\360 \235\354\320\260\232\230\203a\237\306\276\305o sm\216l\012",
"\306(\205\360 \235\354\012",
"\273l\203\200\310t\203ua\213\012",
"\273r\225g\311",
"\273subscript\320\252\200\042[ ]\333\364\222\226\205\334\307j\260\343\234\223\201\312",
"m\337\206-\343\234\223\201\335\255y\205\370f\337l\224\203i\206\216iz\274\012",
"\271ce\274\353\307ximum \376\257\302\343\234\223\201\312",
"\217\354\236c\345s\353b\242c\200(\042}\042\233",
"\230\204\202\302\272bod\224\371\270ou\202\272head\210\012",
"\255ys\320\345c\335\304\275\225\207\272\266t\205c\225\235\316pu\240\336 (\332\215\233",
"\217f\203ish\236\374\334bef\226\200\340\372il\257\343\220c\206v\311",
"dupl\336\222\200\266t; sam\200\315\276p\361s\236tw\336\311",
"\272\315\307\224\235\331\363\251\300a\337\202\244u\200(\332\215\233",
"m\337\206p\362\042#\344se\333\343\220c\206v\275betwe\212 \042#if ... #\212\343f\042\012",
"\042#\344seif\333\343\220c\206\363f\241\345w\205\352\042#\344se\333\343\220c\206v\311",
"\376\257\302\364\225d\205\360\275\235\357\202\270\200\364\222\226\012",
"\272\220s\337\202\366\302\364\222\226\231 \370\215\012",
"c\225\235\261\225g\200\313\322\236\364\222\226\312",
"\272\315\307\224\201l\224\331\363\251s\203g\362\366(\315%d\233",
"\272\315\307\224\235\316\251\220f\210\212c\200\315\260\352\306(\315\215\233",
"\332c\225\235\316bo\270 \251\220f\210\212c\200\225\207\352\306(\332\215\233",
"\273\242\213\335\376\257\313ci\223\334\351#p\242g\307\012",
"\242\213\335\376\257f\226\307\202\216\220ad\224\322\274\012",
"\242\213\335\376\257supp\226\202wa\205\235\212\256\274\012",
"\252\210-\322\236\364\222\260\370\232cl\204\236bef\226\200\252\200(\375\231\233",
"\042\341e\267\333\364\222\260\276\273\334\042\375\333\250\312",
"\272\315\370\352\306(\315\215\233",
"#\322\200p\222\347\342\327\230\204\202\371\270 \352\216p\331be\206c \261\321c\347\012",
"\203pu\202l\203\200\305o l\201\253(aft\257subs\206tu\213s\233",
"\246n\314x \210r\260\351\270\200\374\201\320\260\273\272c\216l\012",
"m\216f\226m\236UTF-8 \212\340d\203g\320\260c\226rupt\236\357le: \211\012",
"\272\252\275bo\270 \042\220turn\333\225\207\042\220tur\342<\244ue>\042\012",
"\203\310\223\230\212\202\220tur\342typ\275(\306& n\201-\255y\233",
"\217k\221w\342\250\320\260\235\251\365\202\250 \330",
"c\225\235\314k\200\251\366a\205\251\300a\337\202\244u\200f\260\352\203\232x\236\306p\321\356t\257\330",
"\252\210-\322\236\364\222\226\205\225\207na\206\363\375\205\307\224\235\331\363\317e\312",
"\251\272\260\332\307\224\201l\224b\344\201\253\305 \251s\203g\362au\305\325\334\330",
"\317\200\310fl\336t: \201\200\302\270\200\317\275\276\216\220ad\224a\254gn\236\305 a\221\270\257i\372le\234\314\237\330",
"\221 \317\275\204\200\322\236f\260\277\012",
"\217k\221w\342au\305\325\201\324",
"\217k\221w\342\317\200\215 f\260au\305\325\201\324",
"pu\240\336 \304\275\225\207\345c\335\304\275\307\224\235\331\363\317\275\330",
"\317\200\304\275\307\224\235\316\203i\206\216iz\236\330",
"pu\240\336 \375\205\307\224\235\220tur\342\255y\205\330",
"a\227i\262ou\205\365t; \366ov\210rid\200\276\220qui\220\207\330",
"\376\257\302\266t\205\360\275\235\354 \322i\213\012",
"\271pect\236\366nam\200id\212\206\357\210\012",
"\272\212um\210a\237\220qui\220\205\217iqu\200\314g\012",
"c\225\235\331\363\220qui\220\207p\321\356\347\205aft\257\346\213\335p\321\356\347\312",
"\340\337\207\235f\203\207\356\227\210\231 \351\230ruc\202\215\012",
"\277 \360\275\235\331\363\251\354\353typ\311",
"\230ruc\202\220qui\220\205\217iqu\200\230ruc\202nam\311",
"\356\227\210\231 appe\204\205m\226\200\270\352\201c\200\351\230ruc\202\215\012",
"\272pro\305typ\275\360 \235\354\012"
"\260pe\324\236\315k\212:\232\331bu\201fo\220\206\217\012",
"\202l\224\251s\203g\360\330e\234\201(\247\260\316\266\202) \307 f\245\356w ea\270 \042c\346e\042\012",
"\226cl\327\237\310\251\356c\353\347\303appe\205 \363\251\345\375o\220\206\241ock\012",
"\361\232 \274\231i\375le\234t\277\012",
"\271\314\224\231\372\263t\275",
"\371a\266gn\236\315 \364\262y\012",
"\357\211\230\247\320\304\221\321\277\012",
"\371\251\351\223\201\260\316\266\202; \346sum\236z\211o\012",
"\276\317\354\200(nega\207ve\331z\211o \247ou\201\310bo\220ds\235",
"\276\271\247\226cl\327\214\012",
"\276out\227d\200\361\275",
"\276\271c\213l\331\231\251\272add\221s\275",
"\215 \212tr\224po\203\201(\215 pu\241ic \361s\235",
"\276\330e\234t; \231\363s\343t\270\012",
"\042\226fa\344t\352c\346\200\371\376l\346\201c\346\200\363s\343t\270 \330e\234t\012",
"m\344\207p\360\226fa\344t\204\363\042s\343t\270\042\012",
"\220\321\236\302\012",
"\203i\207\213iza\237d\230\251\260ce\277\204\226cl\205\236\354\335",
"\231\251la\355l\373",
"\276\254 nam\200\217\012",
"\254 \213\221ad\224\321\277\373",
"\371l\250u\200(n\202-\351\223t\235",
"\317a\266gn\234\201\371\227\375\360a\266gn\234t\012",
"\042b\221ak\352\247\042\305t\203ue\352\274ou\201\310\305t\260t\012",
"\271head\367\342ff\211\204from pro\315typ\335",
"\215 \370\367\042#if...\042\012",
"\276\270\327\324\256\351\223t\012",
"\276subscrip\201(\231\364\317\247\315o m\223\224subscripts)\373",
"\276\260\316\266\202\331\346sum\236z\211o\012",
"\345\375o\220\206\330e\234\201\231c\356s\236a\201\376\212\206\310\332\360(\225\205t\236a\201l\203\200%d\235",
"\220k\215w\340\342\221c\207v\335",
"\317\203\226x ou\201\310bo\220d\204(\347\217\235",
"\317\371\203\226x\236(\347\217\235",
"\325\374\301\231\372\251\226fa\344\201\250u\200(\325%d\235",
"\325typ\200mis\370 (\325%d\235",
"e\375t\224\330e\234t\012",
"\276\225r\367(po\266\241\224n\202-t\211m\203\230\236\225r\203g\235",
"\260t\244 \270\327\324\211\204\326l\203\335",
"\351\223\201\254 \313\204\215 \354\335",
"duplic\230\200\042c\346e\352la\355l (\250u\200%d\235",
"\276ellip\227s\331\317\354\200\274\231k\215wn\012",
"\276\345\233\203a\237\310cl\346\204speci\332\211\275",
"\270\327\324\256\351\223\201\260ce\277\204r\223g\200f\247pack\236\225r\203g\012",
"po\227\214\353p\327\323t\211\204\303\316c\277\200\213l nam\236p\327\323t\211\275",
"\315o m\223\224\271\263t\275",
"\220k\215w\340\317\354\200(\347\217\235",
"\317\354\301\374 \231\370\331\247\226\225\203a\237\317\274\315o sm\213l\012",
"\317(\204\374 \231\370\012",
"\276l\203\200\305t\203ua\214\012",
"\276r\223g\335",
"\276subscript\331\246\200\042[ ]\352\357\211\230\222\204\326\314j\247\342\234\227\202\275",
"m\344\207-\342\234\227\202\353\262y\204\371f\344l\224\203i\207\213iz\277\012",
"\260ce\277\367\314ximum nu\233\256\310\342\234\227\202\275",
"\220\370\236c\356s\367b\244c\200(\042}\042\235",
"\225\205\201\310\271bod\224\343\240ou\201\271head\211\012",
"\262ys\331\356c\353\312\301\223\206\271\263t\204\320\304pu\241ic (\347\217\235",
"\220\264ish\236\260\316\266\326\355\362\200\345\375il\256\342\221c\207v\335",
"duplic\230\200\263t; sam\200\325\274p\346s\236t\343c\335",
"\271\325\314\224\231\372\251\226fa\344\201\250u\200(\347\217\235",
"m\344\207p\360\042#else\352\342\221c\207v\301\355twe\212 \042#if ... #\212\342f\042\012",
"\042#elseif\352\342\221c\207\333f\245\356w\204\364\042#else\352\342\221c\207v\335",
"nu\233\256\310\357\211\223d\204\374\301\231\332\201\376\357\211\230\222\012",
"\271\221s\344\201\366\310\357\211\230\222\232 \371\217\012",
"\320\270\223g\200\316\321\236\357\211\230\222\275",
"\271\325\314\224\202l\224\372\251s\203g\360\366(\325%d\235",
"\271\325\314\224\231\304\251\221f\211\212c\200\325\247\364\317(\325\217\235",
"\347\320\304bo\365\251\221f\211\212c\200\223\206\364\317(\347\217\235",
"\276\244\214\353nu\233\256\316ci\227\326\363#p\244g\314\012",
"\244\214\353nu\233\256\362\314\201\213\221ad\224\321\277\012",
"\244\214\353nu\233\256supp\222\201wa\204\231\212\267\277\012",
"\246\211-\321\236\357\211\230\247\371\226cl\205\236\355\362\200\246\200(\361\232\235",
"\042\354e\273\352\357\211\230\247\274\276\326\042\361\352\254\275",
"\271\325\371\364\317(\325\217\235",
"#\321\200p\230t\211\340\303\225\205\201\343\365\364\213p\313\355\207c \270\327\324\211\012",
"\203pu\201l\203\200\315o l\202\255(aft\256subs\207tu\214s\235",
"\252n\322x \211r\247\363\376\260\316\266\202\331\247\276\271c\213l\012",
"m\213\362m\236UTF-8 \212\345d\203g\331\247c\222rupt\236\332le: \350",
"\271\246\301bo\365\042\221turn\352\223\206\042\221tur\340<\250ue>\042\012",
"\203\305\227\225\212\201\221tur\340typ\301(\317& n\202-\262y\235",
"\220k\215w\340\254\331\247\231\251\351\223\201\254 \341",
"\320\322k\200\251\366a\204\251\226fa\344\201\250u\200f\247\364\203\226x\236\317p\327\323t\256\341",
"\246\211-\321\236\357\211\230\222\204\223\206na\207\333\361\204\314\224\231\372\330e\275",
"\251\271\247\347\314\224\202l\224\355l\202\255\315 \251s\203g\360au\315\336\326\341",
"\330\200\305fli\324: \202\200\310\376\330\301\274\213\221ad\224a\266gn\236\315 a\215\240\256i\375le\234\322\237\341",
"\215 \330\301\205\200\321\236f\247\302\012",
"\220k\215w\340au\315\336\202\334",
"\220k\215w\340\330\200\217 f\247au\315\336\202\334",
"pu\241ic \312\301\223\206\356c\353\312\301\314\224\231\372\330\301\341",
"\330\200\312\301\314\224\231\304\203i\207\213iz\236\341",
"pu\241ic \361\204\314\224\231\221tur\340\262y\204\341",
"a\233i\257ou\204\351\223t; \366ov\211rid\200\274\221qui\221\206\341",
"nu\233\256\310\263t\204\374\301\231\370 \321i\214\012",
"\260pe\324\236\366nam\200id\212\207\332\211\012",
"\271\212um\211a\237\221qui\221\204\220iqu\200\322g\012",
"\320\372\221qui\221\206p\327\323t\211\204aft\256\357\214\353p\327\323t\211\275",
"\345\344\206\231\264\206\323\233\211\232 \363\225ruc\201\217\012",
"\302 \374\301\231\372\251\370\367typ\335",
"typ\200\217 sho\344\206\304\217 \363new-\225y\360\226cl\327\214\275",
"\226\225ru\324\222\204\320\221tur\340\250ue\275",
"\271pro\315typ\301\374 \231\370\012",
"specif\224ei\240\256\213l \342\234\227\202\204\247\202l\224\376l\346\201\342\234\227\202\012",
"\320\264\206%\204\350",
"%\204wa\204\213\221ad\224\321\236\326\240\274\350",
"\320\264\206\223\224\323\240od\204f\247\350",
"\320\264\206\323\240o\206\210.\350",
"\320c\213l \323\240od\204\326\364\262y\012",
"\320c\213l \323\240od\204\326\251\361\012",
"\323\240o\206\303\372\251\332rs\201\325\345\375a\207\241\200\343\365\376%\204typ\200(\210\235",
"%\204nam\200\303\225\205\201\343\365\364upp\211c\346\200lett\211\012",
"%\204\313\204\213\221ad\224\355\212 \321\236(\316vio\246l\224se\212 a\204\210\235",
"\260pe\324\236id\212\207\332\256- d\265you \362ge\201\251type?\012",
"\351ru\324\247\271\303\221tur\340\366\350",
"\320\321\200\351ru\324\247\362\232; \213\221ad\224\260i\225\204a\204\251\350",
"\226\225ru\324\247\303\372\376sam\200nam\200a\204%\204\217\012",
"\226let\200\320\304\246\236\343\365\350",
"\215 \323\240od\314p \247cl\346\204wa\204fo\220\206f\247\350",
"\215 \226\225ru\324\247wa\204fo\220\206f\247%\204\350",
"\226\225ru\324\222\204\371na\207\333\361\275",
"\226\225ru\324\222\204\320\372\260t\244 \263t\275"
#endif
};
static char *fatalmsg[] = {
#if 1
#ifdef SCPACK
/*120*/ "cannot read from file: \"%s\"\n",
/*121*/ "cannot write to file: \"%s\"\n",
/*122*/ "table overflow: \"%s\"\n",
@ -265,23 +307,23 @@ static char *fatalmsg[] = {
/*130*/ "assertion failed: %s\n",
/*131*/ "user error: %s\n",
#else
"c\225\235\220a\207from \357le\355",
"c\225\235writ\200\305 \357le\355",
"t\256\200ov\210f\345w\355",
"\203suff\336i\212\202\356m\226y\012",
"\273\361se\227l\257\203\230ruc\213\324",
"\373m\210\336 ov\210f\345w\320\271ce\274\353capacity\012",
"\340\372il\236scrip\202\271ce\274\205\270\200\307ximum \356m\226\224\341\200(%l\207bytes\233",
"\305o m\225\224\210r\260\356ssag\275\334\201\200l\203\311",
"\340\232pag\200\307pp\353\357\362\235fo\217d\012",
"\273p\222h\355",
"\361s\210\237fail\274: \211\012",
"\252\257\210r\226: \211\012"
"\320\221a\206from \332le\373",
"\320writ\200\315 \332le\373",
"t\267\200ov\211f\356w\373",
"\203suf\332ci\212\201\323m\222y\012",
"\276\346se\233l\256\203\225ruc\214\334",
"num\211ic ov\211f\356w\331\260ce\277\367capacity\012",
"\345\375il\236scrip\201\260ce\277\204\376\314ximum \323m\222\224\354\200(%l\206bytes\235",
"\315o m\223\224\211r\247\323ssag\301\326\202\200l\203\335",
"\345\226pag\200\314pp\367\332\360\231fo\220d\012",
"\276p\230h\373",
"\346s\211\237fail\277: \350",
"\246\256\211r\222: \350"
#endif
};
static char *warnmsg[] = {
#if 1
#ifdef SCPACK
/*200*/ "symbol \"%s\" is truncated to %d characters\n",
/*201*/ "redefinition of constant/macro (symbol \"%s\")\n",
/*202*/ "number of arguments does not match definition\n",
@ -320,42 +362,46 @@ static char *warnmsg[] = {
/*235*/ "public function lacks forward declaration (symbol \"%s\")\n",
/*236*/ "unknown parameter in substitution (incorrect #define pattern)\n"
#else
"\277 \276tr\243\222\236\305 %\207\261\321c\347\312",
"\220\322i\237\302\365t/\307cro \330",
"\376\257\302\266t\205\360\275\235\354 \322i\213\012",
"\250 \276nev\257\252\274\355",
"\250 \276a\254gn\236\251\244u\200\270a\202\276nev\257\252\274\355",
"\220d\217d\225\202\340\232: \365\202\374\334\276z\210o\012",
"\220d\217d\225\202te\230: \365\202\374\334\276n\201-z\210o\012",
"\217k\221w\342#p\242g\307\012",
"\272\371\270 \366\220s\337\202\252\236bef\226\200\322i\213\320f\226c\353\220p\204s\311",
"\375\231 sho\337\207\220tur\342\251\244u\311",
"po\254\240\200\252\200\302\250 bef\226\200\203i\206\216iza\213\355",
"po\254\240\224\217\203t\212\232\207a\254gn\234t\012",
"po\254\240\224\217\203t\212\232\207bit\371s\200\364a\213\012",
"\366mis\354\012",
"po\254\240\224\251\042\350\333\306\315wa\205\203t\212\232d\355",
"\374\334\331\205\221 effect\012",
"ne\230\236\340m\234t\012",
"\345os\200\203d\212\314\213\012",
"\241\207\230y\362pro\305typ\275\252\236\371\270 \346\213\335sem\336\241umn\312",
"\345c\335\332\215 s\331\360w\205\251\332a\202\251\313c\274\353lev\344\012",
"\374\334\371\270 \366ov\210rid\200\327appe\204 betwe\212 p\204\212\270ese\312",
"lab\344 nam\200\215 s\331\360w\205\366nam\311",
"\376\257\302\343git\205\271ce\274\205\242\213\335\376\257\313ci\223\201\012",
"\220d\217d\225\202\042\341e\267\042: \315\341\200\276\216way\2051 \330",
"\203\232\347m\203\222\200\306\341\200\351\042\341e\267\333\374\334\330",
"\217\220a\261\256\200\340\232\012",
"\251\332\276a\254gn\236\305 its\344f \330",
"m\226\200\203i\206\216iz\210\205\270\352\212um \357\344d\312",
"l\212g\270 \302\203i\206\216iz\257\271ce\274\205\341\200\302\270\200\212um \357\344d\012",
"\203\232x \366mis\354 \330",
"\221 i\372le\234\314\237f\260\317\200\215 \351\375\231\320\221 f\216l-back\012",
"\317\200specif\336a\237\334f\226w\204\207\232cl\321\237\276ig\221\220d\012",
"outpu\202\357\362\276writt\212\320bu\202\371\270 \340\372ac\202\212\340d\353\343s\256\274\012",
"\317\200\332\215 s\331\360w\205\251g\345b\335\304\311",
"\277 \276m\204k\236a\205\232\313c\222\274: \211\012",
"pu\240\336 \272lack\205f\226w\204\207\232cl\321\237\330",
"\217k\221w\342p\321\356t\257\351subs\206tu\237(\203c\226\220c\202#\322\200p\222\347n\233"
"\302 \274tr\242\230\236\315 %\206\270\327\324\211\275",
"\221\321i\237\310\351\223t/\314cro \341",
"nu\233\256\310\263t\204\374\301\231\370 \321i\214\012",
"\254 \274nev\256\246\277\373",
"\254 \274a\266gn\236\251\250u\200\240a\201\274nev\256\246\277\373",
"\221d\220d\223\201\345\226: \351\223\201\260\316\266\326\274z\211o\012",
"\221d\220d\223\201te\225: \351\223\201\260\316\266\326\274n\202-z\211o\012",
"\220k\215w\340#p\244g\314\012",
"\271\343\365\366\221s\344\201\246\236\355\362\200\321i\214\331\362c\367\221p\205s\335",
"\361\232 sho\344\206\221tur\340\251\250u\335",
"po\266\241\200\246\200\310\254 \355\362\200\203i\207\213iza\214\373",
"po\266\241\224\220\203t\212\226\206a\266gn\234t\012",
"po\266\241\224\220\203t\212\226\206bit\343s\200\357\211a\214\012",
"\366mis\370\012",
"po\266\241\224\251\042\351\352\317\325wa\204\203t\212\226d\373",
"\260\316\266\326\313\204\215 effe\324\012",
"ne\225\236\345m\234t\012",
"\356os\200\203d\212\322\214\012",
"\245\206\225y\360pro\315typ\301\246\236\343\365\357\214\353semic\245umn\275",
"\356c\353\347\217 s\313\374w\204\251\347a\201\251\316c\277\367level\012",
"\260\316\266\326\343\365\366ov\211rid\200\303appe\205 \355twe\212 p\205\212\240ese\275",
"la\355l nam\200\217 s\313\374w\204\366na\323\012",
"nu\233\256\310\342git\204\260ce\277\204\244\214\353nu\233\256\316ci\227\202\012",
"\221d\220d\223\201\042\354e\273\042: \325\354\200\274\213way\2041 \341",
"\203\226t\211m\203\230\200\317\354\200\363\042\354e\273\352\260\316\266\326\341",
"\220\221a\270\267\200\345\226\012",
"\251\347\274a\266gn\236\315 itself \341",
"m\222\200\203i\207\213iz\211\204\240\364\212um \332eld\275",
"l\212g\365\310\203i\207\213iz\256\260ce\277\204\354\200\310\376\212um \332eld\012",
"\203\226x \366mis\370 \341",
"\215 i\375le\234\322\237f\247\330\200\217 \363\361\232\331\215 f\213l-back\012",
"\330\200speci\332ca\237\326\362w\205\206\226cl\327\237\274ig\215\221d\012",
"outpu\201\332\360\274writt\212\331bu\201\343\365\345\375ac\201\212\345d\367\342s\267\277\012",
"\330\200\347\217 s\313\374w\204\251g\356b\353\312\335",
"\302 \274m\205k\236a\204\226\316c\230\277: \350",
"pu\241ic \271lack\204\362w\205\206\226cl\327\237\341",
"\220k\215w\340p\327\323t\256\363subs\207tu\237(\203c\222\221c\201#\321\200p\230t\211n\235"
#endif
};
#ifdef SCPACK_PUSH
# undef SCPACK
#endif

View File

@ -1,3 +1,4 @@
/* vim: set ts=8 sts=2 sw=2 tw=99 et: */
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@ -10,6 +11,8 @@ funcenum_t *firstenum = NULL;
funcenum_t *lastenum = NULL;
pstruct_t *firststruct = NULL;
pstruct_t *laststruct = NULL;
methodmap_t *methodmap_first = NULL;
methodmap_t *methodmap_last = NULL;
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
{
@ -411,6 +414,13 @@ void popstacklist(int codegen)
{
_stack_genusage(stackusage, 1);
assert(stackusage->head==NULL);
} else {
memuse_t *use = stackusage->head;
while (use) {
memuse_t *temp = use->prev;
free(use);
use = temp;
}
}
oldlist = stackusage->prev;
@ -427,3 +437,141 @@ void resetheaplist()
{
_reset_memlist(&heapusage);
}
void methodmap_add(methodmap_t *map)
{
if (!methodmap_first) {
methodmap_first = map;
methodmap_last = map;
} else {
methodmap_last->next = map;
methodmap_last = map;
}
}
methodmap_t *methodmap_find_by_tag(int tag)
{
methodmap_t *ptr = methodmap_first;
for (; ptr; ptr = ptr->next) {
if (ptr->tag == tag)
return ptr;
}
return NULL;
}
methodmap_t *methodmap_find_by_name(const char *name)
{
int tag = pc_findtag(name);
if (tag == -1)
return NULL;
return methodmap_find_by_tag(tag);
}
methodmap_method_t *methodmap_find_method(methodmap_t *map, const char *name)
{
size_t i;
for (i = 0; i < map->nummethods; i++) {
if (strcmp(map->methods[i]->name, name) == 0)
return map->methods[i];
}
if (map->parent)
return methodmap_find_method(map->parent, name);
return NULL;
}
void methodmaps_free()
{
methodmap_t *ptr = methodmap_first;
while (ptr) {
methodmap_t *next = ptr->next;
for (size_t i = 0; i < ptr->nummethods; i++)
free(ptr->methods[i]);
free(ptr->methods);
free(ptr);
ptr = next;
}
methodmap_first = NULL;
methodmap_last = NULL;
}
LayoutSpec deduce_layout_spec_by_tag(int tag)
{
symbol *sym;
const char *name;
methodmap_t *map;
if ((map = methodmap_find_by_tag(tag)) != NULL)
return map->spec;
if (tag & FUNCTAG)
return Layout_FuncTag;
name = pc_tagname(tag);
if (pstructs_find(name))
return Layout_PawnStruct;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
LayoutSpec deduce_layout_spec_by_name(const char *name)
{
symbol *sym;
methodmap_t *map;
int tag = pc_findtag(name);
if (tag != -1 && (tag & FUNCTAG))
return Layout_FuncTag;
if (pstructs_find(name))
return Layout_PawnStruct;
if ((map = methodmap_find_by_name(name)) != NULL)
return map->spec;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
const char *layout_spec_name(LayoutSpec spec)
{
switch (spec) {
case Layout_None:
return "<none>";
case Layout_Enum:
return "enum";
case Layout_FuncTag:
return "functag";
case Layout_PawnStruct:
return "deprecated-struct";
case Layout_MethodMap:
return "methodmap";
case Layout_Class:
return "class";
}
return "<unknown>";
}
int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2)
{
// Normalize the ordering, since these checks are symmetrical.
if (def1 > def2) {
LayoutSpec temp = def2;
def2 = def1;
def1 = temp;
}
switch (def1) {
case Layout_None:
return TRUE;
case Layout_Enum:
if (def2 == Layout_Enum || def2 == Layout_FuncTag)
return TRUE;
return def2 == Layout_MethodMap;
case Layout_FuncTag:
return def2 == Layout_Enum || def2 == Layout_FuncTag;
case Layout_PawnStruct:
case Layout_MethodMap:
return FALSE;
case Layout_Class:
return FALSE;
}
return FALSE;
}

View File

@ -1,3 +1,4 @@
/* vim: set sts=2 ts=8 sw=2 tw=99 et: */
#ifndef _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
#define _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
@ -66,6 +67,42 @@ typedef struct pstruct_s
struct pstruct_s *next;
} pstruct_t;
// The ordering of these definitions should be preserved for
// can_redef_layout_spec().
typedef enum LayoutSpec_t
{
Layout_None,
Layout_Enum,
Layout_FuncTag,
Layout_PawnStruct,
Layout_MethodMap,
Layout_Class
} LayoutSpec;
// The method name buffer is larger since we can include our parent class's
// name, a "." to separate it, and a "~" for constructors.
#define METHOD_NAMEMAX sNAMEMAX * 2 + 2
typedef struct methodmap_method_s
{
char name[METHOD_NAMEMAX + 1];
symbol *target;
} methodmap_method_t;
typedef struct methodmap_s
{
struct methodmap_s *next;
struct methodmap_s *parent;
int tag;
LayoutSpec spec;
char name[sNAMEMAX+1];
methodmap_method_t **methods;
size_t nummethods;
// Shortcut.
methodmap_method_t *dtor;
} methodmap_t;
/**
* Pawn Structs
*/
@ -83,6 +120,14 @@ funcenum_t *funcenums_add(const char *name);
funcenum_t *funcenums_find_byval(int value);
functag_t *functags_add(funcenum_t *en, functag_t *src);
/**
* Given a name or tag, find any extra weirdness it has associated with it.
*/
LayoutSpec deduce_layout_spec_by_tag(int tag);
LayoutSpec deduce_layout_spec_by_name(const char *name);
const char *layout_spec_name(LayoutSpec spec);
int can_redef_layout_spec(LayoutSpec olddef, LayoutSpec newdef);
/**
* Heap functions
*/
@ -111,6 +156,15 @@ void genheapfree(int stop_id);
void resetstacklist();
void resetheaplist();
/**
* Method maps.
*/
void methodmap_add(methodmap_t *map);
methodmap_t *methodmap_find_by_tag(int tag);
methodmap_t *methodmap_find_by_name(const char *name);
methodmap_method_t *methodmap_find_method(methodmap_t *map, const char *name);
void methodmaps_free();
extern memuse_list_t *heapusage;
extern memuse_list_t *stackusage;

View File

@ -0,0 +1,9 @@
native CloseHandle(Handle:this[]);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -0,0 +1 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -0,0 +1,13 @@
native Float:CreateHandle(count);
native CloseHandle(Handle:handle);
methodmap Handle {
public Handle() = CreateHandle;
public Close() = CloseHandle;
};
public main() {
new Handle:handle = Handle(3);
handle.Close();
}

View File

@ -0,0 +1 @@
constructor function must return tag Handle

View File

@ -0,0 +1,8 @@
native Q(X:this, a);
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -0,0 +1 @@
destructors cannot have extra arguments

View File

@ -0,0 +1,10 @@
Q(X:this)
{
}
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -0,0 +1 @@
destructors must be native functions

View File

@ -0,0 +1,8 @@
native bool:Q();
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -0,0 +1 @@
destructors cannot return values

View File

@ -0,0 +1,8 @@
native X:Crab();
methodmap X {
public X() = Crab;
public X() = Crab;
}
public main() {
}

View File

@ -0,0 +1 @@
X was already defined on this methodmap

View File

@ -0,0 +1,12 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
new Handle:x[2];
x.Close();
}

View File

@ -0,0 +1 @@
cannot call methods on an array

View File

@ -0,0 +1,10 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
main.Close();
}

View File

@ -0,0 +1 @@
cannot call methods on a function

View File

@ -0,0 +1,9 @@
native CloseHandle(HandleEgg:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -0,0 +1 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -0,0 +1,9 @@
native CloseHandle({Handle, Egg}:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -0,0 +1 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -0,0 +1,9 @@
native CloseHandle(this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -0,0 +1 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -0,0 +1,9 @@
native CloseHandle(&Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -0,0 +1 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -0,0 +1,14 @@
native CloseHandle(Handle:this);
methodmap Handle {
};
methodmap Crab < Handle {
public Close() = CloseHandle;
};
public main()
{
new Crab:x;
x.Close();
}

View File

@ -0,0 +1,12 @@
native Handle:CreateHandle(count);
native CloseHandle(Handle:handle);
methodmap Handle {
public Handle() = CreateHandle;
public ~Handle() = CloseHandle;
};
public main() {
new Handle:handle = Handle(3);
delete handle;
}

View File

@ -0,0 +1,14 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
methodmap Crab < Handle {
};
public main()
{
new Crab:x;
x.Close();
}

View File

@ -0,0 +1,14 @@
native CloseHandle(Handle:this);
enum Handle {
INVALID_HANDLE = 0,
};
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
INVALID_HANDLE.Close();
}

View File

@ -0,0 +1,16 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
f(const &Handle:x)
{
x.Close()
}
public main()
{
new Handle:x;
f(x)
}

View File

@ -0,0 +1,11 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
new Handle:x[2];
x[1].Close();
}

View File

@ -0,0 +1,16 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
f(&Handle:x)
{
x.Close()
}
public main()
{
new Handle:x;
f(x)
}

View File

@ -0,0 +1,13 @@
native CloneHandle(Handle:this);
native CloseHandle(Handle:this);
methodmap Handle {
public Clone() = CloneHandle;
public Close() = CloseHandle;
};
public main()
{
new Handle:x;
x.Close();
}

View File

@ -0,0 +1,74 @@
# vim: set ts=4 sw=4 tw=99 et:
import os, sys
import argparse
import subprocess
def run_tests(args):
testdir = os.path.dirname(os.path.abspath(__file__))
tests = []
for filename in os.listdir(testdir):
base, ext = os.path.splitext(filename)
if ext == '.sp':
tests += [base]
failed = False
for test in tests:
print('Testing {0}...'.format(test))
if test.startswith('fail-'):
kind = 'fail'
elif test.startswith('warn-'):
kind = 'warn'
elif test.startswith('ok-'):
kind = 'pass'
try:
argv = [args.spcomp, os.path.join(testdir, test + '.sp')]
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
stdout = stdout.decode('utf-8')
stderr = stderr.decode('utf-8')
smx_path = test + '.smx'
compiled = os.path.exists(smx_path)
if compiled:
os.unlink(smx_path)
status = 'ok'
if compiled and kind == 'fail':
status = 'fail'
elif not compiled and kind != 'fail':
status = 'fail'
if status == 'ok' and kind != 'pass':
with open(os.path.join(testdir, test + '.txt')) as fp:
text = fp.read()
if text not in stdout:
print('Expected to find text in stdout: >>>')
print(text)
print('<<<')
status = 'fail'
if status == 'fail':
failed = True
print('FAILED! Dumping stdout/stderr:')
print(stdout)
print(stderr)
else:
print('... OK!')
except Exception as exn:
raise
sys.stderr.write('FAILED! {0}\n'.format(exn.message))
if failed:
sys.exit(1)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('spcomp', type=str, help='Path to spcomp')
args = parser.parse_args()
run_tests(args)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,15 @@
native CloseHandle(Handle:this);
methodmap Handle {
public Close() = CloseHandle;
};
methodmap Crab {
};
public main()
{
new Crab:x;
new Handle:y;
x = y;
}

View File

@ -0,0 +1 @@
tag mismatch