Refactor matchtag() to not be insane.

This commit is contained in:
David Anderson 2014-06-16 01:31:00 -07:00
parent 4ede6343b0
commit 6ba9e004fb

View File

@ -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; 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 (!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;
}
}
} /* if */
return TRUE;
}
return FALSE;
}
/*