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;
|
||||
uint32_t i;
|
||||
sp_file_t *spf;
|
||||
memfile_t *dbgtab = NULL;
|
||||
memfile_t *dbgtab = NULL; //dbgcrab
|
||||
unsigned char *dbgptr = NULL;
|
||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
|
||||
FILE *fp;
|
||||
|
@ -57,6 +57,8 @@
|
||||
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
|
||||
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
|
||||
#define sDEF_PREFIX "sourcemod.inc" /* default prefix filename */
|
||||
#define sARGS_MAX 32 /* number of arguments a function can have, max */
|
||||
#define sTAGS_MAX 16 /* maximum number of tags on an argument */
|
||||
|
||||
typedef union {
|
||||
void *pv; /* e.g. a name */
|
||||
@ -283,7 +285,7 @@ typedef struct s_stringpair {
|
||||
*/
|
||||
#define tFIRST 256 /* value of first 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 */
|
||||
#define taMULT 256 /* *= */
|
||||
#define taDIV 257 /* /= */
|
||||
@ -327,51 +329,52 @@ typedef struct s_stringpair {
|
||||
#define tEXIT 294
|
||||
#define tFOR 295
|
||||
#define tFORWARD 296
|
||||
#define tGOTO 297
|
||||
#define tIF 298
|
||||
#define tNATIVE 299
|
||||
#define tNEW 300
|
||||
#define tDECL 301
|
||||
#define tOPERATOR 302
|
||||
#define tPUBLIC 303
|
||||
#define tRETURN 304
|
||||
#define tSIZEOF 305
|
||||
#define tSLEEP 306
|
||||
#define tSTATE 307
|
||||
#define tSTATIC 308
|
||||
#define tSTOCK 309
|
||||
#define tSWITCH 310
|
||||
#define tTAGOF 311
|
||||
#define tTHEN 312
|
||||
#define tWHILE 313
|
||||
#define tFUNCENUM 297
|
||||
#define tGOTO 298
|
||||
#define tIF 299
|
||||
#define tNATIVE 300
|
||||
#define tNEW 301
|
||||
#define tDECL 302
|
||||
#define tOPERATOR 303
|
||||
#define tPUBLIC 304
|
||||
#define tRETURN 305
|
||||
#define tSIZEOF 306
|
||||
#define tSLEEP 307
|
||||
#define tSTATE 308
|
||||
#define tSTATIC 309
|
||||
#define tSTOCK 310
|
||||
#define tSWITCH 311
|
||||
#define tTAGOF 312
|
||||
#define tTHEN 313
|
||||
#define tWHILE 314
|
||||
/* compiler directives */
|
||||
#define tpASSERT 314 /* #assert */
|
||||
#define tpDEFINE 315
|
||||
#define tpELSE 316 /* #else */
|
||||
#define tpELSEIF 317 /* #elseif */
|
||||
#define tpEMIT 318
|
||||
#define tpENDIF 319
|
||||
#define tpENDINPUT 320
|
||||
#define tpENDSCRPT 321
|
||||
#define tpERROR 322
|
||||
#define tpFILE 323
|
||||
#define tpIF 324 /* #if */
|
||||
#define tINCLUDE 325
|
||||
#define tpLINE 326
|
||||
#define tpPRAGMA 327
|
||||
#define tpTRYINCLUDE 328
|
||||
#define tpUNDEF 329
|
||||
#define tpASSERT 315 /* #assert */
|
||||
#define tpDEFINE 316
|
||||
#define tpELSE 317 /* #else */
|
||||
#define tpELSEIF 318 /* #elseif */
|
||||
#define tpEMIT 319
|
||||
#define tpENDIF 320
|
||||
#define tpENDINPUT 321
|
||||
#define tpENDSCRPT 322
|
||||
#define tpERROR 323
|
||||
#define tpFILE 324
|
||||
#define tpIF 325 /* #if */
|
||||
#define tINCLUDE 326
|
||||
#define tpLINE 327
|
||||
#define tpPRAGMA 328
|
||||
#define tpTRYINCLUDE 329
|
||||
#define tpUNDEF 330
|
||||
/* semicolon is a special case, because it can be optional */
|
||||
#define tTERM 330 /* semicolon or newline */
|
||||
#define tENDEXPR 331 /* forced end of expression */
|
||||
#define tTERM 331 /* semicolon or newline */
|
||||
#define tENDEXPR 332 /* forced end of expression */
|
||||
/* other recognized tokens */
|
||||
#define tNUMBER 332 /* integer number */
|
||||
#define tRATIONAL 333 /* rational number */
|
||||
#define tSYMBOL 334
|
||||
#define tLABEL 335
|
||||
#define tSTRING 336
|
||||
#define tEXPR 337 /* for assigment to "lastst" only (see SC1.C) */
|
||||
#define tENDLESS 338 /* endless loop, for assigment to "lastst" only */
|
||||
#define tNUMBER 333 /* integer number */
|
||||
#define tRATIONAL 334 /* rational number */
|
||||
#define tSYMBOL 335
|
||||
#define tLABEL 336
|
||||
#define tSTRING 337
|
||||
#define tEXPR 338 /* for assigment to "lastst" only (see SC1.C) */
|
||||
#define tENDLESS 339 /* endless loop, for assigment to "lastst" only */
|
||||
|
||||
/* (reversed) evaluation of staging buffer */
|
||||
#define sSTARTREORDER 0x01
|
||||
@ -432,9 +435,11 @@ typedef enum s_optmark {
|
||||
#if INT_MAX<0x8000u
|
||||
#define PUBLICTAG 0x8000u
|
||||
#define FIXEDTAG 0x4000u
|
||||
#define FUNCTAG 0x2000u
|
||||
#else
|
||||
#define PUBLICTAG 0x80000000Lu
|
||||
#define FIXEDTAG 0x40000000Lu
|
||||
#define FUNCTAG 0x20000000Lu
|
||||
#endif
|
||||
#define TAGMASK (~PUBLICTAG)
|
||||
#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_addconstant(char *name,cell value,int tag);
|
||||
int pc_addtag(char *name);
|
||||
int pc_addfunctag(char *name);
|
||||
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 void exporttag(int tag);
|
||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
||||
SC_FUNC constvalue *find_tag_byval(int tag);
|
||||
|
||||
/* function prototypes in SC2.C */
|
||||
#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 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 constvalue sc_automaton_tab; /* automaton 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 */
|
||||
#endif
|
||||
|
||||
#if defined WIN32
|
||||
#if !defined snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* SC_SKIP_VDECL */
|
||||
|
||||
#endif /* SC_H_INCLUDED */
|
||||
|
@ -70,6 +70,8 @@
|
||||
#define VERSION_STR "3.2." SVN_REVSTR
|
||||
#define VERSION_INT 0x0302
|
||||
|
||||
int pc_functag = 0;
|
||||
|
||||
static void resetglobals(void);
|
||||
static void initglobals(void);
|
||||
static char *get_extension(char *filename);
|
||||
@ -126,6 +128,7 @@ static void doswitch(void);
|
||||
static void dogoto(void);
|
||||
static void dolabel(void);
|
||||
static void doreturn(void);
|
||||
static void dofuncenum(void);
|
||||
static void dobreak(void);
|
||||
static void docont(void);
|
||||
static void dosleep(void);
|
||||
@ -320,6 +323,7 @@ int pc_compile(int argc, char *argv[])
|
||||
inst_datetime_defines();
|
||||
#endif
|
||||
resetglobals();
|
||||
funcenums_free();
|
||||
sc_ctrlchar=sc_ctrlchar_org;
|
||||
sc_packstr=lcl_packstr;
|
||||
sc_needsemicolon=lcl_needsemicolon;
|
||||
@ -380,6 +384,7 @@ int pc_compile(int argc, char *argv[])
|
||||
/* reset "defined" flag of all functions and global variables */
|
||||
reduce_referrers(&glbtab);
|
||||
delete_symbols(&glbtab,0,TRUE,FALSE);
|
||||
funcenums_free();
|
||||
#if !defined NO_DEFINE
|
||||
delete_substtable();
|
||||
inst_datetime_defines();
|
||||
@ -577,6 +582,7 @@ int pc_addtag(char *name)
|
||||
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;
|
||||
@ -590,6 +596,43 @@ int pc_addtag(char *name)
|
||||
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)
|
||||
{
|
||||
/* 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);
|
||||
append_constval(&tagname_tab,"_",0,0);/* "untagged" */
|
||||
append_constval(&tagname_tab,"bool",1,0);
|
||||
pc_functag = pc_addfunctag("Function");
|
||||
|
||||
add_constant("true",1,sGLOBAL,1); /* boolean flags */
|
||||
add_constant("false",0,sGLOBAL,1);
|
||||
@ -1363,6 +1407,9 @@ static void parse(void)
|
||||
case tENUM:
|
||||
decl_enum(sGLOBAL);
|
||||
break;
|
||||
case tFUNCENUM:
|
||||
dofuncenum();
|
||||
break;
|
||||
case tPUBLIC:
|
||||
/* This can be a public function or a public variable; see the comment
|
||||
* above (for static functions/variables) for details.
|
||||
@ -2536,6 +2583,185 @@ static void decl_const(int vclass)
|
||||
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
|
||||
*
|
||||
*/
|
||||
@ -3054,7 +3280,7 @@ static int parse_funcname(char *fname,int *tag1,int *tag2,char *opname)
|
||||
return unary;
|
||||
}
|
||||
|
||||
static constvalue *find_tag_byval(int tag)
|
||||
constvalue *find_tag_byval(int tag)
|
||||
{
|
||||
constvalue *tagsym;
|
||||
tagsym=find_constval_byval(&tagname_tab,tag & ~PUBLICTAG);
|
||||
|
@ -1833,7 +1833,7 @@ char *sc_tokens[] = {
|
||||
"||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
|
||||
"...", "..", "::",
|
||||
"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",
|
||||
"sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
|
||||
"#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
|
||||
* tag is "coerced" to zero
|
||||
*/
|
||||
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0)
|
||||
return FALSE;
|
||||
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0) {
|
||||
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 */
|
||||
return TRUE;
|
||||
}
|
||||
@ -1723,24 +1893,35 @@ restart:
|
||||
if (sc_allowproccall) {
|
||||
callfunction(sym,lval1,FALSE);
|
||||
} else {
|
||||
symbol *oldsym=sym;
|
||||
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) {
|
||||
if (sym->ident==iFUNCTN
|
||||
&& (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
|
||||
if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage)))
|
||||
{
|
||||
assert(sym->vclass==sGLOBAL);
|
||||
if (strcmp(sym->name, lval1->sym->name)==0) {
|
||||
n = iter;
|
||||
code_addr = sym->codeaddr;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
if (n!=-1) {
|
||||
char faketag[sNAMEMAX+1];
|
||||
lval1->sym=NULL;
|
||||
lval1->ident=iCONSTEXPR;
|
||||
lval1->constval=n;
|
||||
lval1->tag=pc_addtag("Function");
|
||||
/* Generate a quick pseudo-tag! */
|
||||
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 {
|
||||
error(76); /* invalid function call, or syntax error */
|
||||
} /* if */
|
||||
|
@ -1,10 +1,94 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sc.h"
|
||||
#include "sctracker.h"
|
||||
|
||||
memuse_list_t *heapusage = 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
|
||||
|
@ -16,6 +16,44 @@ typedef struct memuse_list_s {
|
||||
memuse_t *head; /* head of the current list */
|
||||
} 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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user