/* If we have an enum-valued group attribute, then we need to do extra work to find the containing enum type */ static Symbol* locateenumtype(Symbol* refsym, Symbol* parent, NCConstant* con) { Symbol* match = NULL; List* grpmatches; /* Locate all possible matching enum constant definitions */ List* candidates = findecmatches(refsym->name); if(candidates == NULL) { semerror(con->lineno,"Undefined enum or enum constant reference: %s",refsym->name); return NULL; } /* One hopes that 99% of the time, the match is unique */ if(listlength(candidates) == 1) { match = listget(candidates,0); goto done; } /* If this ref has a specified group prefix, then find that group and search only within it for matches to the candidates */ if(refsym->is_prefixed && refsym->prefix != NULL) { parent = lookupgroup(refsym->prefix); if(parent == NULL) { semerror(con->lineno,"Undefined group reference: ",fullname(refsym)); goto done; } /* Search this group only for matches */ grpmatches = ecsearchgrp(parent,candidates); switch (listlength(grpmatches)) { case 0: semerror(con->lineno,"Undefined enum or enum constant reference: ",refsym->name); listfree(grpmatches); goto done; case 1: break; default: semerror(con->lineno,"Ambiguous enum constant reference: %s", fullname(refsym)); } match = listget(grpmatches,0); listfree(grpmatches); goto done; } /* Sigh, we have to search up the tree to see if any of our candidates are there */ assert(parent == NULL || parent->objectclass == NC_GRP); while(parent != NULL && match == NULL) { grpmatches = ecsearchgrp(parent,candidates); switch (listlength(grpmatches)) { case 0: break; case 1: match = listget(grpmatches,0); break; default: semerror(con->lineno,"Ambiguous enum constant reference: %s", fullname(refsym)); match = listget(grpmatches,0); break; } listfree(grpmatches); } if(match != NULL) goto done; /* Not unique and not in the parent tree, so complains and pick the first candidate */ semerror(con->lineno,"Ambiguous enum constant reference: %s", fullname(refsym)); match = (Symbol*)listget(candidates,0); done: listfree(candidates); return match; }
Symbol* locate(Symbol* refsym) { Symbol* sym = NULL; switch (refsym->objectclass) { case NC_DIM: if(refsym->is_prefixed) { /* locate exact dimension specified*/ sym = lookup(NC_DIM,refsym); } else { /* Search for matching dimension in all parent groups*/ Symbol* parent = lookupgroup(refsym->prefix);/*get group for refsym*/ while(parent != NULL) { /* search this parent for matching name and type*/ sym = lookupingroup(NC_DIM,refsym->name,parent); if(sym != NULL) break; parent = parent->container; } } break; case NC_TYPE: if(refsym->is_prefixed) { /* locate exact type specified*/ sym = lookup(NC_TYPE,refsym); } else { Symbol* parent; int i; /* Search for matching type in all groups (except...)*/ /* Short circuit test for primitive types*/ for(i=NC_NAT;i<=NC_STRING;i++) { Symbol* prim = basetypefor(i); if(prim == NULL) continue; if(strcmp(refsym->name,prim->name)==0) { sym = prim; break; } } if(sym == NULL) { /* Added 5/26/09: look in parent hierarchy first */ parent = lookupgroup(refsym->prefix);/*get group for refsym*/ while(parent != NULL) { /* search this parent for matching name and type*/ sym = lookupingroup(NC_TYPE,refsym->name,parent); if(sym != NULL) break; parent = parent->container; } } if(sym == NULL) { sym = uniquetreelocate(refsym,rootgroup); /* want unique */ } } break; case NC_VAR: if(refsym->is_prefixed) { /* locate exact variable specified*/ sym = lookup(NC_VAR,refsym); } else { Symbol* parent = lookupgroup(refsym->prefix);/*get group for refsym*/ /* search this parent for matching name and type*/ sym = lookupingroup(NC_VAR,refsym->name,parent); } break; case NC_GRP: if(refsym->is_prefixed) { /* locate exact group specified*/ sym = lookup(NC_GRP,refsym); } else { Symbol* parent = lookupgroup(refsym->prefix);/*get group for refsym*/ /* search this parent for matching name and type*/ sym = lookupingroup(NC_GRP,refsym->name,parent); } break; default: PANIC1("locate: bad refsym type: %d",refsym->objectclass); } if(debug > 1) { char* ncname; if(refsym->objectclass == NC_TYPE) ncname = ncclassname(refsym->subclass); else ncname = ncclassname(refsym->objectclass); fdebug("locate: %s: %s -> %s\n", ncname,fullname(refsym),(sym?fullname(sym):"NULL")); } return sym; }