From 6ba9e004fbae18ad68056368ddd0affdc78659f1 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 16 Jun 2014 01:31:00 -0700 Subject: [PATCH] Refactor matchtag() to not be insane. --- sourcepawn/compiler/sc3.c | 331 ++++++++++++++++++-------------------- 1 file changed, 160 insertions(+), 171 deletions(-) diff --git a/sourcepawn/compiler/sc3.c b/sourcepawn/compiler/sc3.c index 4d2eb0470..ab2a144f4 100644 --- a/sourcepawn/compiler/sc3.c +++ b/sourcepawn/compiler/sc3.c @@ -321,191 +321,180 @@ SC_FUNC int matchtag_string(int ident, int tag) return (tag == pc_tag_string) ? TRUE : FALSE; } -SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce) +SC_FUNC int matchtag(int formaltag, int actualtag, int allowcoerce) { - if (formaltag != actualtag) { - /* 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 (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 && !(actualtag & FIXEDTAG)) + return TRUE; + + if (formaltag == pc_anytag || actualtag == pc_anytag) + return TRUE; + + 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; + 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] == '@') { - return TRUE; + usage = uPUBLIC; + } else if (v->name[5] == '!') { + usage = uSTOCK; } - if (formaltag & FUNCTAG) + index = atoi(&v->name[6]); + + assert(index >= 0); + + /* Find the function, either by public idx or code addr */ + if (usage == uPUBLIC) { - 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) + for (sym=glbtab.next; sym!=NULL; sym=sym->next) { + if (sym->ident==iFUNCTN && (sym->usage & uPUBLIC)!=0 && (sym->vclass == sGLOBAL)) { - 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 = 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 (t->ret_tag != sym->tag) + if (index-- == 0) { - t = t->next; - continue; + found = sym; + break; } - /* Check usage */ - if (t->type != usage) + } + } + } else if (usage == uSTOCK) { + for (sym=glbtab.next; sym!=NULL; sym=sym->next) { + if (sym->ident==iFUNCTN && (sym->vclass == sGLOBAL)) + { + if (sym->codeaddr == index) { - t = t->next; - continue; + found = sym; + break; } - /* Begin iterating arguments */ - for (curarg=0; curargargcount; 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; idimcount; 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; itagcount; 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 (!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; curargargcount; 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; idimcount; 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; itagcount; 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; + } } - } /* if */ - return TRUE; + } + + return FALSE; } /*