Expanded weak function pointers with type checking
Added function typing enumeration --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40137
This commit is contained in:
parent
fca7456f4d
commit
bc16901bd6
@ -45,7 +45,7 @@ int main(int argc, char *argv[])
|
|||||||
int err;
|
int err;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
sp_file_t *spf;
|
sp_file_t *spf;
|
||||||
memfile_t *dbgtab = NULL;
|
memfile_t *dbgtab = NULL; //dbgcrab
|
||||||
unsigned char *dbgptr = NULL;
|
unsigned char *dbgptr = NULL;
|
||||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
|
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -57,6 +57,8 @@
|
|||||||
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
|
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
|
||||||
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
|
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
|
||||||
#define sDEF_PREFIX "sourcemod.inc" /* default prefix filename */
|
#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 {
|
typedef union {
|
||||||
void *pv; /* e.g. a name */
|
void *pv; /* e.g. a name */
|
||||||
@ -283,7 +285,7 @@ typedef struct s_stringpair {
|
|||||||
*/
|
*/
|
||||||
#define tFIRST 256 /* value of first multi-character operator */
|
#define tFIRST 256 /* value of first multi-character operator */
|
||||||
#define tMIDDLE 280 /* value of last multi-character operator */
|
#define tMIDDLE 280 /* value of last multi-character operator */
|
||||||
#define tLAST 329 /* value of last multi-character match-able token */
|
#define tLAST 330 /* value of last multi-character match-able token */
|
||||||
/* multi-character operators */
|
/* multi-character operators */
|
||||||
#define taMULT 256 /* *= */
|
#define taMULT 256 /* *= */
|
||||||
#define taDIV 257 /* /= */
|
#define taDIV 257 /* /= */
|
||||||
@ -327,51 +329,52 @@ typedef struct s_stringpair {
|
|||||||
#define tEXIT 294
|
#define tEXIT 294
|
||||||
#define tFOR 295
|
#define tFOR 295
|
||||||
#define tFORWARD 296
|
#define tFORWARD 296
|
||||||
#define tGOTO 297
|
#define tFUNCENUM 297
|
||||||
#define tIF 298
|
#define tGOTO 298
|
||||||
#define tNATIVE 299
|
#define tIF 299
|
||||||
#define tNEW 300
|
#define tNATIVE 300
|
||||||
#define tDECL 301
|
#define tNEW 301
|
||||||
#define tOPERATOR 302
|
#define tDECL 302
|
||||||
#define tPUBLIC 303
|
#define tOPERATOR 303
|
||||||
#define tRETURN 304
|
#define tPUBLIC 304
|
||||||
#define tSIZEOF 305
|
#define tRETURN 305
|
||||||
#define tSLEEP 306
|
#define tSIZEOF 306
|
||||||
#define tSTATE 307
|
#define tSLEEP 307
|
||||||
#define tSTATIC 308
|
#define tSTATE 308
|
||||||
#define tSTOCK 309
|
#define tSTATIC 309
|
||||||
#define tSWITCH 310
|
#define tSTOCK 310
|
||||||
#define tTAGOF 311
|
#define tSWITCH 311
|
||||||
#define tTHEN 312
|
#define tTAGOF 312
|
||||||
#define tWHILE 313
|
#define tTHEN 313
|
||||||
|
#define tWHILE 314
|
||||||
/* compiler directives */
|
/* compiler directives */
|
||||||
#define tpASSERT 314 /* #assert */
|
#define tpASSERT 315 /* #assert */
|
||||||
#define tpDEFINE 315
|
#define tpDEFINE 316
|
||||||
#define tpELSE 316 /* #else */
|
#define tpELSE 317 /* #else */
|
||||||
#define tpELSEIF 317 /* #elseif */
|
#define tpELSEIF 318 /* #elseif */
|
||||||
#define tpEMIT 318
|
#define tpEMIT 319
|
||||||
#define tpENDIF 319
|
#define tpENDIF 320
|
||||||
#define tpENDINPUT 320
|
#define tpENDINPUT 321
|
||||||
#define tpENDSCRPT 321
|
#define tpENDSCRPT 322
|
||||||
#define tpERROR 322
|
#define tpERROR 323
|
||||||
#define tpFILE 323
|
#define tpFILE 324
|
||||||
#define tpIF 324 /* #if */
|
#define tpIF 325 /* #if */
|
||||||
#define tINCLUDE 325
|
#define tINCLUDE 326
|
||||||
#define tpLINE 326
|
#define tpLINE 327
|
||||||
#define tpPRAGMA 327
|
#define tpPRAGMA 328
|
||||||
#define tpTRYINCLUDE 328
|
#define tpTRYINCLUDE 329
|
||||||
#define tpUNDEF 329
|
#define tpUNDEF 330
|
||||||
/* semicolon is a special case, because it can be optional */
|
/* semicolon is a special case, because it can be optional */
|
||||||
#define tTERM 330 /* semicolon or newline */
|
#define tTERM 331 /* semicolon or newline */
|
||||||
#define tENDEXPR 331 /* forced end of expression */
|
#define tENDEXPR 332 /* forced end of expression */
|
||||||
/* other recognized tokens */
|
/* other recognized tokens */
|
||||||
#define tNUMBER 332 /* integer number */
|
#define tNUMBER 333 /* integer number */
|
||||||
#define tRATIONAL 333 /* rational number */
|
#define tRATIONAL 334 /* rational number */
|
||||||
#define tSYMBOL 334
|
#define tSYMBOL 335
|
||||||
#define tLABEL 335
|
#define tLABEL 336
|
||||||
#define tSTRING 336
|
#define tSTRING 337
|
||||||
#define tEXPR 337 /* for assigment to "lastst" only (see SC1.C) */
|
#define tEXPR 338 /* for assigment to "lastst" only (see SC1.C) */
|
||||||
#define tENDLESS 338 /* endless loop, for assigment to "lastst" only */
|
#define tENDLESS 339 /* endless loop, for assigment to "lastst" only */
|
||||||
|
|
||||||
/* (reversed) evaluation of staging buffer */
|
/* (reversed) evaluation of staging buffer */
|
||||||
#define sSTARTREORDER 0x01
|
#define sSTARTREORDER 0x01
|
||||||
@ -432,9 +435,11 @@ typedef enum s_optmark {
|
|||||||
#if INT_MAX<0x8000u
|
#if INT_MAX<0x8000u
|
||||||
#define PUBLICTAG 0x8000u
|
#define PUBLICTAG 0x8000u
|
||||||
#define FIXEDTAG 0x4000u
|
#define FIXEDTAG 0x4000u
|
||||||
|
#define FUNCTAG 0x2000u
|
||||||
#else
|
#else
|
||||||
#define PUBLICTAG 0x80000000Lu
|
#define PUBLICTAG 0x80000000Lu
|
||||||
#define FIXEDTAG 0x40000000Lu
|
#define FIXEDTAG 0x40000000Lu
|
||||||
|
#define FUNCTAG 0x20000000Lu
|
||||||
#endif
|
#endif
|
||||||
#define TAGMASK (~PUBLICTAG)
|
#define TAGMASK (~PUBLICTAG)
|
||||||
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
|
#define CELL_MAX (((ucell)1 << (sizeof(cell)*8-1)) - 1)
|
||||||
@ -451,6 +456,7 @@ typedef enum s_optmark {
|
|||||||
int pc_compile(int argc, char **argv);
|
int pc_compile(int argc, char **argv);
|
||||||
int pc_addconstant(char *name,cell value,int tag);
|
int pc_addconstant(char *name,cell value,int tag);
|
||||||
int pc_addtag(char *name);
|
int pc_addtag(char *name);
|
||||||
|
int pc_addfunctag(char *name);
|
||||||
int pc_enablewarning(int number,int enable);
|
int pc_enablewarning(int number,int enable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -517,6 +523,7 @@ SC_FUNC void delete_consttable(constvalue *table);
|
|||||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
||||||
SC_FUNC void exporttag(int tag);
|
SC_FUNC void exporttag(int tag);
|
||||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
||||||
|
SC_FUNC constvalue *find_tag_byval(int tag);
|
||||||
|
|
||||||
/* function prototypes in SC2.C */
|
/* function prototypes in SC2.C */
|
||||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||||
@ -801,6 +808,7 @@ SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecate
|
|||||||
SC_VDECL int sc_curstates; /* ID of the current state list */
|
SC_VDECL int sc_curstates; /* ID of the current state list */
|
||||||
SC_VDECL int pc_optimize; /* (peephole) optimization level */
|
SC_VDECL int pc_optimize; /* (peephole) optimization level */
|
||||||
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
|
SC_VDECL int pc_memflags; /* special flags for the stack/heap usage */
|
||||||
|
SC_VDECL int pc_functag; /* global function tag */
|
||||||
|
|
||||||
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
||||||
SC_VDECL constvalue sc_state_tab; /* state table */
|
SC_VDECL constvalue sc_state_tab; /* state table */
|
||||||
@ -815,6 +823,12 @@ SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */
|
|||||||
SC_VDECL int sc_makereport; /* generate a cross-reference report */
|
SC_VDECL int sc_makereport; /* generate a cross-reference report */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined WIN32
|
||||||
|
#if !defined snprintf
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SC_SKIP_VDECL */
|
#endif /* SC_SKIP_VDECL */
|
||||||
|
|
||||||
#endif /* SC_H_INCLUDED */
|
#endif /* SC_H_INCLUDED */
|
||||||
|
@ -70,6 +70,8 @@
|
|||||||
#define VERSION_STR "3.2." SVN_REVSTR
|
#define VERSION_STR "3.2." SVN_REVSTR
|
||||||
#define VERSION_INT 0x0302
|
#define VERSION_INT 0x0302
|
||||||
|
|
||||||
|
int pc_functag = 0;
|
||||||
|
|
||||||
static void resetglobals(void);
|
static void resetglobals(void);
|
||||||
static void initglobals(void);
|
static void initglobals(void);
|
||||||
static char *get_extension(char *filename);
|
static char *get_extension(char *filename);
|
||||||
@ -126,6 +128,7 @@ static void doswitch(void);
|
|||||||
static void dogoto(void);
|
static void dogoto(void);
|
||||||
static void dolabel(void);
|
static void dolabel(void);
|
||||||
static void doreturn(void);
|
static void doreturn(void);
|
||||||
|
static void dofuncenum(void);
|
||||||
static void dobreak(void);
|
static void dobreak(void);
|
||||||
static void docont(void);
|
static void docont(void);
|
||||||
static void dosleep(void);
|
static void dosleep(void);
|
||||||
@ -320,6 +323,7 @@ int pc_compile(int argc, char *argv[])
|
|||||||
inst_datetime_defines();
|
inst_datetime_defines();
|
||||||
#endif
|
#endif
|
||||||
resetglobals();
|
resetglobals();
|
||||||
|
funcenums_free();
|
||||||
sc_ctrlchar=sc_ctrlchar_org;
|
sc_ctrlchar=sc_ctrlchar_org;
|
||||||
sc_packstr=lcl_packstr;
|
sc_packstr=lcl_packstr;
|
||||||
sc_needsemicolon=lcl_needsemicolon;
|
sc_needsemicolon=lcl_needsemicolon;
|
||||||
@ -380,6 +384,7 @@ int pc_compile(int argc, char *argv[])
|
|||||||
/* reset "defined" flag of all functions and global variables */
|
/* reset "defined" flag of all functions and global variables */
|
||||||
reduce_referrers(&glbtab);
|
reduce_referrers(&glbtab);
|
||||||
delete_symbols(&glbtab,0,TRUE,FALSE);
|
delete_symbols(&glbtab,0,TRUE,FALSE);
|
||||||
|
funcenums_free();
|
||||||
#if !defined NO_DEFINE
|
#if !defined NO_DEFINE
|
||||||
delete_substtable();
|
delete_substtable();
|
||||||
inst_datetime_defines();
|
inst_datetime_defines();
|
||||||
@ -577,6 +582,7 @@ int pc_addtag(char *name)
|
|||||||
if (strcmp(name,ptr->name)==0)
|
if (strcmp(name,ptr->name)==0)
|
||||||
return tag; /* tagname is known, return its sequence number */
|
return tag; /* tagname is known, return its sequence number */
|
||||||
tag &= (int)~FIXEDTAG;
|
tag &= (int)~FIXEDTAG;
|
||||||
|
tag &= (int)~FUNCTAG;
|
||||||
if (tag>last)
|
if (tag>last)
|
||||||
last=tag;
|
last=tag;
|
||||||
ptr=ptr->next;
|
ptr=ptr->next;
|
||||||
@ -590,6 +596,43 @@ int pc_addtag(char *name)
|
|||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pc_addfunctag(char *name)
|
||||||
|
{
|
||||||
|
cell val;
|
||||||
|
constvalue *ptr;
|
||||||
|
int last,tag;
|
||||||
|
|
||||||
|
if (name==NULL) {
|
||||||
|
/* no tagname was given, check for one */
|
||||||
|
if (lex(&val,&name)!=tLABEL) {
|
||||||
|
lexpush();
|
||||||
|
return 0; /* untagged */
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
assert(strchr(name,':')==NULL); /* colon should already have been stripped */
|
||||||
|
last=0;
|
||||||
|
ptr=tagname_tab.next;
|
||||||
|
while (ptr!=NULL) {
|
||||||
|
tag=(int)(ptr->value & TAGMASK);
|
||||||
|
if (strcmp(name,ptr->name)==0)
|
||||||
|
return tag; /* tagname is known, return its sequence number */
|
||||||
|
tag &= (int)~FIXEDTAG;
|
||||||
|
tag &= (int)~FUNCTAG;
|
||||||
|
if (tag>last)
|
||||||
|
last=tag;
|
||||||
|
ptr=ptr->next;
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
/* tagname currently unknown, add it */
|
||||||
|
tag=last+1; /* guaranteed not to exist already */
|
||||||
|
if (isupper(*name))
|
||||||
|
tag |= (int)FIXEDTAG;
|
||||||
|
tag |= (int)FUNCTAG;
|
||||||
|
append_constval(&tagname_tab,name,(cell)tag,0);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
static void resetglobals(void)
|
static void resetglobals(void)
|
||||||
{
|
{
|
||||||
/* reset the subset of global variables that is modified by the first pass */
|
/* reset the subset of global variables that is modified by the first pass */
|
||||||
@ -1204,6 +1247,7 @@ static void setconstants(void)
|
|||||||
assert(sc_status==statIDLE);
|
assert(sc_status==statIDLE);
|
||||||
append_constval(&tagname_tab,"_",0,0);/* "untagged" */
|
append_constval(&tagname_tab,"_",0,0);/* "untagged" */
|
||||||
append_constval(&tagname_tab,"bool",1,0);
|
append_constval(&tagname_tab,"bool",1,0);
|
||||||
|
pc_functag = pc_addfunctag("Function");
|
||||||
|
|
||||||
add_constant("true",1,sGLOBAL,1); /* boolean flags */
|
add_constant("true",1,sGLOBAL,1); /* boolean flags */
|
||||||
add_constant("false",0,sGLOBAL,1);
|
add_constant("false",0,sGLOBAL,1);
|
||||||
@ -1363,6 +1407,9 @@ static void parse(void)
|
|||||||
case tENUM:
|
case tENUM:
|
||||||
decl_enum(sGLOBAL);
|
decl_enum(sGLOBAL);
|
||||||
break;
|
break;
|
||||||
|
case tFUNCENUM:
|
||||||
|
dofuncenum();
|
||||||
|
break;
|
||||||
case tPUBLIC:
|
case tPUBLIC:
|
||||||
/* This can be a public function or a public variable; see the comment
|
/* This can be a public function or a public variable; see the comment
|
||||||
* above (for static functions/variables) for details.
|
* above (for static functions/variables) for details.
|
||||||
@ -2536,6 +2583,185 @@ static void decl_const(int vclass)
|
|||||||
needtoken(tTERM);
|
needtoken(tTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dofuncenum - declare function enumerations
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void dofuncenum(void)
|
||||||
|
{
|
||||||
|
cell val;
|
||||||
|
char *str,*ptr;
|
||||||
|
char tagname[sNAMEMAX+1];
|
||||||
|
constvalue *cur;
|
||||||
|
funcenum_t *fenum = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* get the explicit tag (required!) */
|
||||||
|
int l = lex(&val,&str);
|
||||||
|
if (l != tSYMBOL)
|
||||||
|
{
|
||||||
|
/* Incomprehensible but it works for now! */
|
||||||
|
error(57);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This tag can't already exist! */
|
||||||
|
cur=tagname_tab.next;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
if (strcmp(cur->name, str) == 0)
|
||||||
|
{
|
||||||
|
/* Another bad one... */
|
||||||
|
if (!(cur->value & FUNCTAG))
|
||||||
|
{
|
||||||
|
error(213);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
strcpy(tagname, str);
|
||||||
|
|
||||||
|
fenum = funcenums_add(tagname);
|
||||||
|
|
||||||
|
needtoken('{');
|
||||||
|
do
|
||||||
|
{
|
||||||
|
functag_t func;
|
||||||
|
if (matchtoken('}'))
|
||||||
|
{
|
||||||
|
/* Quick exit */
|
||||||
|
lexpush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(&func, 0, sizeof(func));
|
||||||
|
func.ret_tag = pc_addtag(NULL); /* Get the return tag */
|
||||||
|
l = lex(&val, &str);
|
||||||
|
if (l == tFORWARD)
|
||||||
|
{
|
||||||
|
func.type = uFORWARD;
|
||||||
|
} else if (l == tPUBLIC) {
|
||||||
|
func.type = uPUBLIC;
|
||||||
|
} else {
|
||||||
|
error(1, "[forward,public]", str);
|
||||||
|
}
|
||||||
|
needtoken('(');
|
||||||
|
do
|
||||||
|
{
|
||||||
|
funcarg_t *arg = &(func.args[func.argcount]);
|
||||||
|
|
||||||
|
/* Quick exit */
|
||||||
|
if (matchtoken(')'))
|
||||||
|
{
|
||||||
|
lexpush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
l = lex(&val, &str);
|
||||||
|
if (l == '&')
|
||||||
|
{
|
||||||
|
if ((arg->ident != iVARIABLE && arg->ident != 0) || arg->tagcount > 0)
|
||||||
|
{
|
||||||
|
error(1, "-identifier-", "&");
|
||||||
|
}
|
||||||
|
arg->ident = iREFERENCE;
|
||||||
|
} else if (l == tCONST) {
|
||||||
|
if ((arg->ident != iVARIABLE && arg->ident != 0) || arg->tagcount > 0)
|
||||||
|
{
|
||||||
|
error(1, "-identifier-", "const");
|
||||||
|
}
|
||||||
|
arg->fconst=TRUE;
|
||||||
|
} else if (l == tLABEL) {
|
||||||
|
if (arg->tagcount > 0)
|
||||||
|
{
|
||||||
|
error(1, "-identifier-", "-tagname-");
|
||||||
|
}
|
||||||
|
arg->tags[arg->tagcount++] = pc_addtag(str);
|
||||||
|
#if 0
|
||||||
|
while (arg->tagcount < sTAGS_MAX)
|
||||||
|
{
|
||||||
|
if (!matchtoken('_') && !needtoken(tSYMBOL))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tokeninfo(&val, &ptr);
|
||||||
|
arg->tags[arg->tagcount++] = pc_addtag(ptr);
|
||||||
|
if (matchtoken('}'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
needtoken(',');
|
||||||
|
}
|
||||||
|
needtoken(':');
|
||||||
|
#endif
|
||||||
|
l=tLABEL;
|
||||||
|
} else if (l == tSYMBOL) {
|
||||||
|
if (func.argcount >= sARGS_MAX)
|
||||||
|
{
|
||||||
|
error(45);
|
||||||
|
}
|
||||||
|
if (str[0] == PUBLIC_CHAR)
|
||||||
|
{
|
||||||
|
error(56, str);
|
||||||
|
}
|
||||||
|
if (matchtoken('['))
|
||||||
|
{
|
||||||
|
if (arg->ident == iREFERENCE)
|
||||||
|
{
|
||||||
|
error(67, str);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
constvalue *enumroot;
|
||||||
|
cell size;
|
||||||
|
int ignore_tag;
|
||||||
|
if (arg->dimcount == sDIMEN_MAX)
|
||||||
|
{
|
||||||
|
error(53);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size = needsub(&ignore_tag, &enumroot);
|
||||||
|
arg->dims[arg->dimcount] = size;
|
||||||
|
arg->dimcount += 1;
|
||||||
|
} while (matchtoken('['));
|
||||||
|
arg->ident=iREFARRAY;
|
||||||
|
} else if (arg->ident == 0) {
|
||||||
|
arg->ident = iVARIABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchtoken('='))
|
||||||
|
{
|
||||||
|
needtoken('0');
|
||||||
|
arg->ommittable = TRUE;
|
||||||
|
func.ommittable = TRUE;
|
||||||
|
} else if (func.ommittable) {
|
||||||
|
/* :TODO: ERROR HERE! */
|
||||||
|
}
|
||||||
|
func.argcount++;
|
||||||
|
} else if (l == tELLIPS) {
|
||||||
|
if (arg->ident == iVARIABLE)
|
||||||
|
{
|
||||||
|
error(10);
|
||||||
|
}
|
||||||
|
arg->ident = iVARARGS;
|
||||||
|
func.argcount++;
|
||||||
|
} else {
|
||||||
|
error(10);
|
||||||
|
}
|
||||||
|
} while (l == '&' || l == tLABEL || l == tCONST || l != tELLIPS && matchtoken(','));
|
||||||
|
needtoken(')');
|
||||||
|
for (i=0; i<func.argcount; i++)
|
||||||
|
{
|
||||||
|
if (func.args[i].tagcount == 0)
|
||||||
|
{
|
||||||
|
func.args[i].tags[0] = 0;
|
||||||
|
func.args[i].tagcount = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
functags_add(fenum, &func);
|
||||||
|
} while (matchtoken(','));
|
||||||
|
needtoken('}');
|
||||||
|
matchtoken(';'); /* eat an optional semicolon. nom nom nom */
|
||||||
|
errorset(sRESET, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* decl_enum - declare enumerated constants
|
/* decl_enum - declare enumerated constants
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -3054,7 +3280,7 @@ static int parse_funcname(char *fname,int *tag1,int *tag2,char *opname)
|
|||||||
return unary;
|
return unary;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constvalue *find_tag_byval(int tag)
|
constvalue *find_tag_byval(int tag)
|
||||||
{
|
{
|
||||||
constvalue *tagsym;
|
constvalue *tagsym;
|
||||||
tagsym=find_constval_byval(&tagname_tab,tag & ~PUBLICTAG);
|
tagsym=find_constval_byval(&tagname_tab,tag & ~PUBLICTAG);
|
||||||
|
@ -1833,7 +1833,7 @@ char *sc_tokens[] = {
|
|||||||
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
||||||
"...", "..", "::",
|
"...", "..", "::",
|
||||||
"assert", "*begin", "break", "case", "char", "const", "continue", "default",
|
"assert", "*begin", "break", "case", "char", "const", "continue", "default",
|
||||||
"defined", "do", "else", "*end", "enum", "exit", "for", "forward", "goto",
|
"defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "goto",
|
||||||
"if", "native", "new", "decl", "operator", "public", "return", "sizeof",
|
"if", "native", "new", "decl", "operator", "public", "return", "sizeof",
|
||||||
"sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
|
"sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
|
||||||
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
"#assert", "#define", "#else", "#elseif", "#emit", "#endif", "#endinput",
|
||||||
|
@ -288,8 +288,178 @@ SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
|
|||||||
/* if the formal tag is zero and the actual tag is not "fixed", the actual
|
/* if the formal tag is zero and the actual tag is not "fixed", the actual
|
||||||
* tag is "coerced" to zero
|
* tag is "coerced" to zero
|
||||||
*/
|
*/
|
||||||
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0)
|
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0) {
|
||||||
return FALSE;
|
if (formaltag & FUNCTAG)
|
||||||
|
{
|
||||||
|
if (actualtag == pc_functag || (formaltag == pc_functag && actualtag & FUNCTAG))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
} else if (actualtag & FUNCTAG) {
|
||||||
|
constvalue *v = find_tag_byval(actualtag);
|
||||||
|
int index;
|
||||||
|
short usage = uPUBLIC;
|
||||||
|
symbol *sym, *found = NULL;
|
||||||
|
funcenum_t *e;
|
||||||
|
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] == '!');
|
||||||
|
|
||||||
|
/* Deduce which function type this is */
|
||||||
|
if (v->name[5] == '@')
|
||||||
|
{
|
||||||
|
usage = uPUBLIC;
|
||||||
|
} else if (v->name[5] = '!') {
|
||||||
|
usage = uFORWARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = atoi(&v->name[6]);
|
||||||
|
|
||||||
|
assert(index >= 0);
|
||||||
|
|
||||||
|
/* Find the function, either by public idx or code addr */
|
||||||
|
if (usage == uPUBLIC)
|
||||||
|
{
|
||||||
|
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||||
|
if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL))
|
||||||
|
{
|
||||||
|
if (index-- == 0)
|
||||||
|
{
|
||||||
|
found = sym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (usage == uFORWARD) {
|
||||||
|
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||||
|
if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL))
|
||||||
|
{
|
||||||
|
if (sym->codeaddr == index)
|
||||||
|
{
|
||||||
|
found = sym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
assert(found);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wow, we now have:
|
||||||
|
* 1) The functional enum deduced from formaltag
|
||||||
|
* 2) The function trying to be shoved in deduced from actualtag
|
||||||
|
* Now we have to check if it matches any one of the functags inside the enum.
|
||||||
|
*/
|
||||||
|
t = e->first;
|
||||||
|
while (t)
|
||||||
|
{
|
||||||
|
int curarg,skip=0,i;
|
||||||
|
arginfo *func_arg;
|
||||||
|
funcarg_t *enum_arg;
|
||||||
|
/* Check return type first. */
|
||||||
|
if (t->ret_tag != sym->tag)
|
||||||
|
{
|
||||||
|
t = t->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Check usage */
|
||||||
|
if (t->type != usage)
|
||||||
|
{
|
||||||
|
t = t->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Begin iterating arguments */
|
||||||
|
for (curarg=0; curarg<t->argcount; curarg++)
|
||||||
|
{
|
||||||
|
enum_arg = &t->args[curarg];
|
||||||
|
/* Check whether we've exhausted our arguments */
|
||||||
|
if (sym->dim.arglist[curarg].ident == 0)
|
||||||
|
{
|
||||||
|
/* Can we bail out early? */
|
||||||
|
if (!enum_arg->ommittable)
|
||||||
|
{
|
||||||
|
/* No! */
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
func_arg = &sym->dim.arglist[curarg];
|
||||||
|
/* First check the ident type */
|
||||||
|
if (enum_arg->ident != func_arg->ident)
|
||||||
|
{
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Next check arrayness */
|
||||||
|
if (enum_arg->dimcount != func_arg->numdim)
|
||||||
|
{
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (enum_arg->dimcount > 0)
|
||||||
|
{
|
||||||
|
for (i=0; i<enum_arg->dimcount; i++)
|
||||||
|
{
|
||||||
|
if (enum_arg->dims[i] != func_arg->dim[i])
|
||||||
|
{
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Lastly, check the tags */
|
||||||
|
if (enum_arg->tagcount != func_arg->numtags)
|
||||||
|
{
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* They should all be in the same order just for clarity... */
|
||||||
|
for (i=0; i<enum_arg->tagcount; i++)
|
||||||
|
{
|
||||||
|
if (enum_arg->tags[i] != func_arg->tags[i])
|
||||||
|
{
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 */
|
} /* if */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1723,24 +1893,35 @@ restart:
|
|||||||
if (sc_allowproccall) {
|
if (sc_allowproccall) {
|
||||||
callfunction(sym,lval1,FALSE);
|
callfunction(sym,lval1,FALSE);
|
||||||
} else {
|
} else {
|
||||||
|
symbol *oldsym=sym;
|
||||||
int n=-1,iter=0;
|
int n=-1,iter=0;
|
||||||
|
int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0;
|
||||||
|
cell code_addr=0;
|
||||||
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
|
||||||
if (sym->ident==iFUNCTN
|
if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage)))
|
||||||
&& (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
|
|
||||||
{
|
{
|
||||||
assert(sym->vclass==sGLOBAL);
|
|
||||||
if (strcmp(sym->name, lval1->sym->name)==0) {
|
if (strcmp(sym->name, lval1->sym->name)==0) {
|
||||||
n = iter;
|
n = iter;
|
||||||
|
code_addr = sym->codeaddr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n!=-1) {
|
if (n!=-1) {
|
||||||
|
char faketag[sNAMEMAX+1];
|
||||||
lval1->sym=NULL;
|
lval1->sym=NULL;
|
||||||
lval1->ident=iCONSTEXPR;
|
lval1->ident=iCONSTEXPR;
|
||||||
lval1->constval=n;
|
/* Generate a quick pseudo-tag! */
|
||||||
lval1->tag=pc_addtag("Function");
|
if (usage == uPUBLIC) {
|
||||||
|
lval1->constval=(n>>1)|(1<<1);
|
||||||
|
snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n);
|
||||||
|
} else {
|
||||||
|
lval1->constval=(code_addr>>1)|(1<<0);
|
||||||
|
snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr);
|
||||||
|
}
|
||||||
|
lval1->tag=pc_addfunctag(faketag);
|
||||||
|
oldsym->usage |= uREAD;
|
||||||
} else {
|
} else {
|
||||||
error(76); /* invalid function call, or syntax error */
|
error(76); /* invalid function call, or syntax error */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
@ -1,10 +1,94 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "sc.h"
|
#include "sc.h"
|
||||||
#include "sctracker.h"
|
#include "sctracker.h"
|
||||||
|
|
||||||
memuse_list_t *heapusage = NULL;
|
memuse_list_t *heapusage = NULL;
|
||||||
memuse_list_t *stackusage = NULL;
|
memuse_list_t *stackusage = NULL;
|
||||||
|
funcenum_t *firstenum = NULL;
|
||||||
|
funcenum_t *lastenum = NULL;
|
||||||
|
|
||||||
|
void funcenums_free()
|
||||||
|
{
|
||||||
|
funcenum_t *e, *next;
|
||||||
|
|
||||||
|
e = firstenum;
|
||||||
|
while (e)
|
||||||
|
{
|
||||||
|
functag_t *tag, *nexttag;
|
||||||
|
tag = e->first;
|
||||||
|
while (tag)
|
||||||
|
{
|
||||||
|
nexttag = tag->next;
|
||||||
|
free(tag);
|
||||||
|
tag = nexttag;
|
||||||
|
}
|
||||||
|
next = e->next;
|
||||||
|
free(e);
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstenum = NULL;
|
||||||
|
lastenum = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcenum_t *funcenums_find_byval(int value)
|
||||||
|
{
|
||||||
|
funcenum_t *e = firstenum;
|
||||||
|
|
||||||
|
while (e)
|
||||||
|
{
|
||||||
|
if (e->value == value)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcenum_t *funcenums_add(const char *name)
|
||||||
|
{
|
||||||
|
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
|
||||||
|
|
||||||
|
memset(e, 0, sizeof(funcenum_t));
|
||||||
|
|
||||||
|
if (firstenum == NULL)
|
||||||
|
{
|
||||||
|
firstenum = e;
|
||||||
|
lastenum = e;
|
||||||
|
} else {
|
||||||
|
lastenum->next = e;
|
||||||
|
lastenum = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(e->name, name);
|
||||||
|
e->value = pc_addfunctag((char *)name);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
functag_t *functags_add(funcenum_t *en, functag_t *src)
|
||||||
|
{
|
||||||
|
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
|
||||||
|
|
||||||
|
memcpy(t, src, sizeof(functag_t));
|
||||||
|
|
||||||
|
t->next = NULL;
|
||||||
|
|
||||||
|
if (en->first == NULL)
|
||||||
|
{
|
||||||
|
en->first = t;
|
||||||
|
en->last = t;
|
||||||
|
} else {
|
||||||
|
en->last->next = t;
|
||||||
|
en->last = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new mem usage tracker entry
|
* Creates a new mem usage tracker entry
|
||||||
|
@ -16,6 +16,44 @@ typedef struct memuse_list_s {
|
|||||||
memuse_t *head; /* head of the current list */
|
memuse_t *head; /* head of the current list */
|
||||||
} memuse_list_t;
|
} memuse_list_t;
|
||||||
|
|
||||||
|
typedef struct funcarg_s
|
||||||
|
{
|
||||||
|
int tagcount;
|
||||||
|
int tags[sTAGS_MAX];
|
||||||
|
int dimcount;
|
||||||
|
cell dims[sDIMEN_MAX];
|
||||||
|
int ident;
|
||||||
|
int fconst;
|
||||||
|
int ommittable;
|
||||||
|
} funcarg_t;
|
||||||
|
|
||||||
|
typedef struct functag_s
|
||||||
|
{
|
||||||
|
int ret_tag;
|
||||||
|
int type;
|
||||||
|
int argcount;
|
||||||
|
int ommittable;
|
||||||
|
funcarg_t args[sARGS_MAX];
|
||||||
|
struct functag_s *next;
|
||||||
|
} functag_t;
|
||||||
|
|
||||||
|
typedef struct funcenum_s
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
char name[sNAMEMAX+1];
|
||||||
|
functag_t *first;
|
||||||
|
functag_t *last;
|
||||||
|
struct funcenum_s *next;
|
||||||
|
} funcenum_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function enumeration tags
|
||||||
|
*/
|
||||||
|
void funcenums_free();
|
||||||
|
funcenum_t *funcenums_add(const char *name);
|
||||||
|
funcenum_t *funcenums_find_byval(int value);
|
||||||
|
functag_t *functags_add(funcenum_t *en, functag_t *src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heap functions
|
* Heap functions
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user