Merge pull request #134 from alliedmodders/calli
Simplify how functags work.
This commit is contained in:
		
						commit
						91f0f1001b
					
				| @ -964,9 +964,10 @@ SC_VDECL jmp_buf errbuf;      /* target of longjmp() on a fatal error */ | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if defined WIN32 | #if defined WIN32 | ||||||
| #if !defined snprintf | # if !defined snprintf | ||||||
| #define snprintf _snprintf | #  define snprintf _snprintf | ||||||
| #endif | #  define vsnprintf _vsnprintf | ||||||
|  | # endif | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif /* SC_SKIP_VDECL */ | #endif /* SC_SKIP_VDECL */ | ||||||
|  | |||||||
| @ -705,7 +705,7 @@ int pc_addtag_flags(char *name, int flags) | |||||||
|   constvalue *ptr; |   constvalue *ptr; | ||||||
|   int last,tag; |   int last,tag; | ||||||
| 
 | 
 | ||||||
|   assert(strchr(name,':')==NULL); /* colon should already have been stripped */ |   assert((flags & FUNCTAG) || strchr(name,':')==NULL); /* colon should already have been stripped */ | ||||||
|   last=0; |   last=0; | ||||||
|   ptr=tagname_tab.next; |   ptr=tagname_tab.next; | ||||||
|   while (ptr!=NULL) { |   while (ptr!=NULL) { | ||||||
| @ -4201,7 +4201,7 @@ static void parse_function_type(functag_t *type) | |||||||
|   needtoken(tFUNCTION); |   needtoken(tFUNCTION); | ||||||
| 
 | 
 | ||||||
|   type->ret_tag = parse_new_typename(NULL); |   type->ret_tag = parse_new_typename(NULL); | ||||||
|   type->type = uPUBLIC; |   type->usage = uPUBLIC; | ||||||
| 
 | 
 | ||||||
|   needtoken('('); |   needtoken('('); | ||||||
| 
 | 
 | ||||||
| @ -4370,13 +4370,13 @@ static void dofuncenum(int listmode) | |||||||
|        * rather than the constant value.  And even if we could, we'd have to change the assembler recognize that. |        * rather than the constant value.  And even if we could, we'd have to change the assembler recognize that. | ||||||
|        */ |        */ | ||||||
|       if (l == tPUBLIC) { |       if (l == tPUBLIC) { | ||||||
|         func.type = uPUBLIC; |         func.usage = uPUBLIC; | ||||||
|       } else { |       } else { | ||||||
|         error(1, "-public-", str); |         error(1, "-public-", str); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       func.ret_tag = newStyleTag; |       func.ret_tag = newStyleTag; | ||||||
|       func.type = uPUBLIC; |       func.usage = uPUBLIC; | ||||||
|     } |     } | ||||||
|     needtoken('('); |     needtoken('('); | ||||||
|     do { |     do { | ||||||
|  | |||||||
| @ -413,13 +413,79 @@ static int matchobjecttags(int formaltag, int actualtag, int flags) | |||||||
|   return obj_typeerror(133, formaltag, actualtag); |   return obj_typeerror(133, formaltag, actualtag); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int matchreturntag(functag_t *t, symbol *sym) | static int matchreturntag(const functag_t *formal, const functag_t *actual) | ||||||
| { | { | ||||||
|   if (t->ret_tag == sym->tag) |   if (formal->ret_tag == actual->ret_tag) | ||||||
|     return TRUE; |     return TRUE; | ||||||
|   if (t->ret_tag == pc_tag_void && (sym->tag == 0 && !(sym->usage & uRETVALUE))) |   if (formal->ret_tag == pc_tag_void) { | ||||||
|  |     if (actual->ret_tag == 0 && !(actual->usage & uRETVALUE)) | ||||||
|  |       return TRUE; | ||||||
|  |   } | ||||||
|  |   return FALSE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int funcarg_compare(const funcarg_t *formal, const funcarg_t *actual) | ||||||
|  | { | ||||||
|  |   // Check type.
 | ||||||
|  |   if (actual->ident != formal->ident) | ||||||
|  |     return FALSE; | ||||||
|  | 
 | ||||||
|  |   // Check rank.
 | ||||||
|  |   if (actual->dimcount != formal->dimcount) | ||||||
|  |     return FALSE; | ||||||
|  | 
 | ||||||
|  |   // Check arity.
 | ||||||
|  |   for (int i = 0; i < formal->dimcount; i++) { | ||||||
|  |     if (actual->dims[i] != formal->dims[i]) | ||||||
|  |       return FALSE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Check tags.
 | ||||||
|  |   if (actual->tagcount != formal->tagcount) | ||||||
|  |     return FALSE; | ||||||
|  |   for (int i = 0; i < formal->tagcount; i++) { | ||||||
|  |     // Note we invert the order we pass things to matchtag() here. If the
 | ||||||
|  |     // typedef specifies base type X, and the function specifies derived
 | ||||||
|  |     // type Y, we want this to type since such an assignment is valid.
 | ||||||
|  |     // 
 | ||||||
|  |     // Most programming languages do not subtype arguments like this. We do
 | ||||||
|  |     // it in SourcePawn to preserve compatibility during the Transitional
 | ||||||
|  |     // Syntax effort.
 | ||||||
|  |     int actual_tag = actual->tags[i]; | ||||||
|  |     int formal_tag = formal->tags[i]; | ||||||
|  |     if (!matchtag(actual_tag, formal_tag, MATCHTAG_SILENT|MATCHTAG_COERCE)) | ||||||
|  |       return FALSE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int functag_compare(const functag_t *formal, const functag_t *actual) | ||||||
|  | { | ||||||
|  |   // Check return types.
 | ||||||
|  |   if (!matchreturntag(formal, actual)) | ||||||
|  |     return FALSE; | ||||||
|  | 
 | ||||||
|  |   // Make sure there are no trailing arguments.
 | ||||||
|  |   if (actual->argcount > formal->argcount) | ||||||
|  |     return FALSE; | ||||||
|  | 
 | ||||||
|  |   // Check arguments.
 | ||||||
|  |   for (int i = 0; i < formal->argcount; i++) { | ||||||
|  |     const funcarg_t *formal_arg = &formal->args[i]; | ||||||
|  | 
 | ||||||
|  |     if (i >= actual->argcount) { | ||||||
|  |       if (formal_arg->ommittable) | ||||||
|         return TRUE; |         return TRUE; | ||||||
|       return FALSE; |       return FALSE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const funcarg_t *actual_arg = &actual->args[i]; | ||||||
|  |     if (!funcarg_compare(formal_arg, actual_arg)) | ||||||
|  |       return FALSE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int matchfunctags(int formaltag, int actualtag) | static int matchfunctags(int formaltag, int actualtag) | ||||||
| @ -433,136 +499,18 @@ static int matchfunctags(int formaltag, int actualtag) | |||||||
|   if (!(actualtag & FUNCTAG)) |   if (!(actualtag & FUNCTAG)) | ||||||
|     return FALSE; |     return FALSE; | ||||||
| 
 | 
 | ||||||
|   constvalue *v = find_tag_byval(actualtag); |   functag_t *actual = functag_find_intrinsic(actualtag); | ||||||
|   int index; |   if (!actual) | ||||||
|   short usage = uPUBLIC; |  | ||||||
|   symbol *sym, *found = NULL; |  | ||||||
|   funcenum_t *e; |  | ||||||
|   functag_t *t; |  | ||||||
| 
 |  | ||||||
|   if (strncmp(v->name, "$Func", 5) != 0) |  | ||||||
|     return FALSE; |     return FALSE; | ||||||
| 
 | 
 | ||||||
|   /* Now we have to go about looking up each function in this enum.  WHICH IS IT. */ |   funcenum_t *e = funcenums_find_by_tag(formaltag); | ||||||
|   e = funcenums_find_byval(formaltag); |  | ||||||
|   if (!e) |   if (!e) | ||||||
|     return FALSE; |     return FALSE; | ||||||
| 
 | 
 | ||||||
|   assert(v->name[5] == '@' || v->name[5] == '!'); |   for (functag_t *formal = e->first; formal; formal = formal->next) { | ||||||
| 
 |     if (functag_compare(formal, actual)) | ||||||
|   /* Deduce which function type this is */ |  | ||||||
|   if (v->name[5] == '@') |  | ||||||
|   { |  | ||||||
|     usage = uPUBLIC; |  | ||||||
|   } else if (v->name[5] == '!') { |  | ||||||
|     usage = uSTOCK; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   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 == uSTOCK) { |  | ||||||
|     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 (!matchreturntag(t, sym)) { |  | ||||||
|       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 (!matchtag(func_arg->tags[i], enum_arg->tags[i], MATCHTAG_SILENT|MATCHTAG_COERCE)) { |  | ||||||
|           skip = 1; |  | ||||||
|           break; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (skip) |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     if (!skip) { |  | ||||||
|       /* Make sure there are no trailing arguments */ |  | ||||||
|       if (sym->dim.arglist[curarg].ident == 0) |  | ||||||
|       return TRUE; |       return TRUE; | ||||||
|   } |   } | ||||||
|     t = t->next; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   return FALSE; |   return FALSE; | ||||||
| } | } | ||||||
| @ -2281,48 +2229,36 @@ restart: | |||||||
|   } /* if */ |   } /* if */ | ||||||
|   if (sym!=NULL && lval1->ident==iFUNCTN) { |   if (sym!=NULL && lval1->ident==iFUNCTN) { | ||||||
|     assert(sym->ident==iFUNCTN); |     assert(sym->ident==iFUNCTN); | ||||||
|     if (sc_allowproccall) { | 
 | ||||||
|       // Note: this is unreachable in SourceMod, we don't support paren-less calls.
 |     if (sym->usage & uNATIVE) { | ||||||
|       callfunction(sym,NULL,lval1,FALSE); |       error(76); | ||||||
|     } else if ((sym->usage & uNATIVE) != uNATIVE) { |       return FALSE; | ||||||
|       symbol *oldsym=sym; |     } | ||||||
|       int n=-1,iter=0; | 
 | ||||||
|       int usage = ((sym->usage & uPUBLIC) == uPUBLIC) ? uPUBLIC : 0; |     int public_index = 0; | ||||||
|       cell code_addr=0; |     symbol *target = NULL; | ||||||
|       for (sym=glbtab.next; sym!=NULL; sym=sym->next) { |     for (symbol *iter = glbtab.next; iter; iter = iter->next) { | ||||||
|         if (sym->ident==iFUNCTN && sym->vclass == sGLOBAL && (!usage || (sym->usage & usage))) |       if (iter->ident != iFUNCTN || iter->vclass != sGLOBAL) | ||||||
|         { |         continue; | ||||||
|           if (strcmp(sym->name, lval1->sym->name)==0) { |       if (strcmp(iter->name, lval1->sym->name) == 0) { | ||||||
|             n = iter; |         target = iter; | ||||||
|             code_addr = sym->codeaddr; |  | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|           iter++; |       if (iter->usage & uPUBLIC) | ||||||
|  |         public_index++; | ||||||
|     } |     } | ||||||
|       } | 
 | ||||||
|       if (n!=-1) { |     if (!target || !(target->usage & uPUBLIC)) { | ||||||
|         char faketag[sNAMEMAX+1]; |       error(76); | ||||||
|         lval1->sym=NULL; |  | ||||||
|         lval1->ident=iCONSTEXPR; |  | ||||||
|         /* Generate a quick pseudo-tag! */ |  | ||||||
|         if (usage == uPUBLIC) { |  | ||||||
|           lval1->constval=(n<<1)|1; |  | ||||||
|           snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n); |  | ||||||
|         } else { |  | ||||||
|           lval1->constval=(code_addr<<1)|0; |  | ||||||
|           snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr); |  | ||||||
|           error(153); |  | ||||||
|         } |  | ||||||
|         lval1->tag=pc_addtag_flags(faketag, FIXEDTAG|FUNCTAG); |  | ||||||
|         oldsym->usage |= uREAD; |  | ||||||
|         sym->usage |= uREAD; |  | ||||||
|       } else { |  | ||||||
|         error(76);                /* invalid function call, or syntax error */ |  | ||||||
|       } /* if */ |  | ||||||
|       return FALSE; |       return FALSE; | ||||||
|     } else { |  | ||||||
|       error(76);                  /* invalid function call, or syntax error */ |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     funcenum_t *fe = funcenum_for_symbol(target); | ||||||
|  |     lval1->sym = NULL; | ||||||
|  |     lval1->ident = iCONSTEXPR; | ||||||
|  |     lval1->constval = (public_index << 1) | 1; | ||||||
|  |     lval1->tag = fe->tag; | ||||||
|  |     target->usage |= uREAD; | ||||||
|   } /* if */ |   } /* if */ | ||||||
|   return lvalue; |   return lvalue; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | #include <stdarg.h> | ||||||
| #include "sc.h" | #include "sc.h" | ||||||
| #include "sctracker.h" | #include "sctracker.h" | ||||||
| 
 | 
 | ||||||
| @ -127,12 +128,12 @@ void funcenums_free() | |||||||
|   lastenum = NULL; |   lastenum = NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| funcenum_t *funcenums_find_byval(int value) | funcenum_t *funcenums_find_by_tag(int tag) | ||||||
| { | { | ||||||
|   funcenum_t *e = firstenum; |   funcenum_t *e = firstenum; | ||||||
| 
 | 
 | ||||||
|   while (e) { |   while (e) { | ||||||
|     if (e->value == value) |     if (e->tag == tag) | ||||||
|       return e; |       return e; | ||||||
|     e = e->next; |     e = e->next; | ||||||
|   } |   } | ||||||
| @ -146,7 +147,7 @@ funcenum_t *funcenums_add(const char *name) | |||||||
| 
 | 
 | ||||||
|   memset(e, 0, sizeof(funcenum_t)); |   memset(e, 0, sizeof(funcenum_t)); | ||||||
| 
 | 
 | ||||||
|   if (firstenum == NULL) { |   if (!firstenum) { | ||||||
|     firstenum = e; |     firstenum = e; | ||||||
|     lastenum = e; |     lastenum = e; | ||||||
|   } else { |   } else { | ||||||
| @ -155,11 +156,57 @@ funcenum_t *funcenums_add(const char *name) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   strcpy(e->name, name); |   strcpy(e->name, name); | ||||||
|   e->value = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG); |   e->tag = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG); | ||||||
| 
 | 
 | ||||||
|   return e; |   return e; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | funcenum_t *funcenum_for_symbol(symbol *sym) | ||||||
|  | { | ||||||
|  |   functag_t ft; | ||||||
|  |   memset(&ft, 0, sizeof(ft)); | ||||||
|  | 
 | ||||||
|  |   ft.ret_tag = sym->tag; | ||||||
|  |   ft.usage = uPUBLIC & (sym->usage & uRETVALUE); | ||||||
|  |   ft.argcount = 0; | ||||||
|  |   ft.ommittable = FALSE; | ||||||
|  |   for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) { | ||||||
|  |     funcarg_t *dest = &ft.args[ft.argcount++]; | ||||||
|  | 
 | ||||||
|  |     dest->tagcount = arg->numtags; | ||||||
|  |     memcpy(dest->tags, arg->tags, arg->numtags * sizeof(int)); | ||||||
|  | 
 | ||||||
|  |     dest->dimcount = arg->numdim; | ||||||
|  |     memcpy(dest->dims, arg->dim, arg->numdim * sizeof(int)); | ||||||
|  | 
 | ||||||
|  |     dest->ident = arg->ident; | ||||||
|  |     dest->fconst = !!(arg->usage & uCONST); | ||||||
|  |     dest->ommittable = FALSE; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   char name[METHOD_NAMEMAX+1]; | ||||||
|  |   UTIL_Format(name, sizeof(name), "::ft:%s:%d:%d", sym->name, sym->addr, sym->codeaddr); | ||||||
|  | 
 | ||||||
|  |   funcenum_t *fe = funcenums_add(name); | ||||||
|  |   functags_add(fe, &ft); | ||||||
|  | 
 | ||||||
|  |   return fe; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Finds a functag that was created intrinsically.
 | ||||||
|  | functag_t *functag_find_intrinsic(int tag) | ||||||
|  | { | ||||||
|  |   funcenum_t *fe = funcenums_find_by_tag(tag); | ||||||
|  |   if (!fe) | ||||||
|  |     return NULL; | ||||||
|  | 
 | ||||||
|  |   if (strncmp(fe->name, "::ft:", 5) != 0) | ||||||
|  |     return NULL; | ||||||
|  | 
 | ||||||
|  |   assert(fe->first && fe->first == fe->last); | ||||||
|  |   return fe->first; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| functag_t *functags_add(funcenum_t *en, functag_t *src) | functag_t *functags_add(funcenum_t *en, functag_t *src) | ||||||
| { | { | ||||||
|   functag_t *t = (functag_t *)malloc(sizeof(functag_t)); |   functag_t *t = (functag_t *)malloc(sizeof(functag_t)); | ||||||
| @ -550,3 +597,18 @@ int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2) | |||||||
|   } |   } | ||||||
|   return FALSE; |   return FALSE; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) | ||||||
|  | { | ||||||
|  |   va_list ap; | ||||||
|  | 
 | ||||||
|  |   va_start(ap, fmt); | ||||||
|  |   size_t len = vsnprintf(buffer, maxlength, fmt, ap); | ||||||
|  |   va_end(ap); | ||||||
|  | 
 | ||||||
|  |   if (len >= maxlength) { | ||||||
|  |     buffer[maxlength - 1] = '\0'; | ||||||
|  |     return maxlength - 1; | ||||||
|  |   } | ||||||
|  |   return len; | ||||||
|  | } | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ typedef struct funcarg_s | |||||||
| typedef struct functag_s | typedef struct functag_s | ||||||
| { | { | ||||||
|   int ret_tag; |   int ret_tag; | ||||||
|   int type; |   int usage; | ||||||
|   int argcount; |   int argcount; | ||||||
|   int ommittable; |   int ommittable; | ||||||
|   funcarg_t args[sARGS_MAX]; |   funcarg_t args[sARGS_MAX]; | ||||||
| @ -40,8 +40,8 @@ typedef struct functag_s | |||||||
| 
 | 
 | ||||||
| typedef struct funcenum_s | typedef struct funcenum_s | ||||||
| { | { | ||||||
|   int value; |   int tag; | ||||||
|   char name[sNAMEMAX+1]; |   char name[METHOD_NAMEMAX+1]; | ||||||
|   functag_t *first; |   functag_t *first; | ||||||
|   functag_t *last; |   functag_t *last; | ||||||
|   struct funcenum_s *next; |   struct funcenum_s *next; | ||||||
| @ -116,8 +116,10 @@ structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member); | |||||||
|  */ |  */ | ||||||
| void funcenums_free(); | void funcenums_free(); | ||||||
| funcenum_t *funcenums_add(const char *name); | funcenum_t *funcenums_add(const char *name); | ||||||
| funcenum_t *funcenums_find_byval(int value); | funcenum_t *funcenums_find_by_tag(int tag); | ||||||
| functag_t *functags_add(funcenum_t *en, functag_t *src); | functag_t *functags_add(funcenum_t *en, functag_t *src); | ||||||
|  | funcenum_t *funcenum_for_symbol(symbol *sym); | ||||||
|  | functag_t *functag_find_intrinsic(int tag); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Given a name or tag, find any extra weirdness it has associated with it. |  * Given a name or tag, find any extra weirdness it has associated with it. | ||||||
| @ -167,4 +169,6 @@ void methodmaps_free(); | |||||||
| extern memuse_list_t *heapusage; | extern memuse_list_t *heapusage; | ||||||
| extern memuse_list_t *stackusage; | extern memuse_list_t *stackusage; | ||||||
| 
 | 
 | ||||||
|  | size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); | ||||||
|  | 
 | ||||||
| #endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
 | #endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user