#include "compiler.h" #include "compiler/CError.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CPrep.h" #include "compiler/CScope.h" #include "compiler/enode.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/templates.h" #include "compiler/types.h" static Boolean cscope_isambig; static UInt8 cscope_lookuptype; static SInt32 cscope_foundclassoffset; static TemplClass *cscope_foundtemplate; static TypeClass *cscope_foundclass; static HashNameNode *cscope_name; static TypeClass *cscope_mostderived; Boolean cscope_is_member_func; Object *cscope_currentfunc; TypeClass *cscope_currentclass; NameSpace *cscope_current; NameSpace *cscope_root; void CScope_Setup() { cscope_current = cscope_root = CScope_NewHashNameSpace(0); cscope_currentclass = NULL; cscope_currentfunc = NULL; cscope_is_member_func = 0; } void CScope_Cleanup() { } void CScope_GetScope(CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; } void CScope_SetNameSpaceScope(NameSpace *nspace, CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; cscope_current = nspace; cscope_currentclass = nspace->theclass; cscope_currentfunc = NULL; cscope_is_member_func = 0; } void CScope_SetClassScope(TypeClass *cls, CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; cscope_current = cls->nspace; cscope_currentclass = cls; cscope_currentfunc = NULL; cscope_is_member_func = 0; } void CScope_SetClassDefScope(TypeClass *cls, CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; cscope_current = cls->nspace; cscope_currentclass = cls; } void CScope_SetFunctionScope(Object *function, CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; cscope_currentfunc = function; cscope_currentclass = NULL; cscope_is_member_func = 0; if (TYPE_FUNC(function->type)->flags & FUNC_FLAGS_METHOD) { cscope_currentclass = TYPE_METHOD(function->type)->theclass; cscope_current = cscope_currentclass->nspace; cscope_is_member_func = TYPE_METHOD(function->type)->x26 == 0; } else { cscope_current = function->nspace; } } void CScope_SetMethodScope(Object *function, TypeClass *cls, Boolean is_static, CScopeSave *save) { save->current = cscope_current; save->currentclass = cscope_currentclass; save->currentfunc = cscope_currentfunc; save->is_member_func = cscope_is_member_func; cscope_currentfunc = function; cscope_currentclass = cls; cscope_current = cls->nspace; cscope_is_member_func = !is_static; } void CScope_RestoreScope(CScopeSave *saved) { cscope_current = saved->current; cscope_currentclass = saved->currentclass; cscope_currentfunc = saved->currentfunc; cscope_is_member_func = saved->is_member_func; } static Boolean CScope_ObjectIsFunction(Object *obj) { return obj->otype == OT_OBJECT && obj->type->type == TYPEFUNC; } Boolean CScope_IsEmptySymTable() { NameSpaceObjectList *scan; NameSpaceName *nsname; int i; #line 232 CError_ASSERT(cscope_root->is_hash); i = 0; do { for (nsname = cscope_root->data.hash[i]; nsname; nsname = nsname->next) { for (scan = &nsname->first; scan; scan = scan->next) { if (scan->object->otype != OT_OBJECT || !CParser_IsPublicRuntimeObject(OBJECT(scan->object))) return 0; } } } while (++i < 1024); return 1; } Boolean CScope_IsInLocalNameSpace(NameSpace *nspace) { while (nspace) { if (!nspace->is_global && !nspace->is_templ) return 1; nspace = nspace->parent; } return 0; } static void CScope_AppendNameSpaceName(NameSpaceName *nsn) { if (nsn->next) CScope_AppendNameSpaceName(nsn->next); if (nsn->name) { AppendGListName(&name_mangle_list, nsn->name->name); AppendGListName(&name_mangle_list, "::"); } } static void CScope_AmbigNameError(NameSpace *nspace1, NameSpace *nspace2, HashNameNode *name) { if (name && nspace1 != nspace2) { CError_Error(319, CError_GetNameString(nspace1, name), CError_GetNameString(nspace2, name)); } else { CError_Error(188, nspace2); } } NameSpaceObjectList *CScope_FindName(NameSpace *nspace, HashNameNode *name) { NameSpaceName *scan; for (scan = nspace->tparams; scan; scan = scan->next) { if (scan->name == name) return &scan->first; } if (!nspace->is_hash) scan = nspace->data.list; else scan = nspace->data.hash[name->hashval & 1023]; for (; scan; scan = scan->next) { if (scan->name == name) return &scan->first; } return NULL; } static NameSpaceObjectList *CScope_FindQualName(NameSpace *nspace, HashNameNode *name) { NameSpaceName *scan; if (!nspace->is_hash) scan = nspace->data.list; else scan = nspace->data.hash[name->hashval & 1023]; for (; scan; scan = scan->next) { if (scan->name == name) return &scan->first; } return NULL; } NameSpaceName *CScope_FindNameSpaceName(NameSpace *nspace, HashNameNode *name) { NameSpaceName *scan; for (scan = nspace->tparams; scan; scan = scan->next) { if (scan->name == name) return scan; } if (!nspace->is_hash) scan = nspace->data.list; else scan = nspace->data.hash[name->hashval & 1023]; for (; scan; scan = scan->next) { if (scan->name == name) return scan; } return NULL; } NameSpaceObjectList *CScope_InsertName(NameSpace *nspace, HashNameNode *name) { NameSpaceName **nsnptr; NameSpaceName *nsname; if (nspace->is_global) nsname = galloc(sizeof(NameSpaceName)); else nsname = lalloc(sizeof(NameSpaceName)); nsname->name = name; nsname->first.next = NULL; nsname->first.object = NULL; if (nspace->is_hash) { nsnptr = &nspace->data.hash[name->hashval & 0x3FF]; nsname->next = *nsnptr; *nsnptr = nsname; } else { nsname->next = nspace->data.list; nspace->data.list = nsname; } nspace->names++; return &nsname->first; } static NameSpaceObjectList *CScope_AppendName(NameSpace *nspace, HashNameNode *name) { NameSpaceName *nsname; NameSpaceName *scan; #line 387 CError_ASSERT(!nspace->is_hash); if (nspace->is_global) nsname = galloc(sizeof(NameSpaceName)); else nsname = lalloc(sizeof(NameSpaceName)); nsname->next = NULL; nsname->name = name; nsname->first.next = NULL; nsname->first.object = NULL; if (nspace->data.list) { scan = nspace->data.list; while (scan->next) scan = scan->next; scan->next = nsname; } else { nspace->data.list = nsname; } nspace->names++; return &nsname->first; } static NameSpaceList *CScope_AddNameSpaceToList(NameSpaceList *list, NameSpace *nspace) { NameSpaceList *scan; NameSpaceList *newlist; ClassList *clslist; for (scan = list; scan; scan = scan->next) { if (scan->nspace == nspace) return list; } newlist = lalloc(sizeof(NameSpaceList)); newlist->next = list; newlist->nspace = nspace; list = newlist; if (nspace->theclass) { list = CScope_AddNameSpaceToList(list, nspace->parent); for (clslist = nspace->theclass->bases; clslist; clslist = clslist->next) list = CScope_AddNameSpaceToList(list, clslist->base->nspace); } return list; } static NameSpaceList *CScope_BuildTypeAssociatedNameSpaceList(NameSpaceList *list, Type *type) { FuncArg *arg; restart: switch (type->type) { case TYPEVOID: case TYPEINT: case TYPEFLOAT: case TYPESTRUCT: case TYPEBITFIELD: case TYPETEMPLATE: case TYPETEMPLDEPEXPR: break; case TYPEPOINTER: case TYPEARRAY: type = TYPE_POINTER(type)->target; goto restart; case TYPEENUM: list = CScope_AddNameSpaceToList(list, TYPE_ENUM(type)->nspace); break; case TYPEFUNC: for (arg = TYPE_FUNC(type)->args; arg; arg = arg->next) { if (arg->type) list = CScope_BuildTypeAssociatedNameSpaceList(list, arg->type); } type = TYPE_FUNC(type)->functype; goto restart; case TYPEMEMBERPOINTER: list = CScope_BuildTypeAssociatedNameSpaceList(list, TYPE_MEMBER_POINTER(type)->ty1); type = TYPE_MEMBER_POINTER(type)->ty2; if (type->type != TYPECLASS) break; case TYPECLASS: list = CScope_AddNameSpaceToList(list, TYPE_CLASS(type)->nspace); break; default: #line 494 CError_FATAL(); } return list; } static NameSpaceList *CScope_BuildAssociatedNameSpaceList(ENodeList *enodeList) { // not 100% sure about the type for this but i think it's right?? NameSpaceList *nslist = NULL; while (enodeList) { nslist = CScope_BuildTypeAssociatedNameSpaceList(nslist, enodeList->node->rtype); enodeList = enodeList->next; } return nslist; } static Boolean CScope_IsSameObject(Object *a, Object *b) { if (a == b) return 1; return (a->nspace == b->nspace) && (a->name == b->name) && is_typesame(a->type, b->type); } NameSpaceObjectList *CScope_ArgumentDependentNameLookup(NameSpaceObjectList *list, HashNameNode *name, ENodeList *argNodes, Boolean flag) { NameSpaceList *scan; NameSpaceObjectList *iscan; NameSpaceObjectList *iiscan; NameSpaceObjectList *newlist; for (scan = CScope_BuildAssociatedNameSpaceList(argNodes); scan; scan = scan->next) { for (iscan = CScope_FindQualName(scan->nspace, name); iscan; iscan = iscan->next) { if (iscan->object->otype != OT_OBJECT) continue; if (OBJECT(iscan->object)->type->type != TYPEFUNC) continue; if (flag && (TYPE_FUNC(OBJECT(iscan->object)->type)->flags & FUNC_FLAGS_METHOD)) continue; for (iiscan = list; iiscan; iiscan = iiscan->next) { if (iiscan->object->otype == OT_OBJECT && CScope_IsSameObject(OBJECT(iiscan->object), OBJECT(iscan->object))) break; } if (!iiscan) { newlist = lalloc(sizeof(NameSpaceObjectList)); newlist->object = iscan->object; newlist->next = list; list = newlist; } } } return list; } NameSpace *CScope_NewHashNameSpace(HashNameNode *name) { NameSpace *nspace; void *buffer; buffer = galloc(0x400 * sizeof(void *)); memclrw(buffer, 0x400 * sizeof(void *)); nspace = galloc(sizeof(NameSpace)); memclrw(nspace, sizeof(NameSpace)); nspace->name = name; nspace->data.hash = buffer; nspace->is_hash = 1; nspace->is_global = 1; return nspace; } NameSpace *CScope_NewListNameSpace(HashNameNode *name, Boolean is_global) { NameSpace *nspace; if (is_global) { nspace = galloc(sizeof(NameSpace)); memclrw(nspace, sizeof(NameSpace)); } else { nspace = lalloc(sizeof(NameSpace)); memclrw(nspace, sizeof(NameSpace)); } nspace->name = name; nspace->is_hash = 0; nspace->is_global = is_global; return nspace; } NameSpace *CScope_FindNonClassNonFunctionNS(NameSpace *nspace) { while (nspace) { if (!nspace->theclass && !nspace->is_templ) return nspace; nspace = nspace->parent; } return cscope_root; } NameSpace *CScope_FindGlobalNS(NameSpace *nspace) { while (nspace) { if (nspace->name && !nspace->theclass && nspace->is_global) return nspace; nspace = nspace->parent; } return cscope_root; } Boolean CScope_IsStdNameSpace(NameSpace *nspace) { return nspace && !nspace->theclass && (nspace->parent == cscope_root) && nspace->name && !strcmp(nspace->name->name, "std"); } Boolean CScope_IsEmptyNameSpace(NameSpace *nspace) { #line 664 CError_ASSERT(!nspace->is_hash); return !nspace->data.list; } void CScope_MergeNameSpace(NameSpace *dst, NameSpace *src) { NameSpaceName *nsname; #line 678 CError_ASSERT(!dst->is_hash && !src->is_hash); if ((nsname = dst->data.list)) { while (nsname->next) nsname = nsname->next; nsname->next = src->data.list; } else { dst->data.list = src->data.list; } } void CScope_AddObject(NameSpace *nspace, HashNameNode *name, ObjBase *obj) { NameSpaceObjectList *objlist; NameSpaceObjectList *newlist; objlist = CScope_FindQualName(nspace, name); if (objlist) { if (nspace->is_global) newlist = galloc(sizeof(NameSpaceObjectList)); else newlist = lalloc(sizeof(NameSpaceObjectList)); if (obj->otype == OT_NAMESPACE || objlist->object->otype == OT_NAMESPACE) { CError_Error(322/*, objlist->object*/); return; } if (obj->otype == OT_TYPETAG) { do { if (objlist->object->otype == OT_TYPETAG) { CError_Error(322/*, objlist->object*/); return; } if (copts.cplusplus && objlist->object->otype == OT_TYPE && !is_typesame(OBJ_TYPE_TAG(obj)->type, OBJ_TYPE(objlist->object)->type)) { CError_Error(332); return; } if (!objlist->next) { objlist->next = newlist; newlist->next = NULL; newlist->object = obj; return; } objlist = objlist->next; } while (1); } if (objlist->object->otype == OT_TYPETAG) { if (copts.cplusplus && obj->otype == OT_TYPE && !is_typesame(OBJ_TYPE(obj)->type, OBJ_TYPE_TAG(objlist->object)->type)) { CError_Error(332); return; } #line 739 CError_ASSERT(!objlist->next); newlist->object = objlist->object; newlist->next = NULL; objlist->object = obj; objlist->next = newlist; return; } if (!copts.cplusplus || !CScope_ObjectIsFunction(OBJECT(obj))) { CError_Error(322); return; } do { if (objlist->object->otype == OT_TYPETAG) { objlist->next = galloc(sizeof(NameSpaceObjectList)); objlist->next->next = NULL; objlist->next->object = objlist->object; objlist->object = obj; return; } if (!CScope_ObjectIsFunction(OBJECT(objlist->object))) { CError_Error(322); return; } if (!objlist->next) { objlist->next = galloc(sizeof(NameSpaceObjectList)); objlist->next->next = NULL; objlist->next->object = obj; return; } objlist = objlist->next; } while (1); } else if (nspace->theclass && TYPE_CLASS(nspace->theclass)->flags & CLASS_FLAGS_900) { CScope_AppendName(nspace, name)->object = obj; } else { CScope_InsertName(nspace, name)->object = obj; } } void CScope_AddGlobalObject(Object *obj) { obj->nspace = cscope_root; CScope_AddObject(cscope_root, obj->name, OBJ_BASE(obj)); } NameSpaceLookupList *CScope_BuildNameSpaceLookupList(NameSpace *nspace) { NameSpaceLookupList *lookup; NameSpaceList list; NameSpaceList *current; NameSpaceList *current2; NameSpaceList *current3; NameSpaceList *newlist; NameSpaceLookupList *currentL; NameSpace *currentNS; lookup = lalloc(sizeof(NameSpaceLookupList)); memclrw(lookup, sizeof(NameSpaceLookupList)); lookup->nspace = nspace; if (nspace->parent) lookup->next = CScope_BuildNameSpaceLookupList(nspace->parent); if (nspace->usings) { list.nspace = nspace; list.next = NULL; for (current2 = &list; current2; current2 = current2->next) { for (current = current2->nspace->usings; current; current = current->next) { for (current3 = &list; current3; current3 = current3->next) { if (current3->nspace == current->nspace) break; } if (!current3) { newlist = lalloc(sizeof(NameSpaceList)); newlist->nspace = current->nspace; newlist->next = current2->next; current2->next = newlist; } } } for (current = list.next; current; current = current->next) { for (currentL = lookup; currentL; currentL = currentL->next) { for (currentNS = current->nspace; currentNS; currentNS = currentNS->parent) { if (currentL->nspace == currentNS) goto foundIt; } } #line 853 CError_FATAL(); foundIt: for (current2 = currentL->namespaces; current2; current2 = current2->next) { if (current2->nspace == current->nspace) break; } if (!current2) { newlist = lalloc(sizeof(NameSpaceList)); newlist->nspace = current->nspace; newlist->next = currentL->namespaces; currentL->namespaces = newlist; } } } return lookup; } static Boolean CScope_IsInLookup(NameSpaceLookupList *list, NameSpace *nspace) { NameSpaceLookupList *scan; NameSpaceList *iscan; for (scan = list; scan; scan = scan->next) { if (scan->nspace == nspace) return 1; for (iscan = scan->namespaces; iscan; iscan = iscan->next) { if (iscan->nspace == nspace) return 1; } } return 0; } static NameSpaceLookupList *CScope_BuildNameSpaceMemberLookupList(NameSpace *nspace) { NameSpaceLookupList list; NameSpaceLookupList *current; NameSpaceList *scan; NameSpaceList *oscan; NameSpaceList *newlist; list.nspace = nspace; list.namespaces = NULL; list.next = NULL; for (current = &list; current; current = current->next) { if (current->nspace) { for (scan = current->nspace->usings; scan; scan = scan->next) { if (!CScope_IsInLookup(&list, scan->nspace)) { if (!current->next) { current->next = lalloc(sizeof(NameSpaceLookupList)); current->next->nspace = NULL; current->next->namespaces = NULL; current->next->next = NULL; } newlist = lalloc(sizeof(NameSpaceList)); newlist->nspace = scan->nspace; newlist->next = current->next->namespaces; current->next->namespaces = newlist; } } } for (oscan = current->namespaces; oscan; oscan = oscan->next) { for (scan = oscan->nspace->usings; scan; scan = scan->next) { if (!CScope_IsInLookup(&list, scan->nspace)) { if (!current->next) { current->next = lalloc(sizeof(NameSpaceLookupList)); current->next->nspace = NULL; current->next->namespaces = NULL; current->next->next = NULL; } newlist = lalloc(sizeof(NameSpaceList)); newlist->nspace = scan->nspace; newlist->next = current->next->namespaces; current->next->namespaces = newlist; } } } } return list.next; } static NameSpaceObjectList *CScope_CopyNameSpaceObjectList(NameSpaceObjectList *list) { NameSpaceObjectList *first, *current; first = current = lalloc(sizeof(NameSpaceObjectList)); do { current->object = list->object; list = list->next; if (!list) { current->next = NULL; break; } else { current->next = lalloc(sizeof(NameSpaceObjectList)); current = current->next; } } while (1); return first; } static NameSpace *CScope_ExtractNameSpace(NameSpaceObjectList *list, Boolean *fail) { Type *type; restart: if (!list) return NULL; switch (list->object->otype) { case OT_TYPE: type = OBJ_TYPE(list->object)->type; break; case OT_TYPETAG: type = OBJ_TYPE_TAG(list->object)->type; break; case OT_NAMESPACE: return OBJ_NAMESPACE(list->object)->nspace; default: #line 1052 CError_FATAL(); break; case OT_ENUMCONST: case OT_MEMBERVAR: case OT_OBJECT: list = list->next; goto restart; } if (type->type != TYPECLASS) { if (type->type == TYPETEMPLATE) return NULL; CError_Error(320); if (fail) *fail = 1; return NULL; } else { return TYPE_CLASS(type)->nspace; } } static BClassList *CScope_RecFindClassMember(CScopeParseResult *result, TypeClass *tclass, SInt32 offset) { // does not match, r24 and r23 are swapped at the end x.x Boolean fail; NameSpace *nspace; NameSpaceObjectList *list; ClassList *base; TypeClass *bestClass; BClassList *bestBase, *n; BClassList *candidate; SInt32 thisoffset; BClassList *newlist; if ((list = CScope_FindName(tclass->nspace, cscope_name))) { if (cscope_foundclass) { if (CClass_ClassDominates(cscope_foundclass, tclass)) return NULL; if (CClass_ClassDominates(tclass, cscope_foundclass)) cscope_foundclass = NULL; } switch (cscope_lookuptype) { case 2: fail = 0; if ((nspace = CScope_ExtractNameSpace(list, &fail))) { if (cscope_foundclass) { if (cscope_foundclass != tclass) { CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name); return NULL; } if (cscope_foundclassoffset != offset) cscope_isambig = 1; return NULL; } cscope_foundclass = tclass; cscope_foundclassoffset = offset; result->nspace_0 = nspace; newlist = lalloc(sizeof(BClassList)); newlist->next = NULL; newlist->type = (Type *) tclass; return newlist; } if (fail) return NULL; break; case 0: if (cscope_foundclass) { if ( list->object->otype == OT_TYPETAG && result->nsol_14->object->otype == OT_TYPETAG && OBJ_TYPE_TAG(list->object)->type->type == TYPECLASS && OBJ_TYPE_TAG(result->nsol_14->object)->type->type == TYPECLASS && (TYPE_CLASS(OBJ_TYPE_TAG(list->object)->type)->flags & CLASS_FLAGS_800) && (TYPE_CLASS(OBJ_TYPE_TAG(result->nsol_14->object)->type)->flags & CLASS_FLAGS_800) && TEMPL_CLASS_INST(OBJ_TYPE_TAG(list->object)->type)->templ == TEMPL_CLASS_INST(OBJ_TYPE_TAG(result->nsol_14->object)->type)->templ ) { cscope_foundtemplate = TEMPL_CLASS_INST(OBJ_TYPE_TAG(result->nsol_14->object)->type)->templ; } else { if (cscope_foundclass != tclass) { CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name); return NULL; } if (cscope_foundclassoffset != offset) { cscope_isambig = 1; return NULL; } } } cscope_foundclass = tclass; cscope_foundclassoffset = offset; result->nsol_14 = list; newlist = lalloc(sizeof(BClassList)); newlist->next = NULL; newlist->type = (Type *) tclass; return newlist; case 1: for (; list; list = list->next) { if (list->object->otype == OT_TYPETAG) { if (cscope_foundclass) { if (cscope_foundclass != tclass) { CScope_AmbigNameError(cscope_foundclass->nspace, tclass->nspace, cscope_name); return NULL; } if (cscope_foundclassoffset != offset) cscope_isambig = 1; return NULL; } cscope_foundclass = tclass; cscope_foundclassoffset = offset; result->x8 = OBJ_TYPE_TAG(list->object)->type; newlist = lalloc(sizeof(BClassList)); newlist->next = NULL; newlist->type = (Type *) tclass; return newlist; } } break; default: #line 1202 CError_FATAL(); } } for (base = tclass->bases, bestBase = NULL; base; base = base->next) { thisoffset = base->is_virtual ? CClass_VirtualBaseOffset(cscope_mostderived, base->base) : offset + base->offset; if ((candidate = CScope_RecFindClassMember(result, base->base, thisoffset))) { n = lalloc(sizeof(BClassList)); n->next = candidate; n->type = (Type *) tclass; if (bestBase && bestClass == cscope_foundclass) { if (CClass_IsMoreAccessiblePath(n, bestBase)) bestBase = n; } else { bestClass = cscope_foundclass; bestBase = n; } } } return bestBase; } static Boolean CScope_FindClassMember(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name, UInt8 lookupType) { BClassList *bcl; BClassList *scan; cscope_mostderived = nspace->theclass; cscope_foundclass = NULL; cscope_foundtemplate = NULL; cscope_name = name; cscope_lookuptype = lookupType; cscope_isambig = 0; if ((bcl = CScope_RecFindClassMember(result, cscope_mostderived, 0))) { if (cscope_foundtemplate) return 1; if ((scan = result->bcl_18)) { while (scan->next) scan = scan->next; if (TYPE_CLASS(scan->type) != cscope_mostderived) scan->next = bcl; else scan->next = bcl->next; } else { result->bcl_18 = bcl; } if (cscope_isambig) result->isambig = 1; return 1; } else { return 0; } } static BClassList *CScope_GetAccessPathRec(TypeClass *src, TypeClass *dest, SInt32 offset) { BClassList *list; BClassList *best; ClassList *base; if (src == dest) { if (cscope_foundclass && cscope_foundclassoffset != offset) CError_Error(188); list = lalloc(sizeof(BClassList)); list->next = NULL; list->type = (Type *) src; cscope_foundclass = src; cscope_foundclassoffset = offset; return list; } for (base = src->bases, best = NULL; base; base = base->next) { if ((list = CScope_GetAccessPathRec(base->base, dest, base->is_virtual ? CClass_VirtualBaseOffset(cscope_mostderived, base->base) : (offset + base->offset)))) best = list; } if (best) { list = lalloc(sizeof(BClassList)); list->next = best; list->type = (Type *) src; return list; } return NULL; } static BClassList *CScope_GetAccessPath(TypeClass *src, TypeClass *dest) { cscope_mostderived = src; cscope_foundclass = NULL; return CScope_GetAccessPathRec(src, dest, 0); } static NameSpace *CScope_FindLookupNameSpace(CScopeNSIterator *iterator, NameSpaceLookupList *lookup, HashNameNode *name) { NameSpaceObjectList *list; NameSpaceList *scan; NameSpace *retnspace = NULL; NameSpace *candidate; Boolean fail = 0; if (lookup->nspace->theclass) { if (CScope_FindClassMember(iterator->result, lookup->nspace, name, 2)) { retnspace = iterator->result->nspace_0; iterator->result->nspace_0 = NULL; return retnspace; } else { return NULL; } } if ((list = CScope_FindName(lookup->nspace, name))) { fail = 0; retnspace = CScope_ExtractNameSpace(list, &fail); if (fail) return NULL; } for (scan = lookup->namespaces; scan; scan = scan->next) { fail = 0; if ((list = CScope_FindName(scan->nspace, name)) && (candidate = CScope_ExtractNameSpace(list, &fail))) { if (retnspace) { if (retnspace != candidate) CScope_AmbigNameError(retnspace, candidate, NULL); } else { retnspace = candidate; } } if (fail) return NULL; } return retnspace; } static NameSpaceObjectList *CScope_FindLookupName(NameSpaceLookupList *list, HashNameNode *name, NameSpace **foundnspace) { NameSpaceName *scanname; NameSpaceObjectList *tmpOL; NameSpaceObjectList *r31; NameSpaceObjectList *r30; NameSpaceList *r29; NameSpace *r28; Boolean r27; NameSpaceObjectList *r6; NameSpaceObjectList *scanOL; NameSpaceObjectList *newlist; if (list->nspace) { for (scanname = list->nspace->tparams; scanname; scanname = scanname->next) { if (scanname->name == name) return &scanname->first; } if ((tmpOL = CScope_FindName(list->nspace, name))) { r31 = tmpOL; r28 = list->nspace; } else { r31 = NULL; r28 = NULL; } } else { r31 = NULL; r28 = NULL; } r27 = 0; for (r29 = list->namespaces; r29; r29 = r29->next) { if ((tmpOL = CScope_FindName(r29->nspace, name))) { if (r31) { for (r30 = tmpOL; r30; r30 = r30->next) { for (r6 = r31; r6; r6 = r6->next) { if (r6->object == r30->object) break; if (r6->object->otype == r30->object->otype) { switch (r6->object->otype) { case OT_TYPE: if ((OBJ_TYPE(r6->object)->type == OBJ_TYPE(r30->object)->type) && (OBJ_TYPE(r6->object)->qual == OBJ_TYPE(r30->object)->qual)) goto break1; break; case OT_TYPETAG: if (OBJ_TYPE_TAG(r6->object)->type == OBJ_TYPE_TAG(r30->object)->type) goto break1; break; case OT_ENUMCONST: if (OBJ_ENUM_CONST(r6->object)->type == OBJ_ENUM_CONST(r30->object)->type) goto break1; break; case OT_OBJECT: if (OBJECT(r6->object)->datatype == DALIAS) { if (OBJECT(r30->object)->datatype == DALIAS) { if (OBJECT(r6->object)->u.alias.object == OBJECT(r30->object)->u.alias.object) goto break1; } else { if (OBJECT(r6->object)->u.alias.object == OBJECT(r30->object)) goto break1; } } else { if ((OBJECT(r30->object)->datatype == DALIAS) && OBJECT(r6->object) == OBJECT(r30->object)->u.alias.object) goto break1; } break; } } } break1: if (!r6) { if (!r27) { r31 = CScope_CopyNameSpaceObjectList(r31); r27 = 1; } if (CScope_ObjectIsFunction(OBJECT(r30->object))) { for (scanOL = r31; scanOL; scanOL = scanOL->next) { if (!CScope_ObjectIsFunction(OBJECT(scanOL->object))) { if (scanOL->object->otype != OT_TYPETAG) { CScope_AmbigNameError(r28, r29->nspace, name); break; } } } } else if (r30->object->otype == OT_TYPETAG) { for (scanOL = r31; scanOL; scanOL = scanOL->next) { if (scanOL->object->otype == OT_TYPETAG) { CScope_AmbigNameError(r28, r29->nspace, name); break; } } } else { for (scanOL = r31; scanOL; scanOL = scanOL->next) { if (scanOL->object->otype != OT_TYPETAG) { CScope_AmbigNameError(r28, r29->nspace, name); break; } } } if (!scanOL) { newlist = lalloc(sizeof(NameSpaceObjectList)); newlist->object = r30->object; newlist->next = r31; r31 = newlist; } } } } else { r31 = tmpOL; r28 = r29->nspace; } } } if (foundnspace) *foundnspace = r28; return r31; } static NameSpaceObjectList *CScope_NSIteratorFind(CScopeNSIterator *iterator, HashNameNode *name) { NameSpaceObjectList *list; if (iterator->lookup) { if (iterator->lookup->namespaces) return CScope_FindLookupName(iterator->lookup, name, NULL); if (iterator->lookup->nspace->theclass) { if (CScope_FindClassMember(iterator->result, iterator->lookup->nspace, name, 0)) { list = iterator->result->nsol_14; iterator->result->nsol_14 = NULL; return list; } else { return NULL; } } if ((list = CScope_FindName(iterator->lookup->nspace, name))) return list; } else { if (iterator->nspace->theclass) { if (CScope_FindClassMember(iterator->result, iterator->nspace, name, 0)) { list = iterator->result->nsol_14; iterator->result->nsol_14 = NULL; return list; } else { return NULL; } } if ((list = CScope_FindName(iterator->nspace, name))) return list; } return NULL; } static NameSpaceObjectList *CScope_NSIteratorNonClassFind(CScopeNSIterator *iterator, HashNameNode *name) { NameSpaceObjectList *list; if (iterator->lookup) { if (iterator->lookup->namespaces) return CScope_FindLookupName(iterator->lookup, name, NULL); if (iterator->lookup->nspace->theclass) return NULL; if ((list = CScope_FindName(iterator->lookup->nspace, name))) return list; } else { if (iterator->nspace->theclass) return NULL; if ((list = CScope_FindName(iterator->nspace, name))) return list; } return NULL; } static NameSpace *CScope_NSIteratorFindNameSpace(CScopeNSIterator *iterator, HashNameNode *name) { NameSpace *nspace; NameSpaceObjectList *list; if (iterator->lookup) { if (iterator->lookup->namespaces) return CScope_FindLookupNameSpace(iterator, iterator->lookup, name); if (iterator->lookup->nspace->theclass) { if (CScope_FindClassMember(iterator->result, iterator->lookup->nspace, name, 2)) { nspace = iterator->result->nspace_0; iterator->result->nspace_0 = NULL; return nspace; } else { return NULL; } } if ((list = CScope_FindName(iterator->lookup->nspace, name))) return CScope_ExtractNameSpace(list, NULL); } else { if (iterator->nspace->theclass) { if (CScope_FindClassMember(iterator->result, iterator->nspace, name, 2)) { nspace = iterator->result->nspace_0; iterator->result->nspace_0 = NULL; return nspace; } else { return NULL; } } if ((list = CScope_FindName(iterator->nspace, name))) return CScope_ExtractNameSpace(list, NULL); } return NULL; } static Boolean CScope_SetupParseNameResult(CScopeParseResult *result, NameSpaceObjectList *list, HashNameNode *name) { if (!list->next || list->next->object->otype == OT_TYPETAG) { switch (list->object->otype) { case OT_NAMESPACE: CError_Error(321); return 0; case OT_TYPE: result->x8 = OBJ_TYPE(list->object)->type; result->xC = OBJ_TYPE(list->object)->qual; result->obj_10 = list->object; result->name_4 = name; result->x20 = 1; break; case OT_TYPETAG: result->x8 = OBJ_TYPE_TAG(list->object)->type; result->xC = NULL; result->obj_10 = list->object; result->name_4 = name; result->x20 = 1; break; default: result->obj_10 = list->object; } } else { result->nsol_14 = list; } return 1; } Boolean CScope_FindQualifiedClassMember(CScopeParseResult *result, TypeClass *tclass, HashNameNode *name) { NameSpaceObjectList *list; memclrw(result, sizeof(CScopeParseResult)); CDecl_CompleteType((Type *) tclass); if (CScope_FindClassMember(result, tclass->nspace, name, 0)) { list = result->nsol_14; #line 1780 CError_ASSERT(list); result->nsol_14 = NULL; if (CScope_SetupParseNameResult(result, list, name) && !result->x8) return 1; else CError_Error(340, name->name); } return 0; } static NameSpace *CScope_FindQualifiedNameSpace(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name) { NameSpaceObjectList *list; NameSpace *cand; NameSpace *found; NameSpaceList *scan; NameSpaceLookupList *lookup; Boolean fail = 0; if (nspace->theclass) { if (CScope_FindClassMember(result, nspace, name, 2)) { nspace = result->nspace_0; result->nspace_0 = NULL; return nspace; } else { return NULL; } } if ((list = CScope_FindQualName(nspace, name)) && CScope_ExtractNameSpace(list, &fail)) return nspace; if (!fail && nspace->usings) { found = NULL; for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) { for (scan = lookup->namespaces; scan; scan = scan->next) { if ((list = CScope_FindQualName(scan->nspace, name)) && (cand = CScope_ExtractNameSpace(list, &fail))) { if (found && cand != found) CScope_AmbigNameError(found, cand, NULL); found = cand; } if (fail) return NULL; } if (found) return found; } } return NULL; } static NameSpaceObjectList *CScope_FindQualifiedName(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name, NameSpace **foundnspace) { NameSpaceObjectList *list; NameSpaceLookupList *lookup; if (nspace->theclass) { CDecl_CompleteType((Type *) nspace->theclass); if (CScope_FindClassMember(result, nspace, name, 0)) { list = result->nsol_14; result->nsol_14 = NULL; return list; } else { return NULL; } } if ((list = CScope_FindQualName(nspace, name))) { *foundnspace = nspace; return list; } if (nspace->usings) { for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) { if ((list = CScope_FindLookupName(lookup, name, foundnspace))) return list; } } return NULL; } static Boolean CScope_FindQualifiedTag(CScopeParseResult *result, NameSpace *nspace, HashNameNode *name) { NameSpaceObjectList *list; NameSpaceLookupList *lookup; Type *best; NameSpace *bestnspace; NameSpaceList *scan; if (nspace->theclass) { CDecl_CompleteType((Type *) nspace->theclass); return CScope_FindClassMember(result, nspace, name, 1) != 0; } if ((list = CScope_FindQualName(nspace, name))) { for (; list; list = list->next) { if (list->object->otype == OT_TYPETAG) { result->x8 = OBJ_TYPE_TAG(list->object)->type; return 1; } } } if (nspace->usings) { best = NULL; for (lookup = CScope_BuildNameSpaceMemberLookupList(nspace); lookup; lookup = lookup->next) { for (scan = lookup->namespaces; scan; scan = scan->next) { for (list = CScope_FindQualName(scan->nspace, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG) { if (best && best != OBJ_TYPE_TAG(list->object)->type) CScope_AmbigNameError(scan->nspace, bestnspace, name); best = OBJ_TYPE_TAG(list->object)->type; bestnspace = scan->nspace; break; } } } if (best) { result->x8 = best; return 1; } } } return 0; } inline void CScope_NSIteratorInit(CScopeNSIterator *iterator, NameSpace *nspace, CScopeParseResult *result) { // assumed name if (nspace->usings) { iterator->nspace = NULL; iterator->lookup = CScope_BuildNameSpaceLookupList(nspace); } else { iterator->nspace = nspace; iterator->lookup = NULL; } iterator->result = result; } inline Boolean CScope_NSIteratorNext(CScopeNSIterator *iterator) { // assumed name if (iterator->lookup) return (iterator->lookup = iterator->lookup->next) != NULL; if (iterator->result->x1D) return 0; if ((iterator->nspace = iterator->nspace->parent)) { if (iterator->nspace->usings && !iterator->result->x1D) { iterator->lookup = CScope_BuildNameSpaceLookupList(iterator->nspace); iterator->nspace = NULL; } return 1; } else { return 0; } } Type *CScope_GetType(NameSpace *nspace, HashNameNode *name, UInt32 *qual) { CScopeParseResult result; CScopeNSIterator iterator; NameSpaceObjectList *list; Boolean ok; memclrw(&result, sizeof(result)); CScope_NSIteratorInit(&iterator, nspace, &result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG) { if (qual) *qual = 0; return OBJ_TYPE_TAG(list->object)->type; } if (list->object->otype == OT_TYPE) { if (qual) *qual = OBJ_TYPE(list->object)->qual; return OBJ_TYPE(list->object)->type; } } } while (CScope_NSIteratorNext(&iterator)); return NULL; } Type *CScope_GetTagType(NameSpace *nspace, HashNameNode *name) { CScopeParseResult result; CScopeNSIterator iterator; NameSpaceObjectList *list; Boolean ok; memclrw(&result, sizeof(result)); CScope_NSIteratorInit(&iterator, nspace, &result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG) return OBJ_TYPE_TAG(list->object)->type; } } while (CScope_NSIteratorNext(&iterator)); return NULL; } static Boolean CScope_DependentTemplateMember(CScopeParseResult *result, TypeTemplDep *ttempldep, Boolean flag1, Boolean flag2) { // does not match, sign extension/caching mishap SInt32 streamstate; short token; short token2; TypeTemplDep *newtype; TypeTemplDep *newtype2; CPrep_TokenStreamGetState(&streamstate); #line 2026 CError_ASSERT(lex() == TK_COLON_COLON); do { token = lex(); if (token == TK_OPERATOR && flag1) { if (!CParser_ParseOperatorName(NULL, 1, 1)) return 0; newtype = CDecl_NewTemplDepType(TEMPLDEP_QUALNAME); newtype->u.qual.type = ttempldep; newtype->u.qual.name = tkidentifier; CPrep_TokenStreamSetState(&streamstate); lex(); tk = lex(); result->x8 = (Type *) newtype; return 1; } else if (token == TK_TEMPLATE) { if (lex() != TK_IDENTIFIER) { CError_Error(107); return 0; } CPrep_TokenStreamGetState(&streamstate); newtype = CDecl_NewTemplDepType(TEMPLDEP_QUALNAME); newtype->u.qual.type = ttempldep; newtype->u.qual.name = tkidentifier; if ((token2 = lex()) != '<') { CError_Error(230); return 0; } tk = token2; newtype2 = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL); newtype2->u.qualtempl.type = newtype; newtype2->u.qualtempl.args = CTempl_ParseUncheckTemplArgs(NULL, 1); CPrep_TokenStreamGetState(&streamstate); if (lex() == TK_COLON_COLON) { ttempldep = newtype2; continue; } else { CPrep_TokenStreamSetState(&streamstate); result->x8 = (Type *) newtype2; return 1; } } else if (token == TK_IDENTIFIER) { newtype = CDecl_NewTemplDepType(TEMPLDEP_QUALNAME); newtype->u.qual.type = ttempldep; newtype->u.qual.name = tkidentifier; tk = token; CPrep_TokenStreamGetState(&streamstate); token2 = lex(); tkidentifier = newtype->u.qual.name; if (token2 == TK_COLON_COLON) { ttempldep = newtype; continue; } if ((token2 == '<') && !flag2) { tk = token2; newtype2 = newtype; newtype = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL); newtype->u.qualtempl.type = newtype2; newtype->u.qualtempl.args = CTempl_ParseUncheckTemplArgs(NULL, 1); CPrep_TokenStreamGetState(&streamstate); if (lex() == TK_COLON_COLON) { ttempldep = newtype; continue; } } CPrep_TokenStreamSetState(&streamstate); result->x8 = (Type *) newtype; return 1; } else { CPrep_TokenStreamSetState(&streamstate); result->x8 = (Type *) ttempldep; return 1; } } while (1); } static Boolean CScope_CheckDtorName(TypeClass *tclass, Boolean *flag) { if ((tk = lex()) != TK_IDENTIFIER) CError_Error(107); if (tclass) { *flag = 0; if ((tclass->classname == tkidentifier) || (CScope_GetType(tclass->nspace, tkidentifier, NULL) == (Type *) tclass) || (CScope_GetType(cscope_current, tkidentifier, NULL) == (Type *) tclass)) { if (!CClass_Destructor(tclass)) *flag = 1; if ((tclass->flags & CLASS_FLAGS_800) && (lookahead() == '<')) { tk = lex(); if (!CTemplTool_EqualArgs(TEMPL_CLASS_INST(tclass)->inst_args, CTempl_ParseUncheckTemplArgs(NULL, 0))) CError_Error(374); } return 1; } } CError_Error(141); return 0; } static Boolean CScope_ParseQualifiedName(CScopeParseResult *result, NameSpace *nspace) { NameSpaceObjectList *list; HashNameNode *saveidentifier; TypeClass *tclass; Boolean flag = 0; do { switch (tk) { case TK_TEMPLATE: if ((tk = lex()) != TK_IDENTIFIER) { CError_Error(107); return 0; } case TK_IDENTIFIER: saveidentifier = tkidentifier; if (lookahead() == TK_COLON_COLON) { tk = lex(); nspace = CScope_FindQualifiedNameSpace(result, nspace, saveidentifier); if (!nspace) return 0; result->x1D = 1; tk = lex(); continue; } break; case TK_OPERATOR: if (!CParser_ParseOperatorName(NULL, 1, 1)) return 0; CPrep_UnLex(); saveidentifier = tkidentifier; break; case '~': if (!CScope_CheckDtorName(nspace->theclass, &flag)) return 0; saveidentifier = destructor_name_node; flag = 1; break; default: CError_Error(107); return 0; } if (!(list = CScope_FindQualifiedName(result, nspace, saveidentifier, &result->nspace_0)) || !CScope_SetupParseNameResult(result, list, saveidentifier)) { if (flag) { result->x1C = 1; return 1; } if (nspace->theclass && !(nspace->theclass->flags & CLASS_FLAGS_2)) CError_Error(136, nspace->theclass, 0); else CError_Error(140, saveidentifier->name); return 0; } if (result->x8 && (result->x8->type == TYPECLASS) && (lookahead() == '<')) { tclass = TYPE_CLASS(result->x8); if (tclass->flags & CLASS_FLAGS_800) tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ); else if (!(tclass->flags & CLASS_FLAGS_100)) return 1; tk = lex(); result->x8 = CTempl_ClassGetType(tclass); if ((result->x8->type == TYPECLASS) && (lookahead() == TK_COLON_COLON)) { lex(); tk = lex(); result->x1D = 1; nspace = TYPE_CLASS(result->x8)->nspace; result->x8 = NULL; result->obj_10 = NULL; continue; } } return 1; } while (1); } Boolean CScope_ParseExprName(CScopeParseResult *result) { CScopeNSIterator iterator; HashNameNode *name; NameSpaceObjectList *list; Boolean flag; if (!copts.cplusplus) { memclrw(result, sizeof(CScopeParseResult)); if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } name = tkidentifier; CScope_NSIteratorInit(&iterator, cscope_current, result); do { if ((list = CScope_NSIteratorFind(&iterator, name)) && (list->object->otype != OT_TYPETAG)) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } while (CScope_NSIteratorNext(&iterator)); result->nspace_0 = cscope_current; result->name_4 = name; return 1; } else { if ((tk == TK_COLON_COLON || tk == TK_IDENTIFIER) && CScope_ParseQualifiedNameSpace(result, 1, 1)) { if (result->x8) return 1; #line 2313 CError_ASSERT(result->nspace_0); } else { memclrw(result, sizeof(CScopeParseResult)); result->nspace_0 = cscope_current; } switch (tk) { case TK_TEMPLATE: if (!result->x1D) CError_Error(373); if ((tk = lex()) != TK_IDENTIFIER) { CError_Error(107); return 0; } case TK_IDENTIFIER: name = tkidentifier; break; case TK_OPERATOR: if (!CParser_ParseOperatorName(NULL, 1, 1)) return 0; name = tkidentifier; CPrep_UnLex(); break; case '~': if (!CScope_CheckDtorName(result->nspace_0->theclass, &flag)) return 0; if (flag) { result->x1C = 1; return 1; } name = destructor_name_node; break; default: CError_Error(107); return 0; } if (result->x1D) { if (!(list = CScope_FindQualifiedName(result, result->nspace_0, name, &result->nspace_0))) { CError_Error(140, CError_GetNameString(result->nspace_0, name)); return 0; } else { return CScope_SetupParseNameResult(result, list, name); } } CScope_NSIteratorInit(&iterator, result->nspace_0, result); do { if ((list = CScope_NSIteratorFind(&iterator, name))) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } while (CScope_NSIteratorNext(&iterator)); if (result->x1D) { CError_Error(140, name->name); return 0; } else { result->nspace_0 = cscope_current; result->name_4 = name; return 1; } } } Boolean CScope_ParseDeclName(CScopeParseResult *result) { CScopeNSIterator iterator; HashNameNode *name; NameSpaceObjectList *list; NameSpace *nspace; Boolean flag; CScopeSave save; short op; if (!copts.cplusplus) { non_cpp_mode: if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } memclrw(result, sizeof(CScopeParseResult)); name = tkidentifier; CScope_NSIteratorInit(&iterator, cscope_current, result); do { if ((list = CScope_NSIteratorFind(&iterator, name)) && (copts.cplusplus || (list->object->otype != OT_TYPETAG))) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } while (CScope_NSIteratorNext(&iterator)); result->nspace_0 = cscope_current; result->name_4 = name; return 0; } else { if ((tk != TK_COLON_COLON) && (tk != TK_IDENTIFIER)) { CError_Error(107); return 0; } if (!CScope_ParseQualifiedNameSpace(result, 0, 0)) goto non_cpp_mode; if (result->x8) return 1; nspace = result->nspace_0; #line 2435 CError_ASSERT(nspace); switch (tk) { case TK_OPERATOR: CScope_SetNameSpaceScope(nspace, &save); if (!CParser_ParseOperatorName(&op, 1, 1)) { CScope_RestoreScope(&save); return 0; } CScope_RestoreScope(&save); if (op) CError_Error(121); result->x21 = 1; return 1; case TK_IDENTIFIER: name = tkidentifier; if (nspace->theclass && nspace->theclass->classname == tkidentifier) name = constructor_name_node; break; case '~': if (!nspace->theclass) { CError_Error(121); return 0; } tk = lex(); if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } if (nspace->theclass->classname != tkidentifier) CError_Error(121); name = destructor_name_node; break; default: CError_Error(107); return 0; } if (result->x1D) { if (!(list = CScope_FindQualifiedName(result, result->nspace_0, name, &result->nspace_0))) { CError_Error(140, name->name); return 0; } else { return CScope_SetupParseNameResult(result, list, name); } } CScope_NSIteratorInit(&iterator, nspace, result); do { if ((list = CScope_NSIteratorFind(&iterator, name))) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } while (CScope_NSIteratorNext(&iterator)); CError_Error(140, name->name); return 0; } } Boolean CScope_ParseQualifiedNameSpace(CScopeParseResult *result, Boolean flag1, Boolean flag2) { // mostly matches, some registers are awkwardly swapped HashNameNode *name; // r25 NameSpace *nspace; // r24 short t; // r23 Type *type; // r28? Type *type2; // r21? NameSpaceObjectList *list; // r21 CScopeNSIterator iterator; memclrw(result, sizeof(CScopeParseResult)); nspace = NULL; if (tk == TK_COLON_COLON) { result->nspace_0 = nspace = cscope_root; result->x1D = 1; tk = lex(); } restart: if (tk != TK_IDENTIFIER) { if (tk != TK_TEMPLATE) return nspace != NULL; if (!result->x1D) CError_Error(373); if ((tk = lex()) != TK_IDENTIFIER) { CError_Error(107); return 0; } } name = tkidentifier; t = lookahead(); tkidentifier = name; if (t != TK_COLON_COLON && t != '<') return nspace != NULL; CScope_NSIteratorInit(&iterator, nspace ? nspace : cscope_current, result); // r28 = r23 ??? do { // list = r21 for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (list->object->otype == OT_NAMESPACE) { #line 2565 CError_ASSERT(!nspace || !nspace->theclass); result->nspace_0 = nspace = OBJ_NAMESPACE(list->object)->nspace; if ((tk = lex()) != TK_COLON_COLON) { CError_Error(321); return 0; } result->x1D = 1; tk = lex(); goto restart; } if (list->object->otype == OT_TYPETAG) { type = OBJ_TYPE_TAG(list->object)->type; if (type->type != TYPECLASS) { if (t == '<') { result->x8 = type; return 1; } else { CError_Error(121); return 0; } } parse_thing: if (t == '<') { if (TYPE_CLASS(type)->flags & CLASS_FLAGS_800) { type = (Type *) TEMPL_CLASS_INST(type)->templ; } else if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_100)) { result->x8 = type; return 1; } } if ((tk = lex()) == '<') { #line 2609 CError_ASSERT(TYPE_CLASS(type)->flags & CLASS_FLAGS_100); type2 = CTempl_ClassGetType(TYPE_CLASS(type)); if (type2->type == TYPETEMPLATE) { if (lookahead() != TK_COLON_COLON) { result->x8 = type2; return 1; } return CScope_DependentTemplateMember(result, TYPE_TEMPLATE(type2), flag1, flag2); } else if (type2->type != TYPECLASS) { return 0; } result->nspace_0 = nspace = TYPE_CLASS(type2)->nspace; if (lookahead() != TK_COLON_COLON) { result->x8 = type2; return 1; } tk = lex(); CDecl_CompleteType(type2); } else { #line 2632 CError_ASSERT(tk == TK_COLON_COLON); if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_100) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1)) result->nspace_0 = nspace = TYPE_CLASS(type)->nspace; CDecl_CompleteType(type); } result->x1D = 1; tk = lex(); goto restart; } if (list->object->otype == OT_TYPE) { type2 = OBJ_TYPE(list->object)->type; if (type2->type != TYPECLASS) { if (type2->type == TYPETEMPLATE) { if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(type2)->u.pid.type == TPT_TEMPLATE) { type2 = CTempl_ParseTemplTemplParam(type2); if ((type2->type != TYPETEMPLATE) || ((t = lookahead()) != TK_COLON_COLON)) { result->x8 = type2; return 1; } } if (t == TK_COLON_COLON) return CScope_DependentTemplateMember(result, TYPE_TEMPLATE(type2), flag1, flag2); } if (t == '<') { result->x8 = type2; return 1; } else { CError_Error(121); return 0; } } else { if ((t == '<') && (TYPE_CLASS(type2)->flags & CLASS_FLAGS_100)) { type = type2; goto parse_thing; } if ((tk = lex()) == '<') { result->x8 = type2; return 1; } #line 2686 CError_ASSERT(tk == TK_COLON_COLON); if (!type2->size) CDecl_CompleteType(type2); result->nspace_0 = nspace = TYPE_CLASS(type2)->nspace; result->x1D = 1; tk = lex(); goto restart; } } if (t == '<') return nspace != NULL; } } while (CScope_NSIteratorNext(&iterator)); CError_Error(140, name->name); return 0; } Boolean CScope_ParseElaborateName(CScopeParseResult *result) { CScopeNSIterator iterator; HashNameNode *name; NameSpaceObjectList *list; Boolean flag; if (!copts.cplusplus) { memclrw(result, sizeof(CScopeParseResult)); if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } name = tkidentifier; CScope_NSIteratorInit(&iterator, cscope_current, result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } } while (CScope_NSIteratorNext(&iterator)); result->name_4 = name; return 1; } else { if ((tk != TK_COLON_COLON) && (tk != TK_IDENTIFIER)) { CError_Error(107); return 0; } if (!CScope_ParseQualifiedNameSpace(result, 0, 0)) { result->nspace_0 = cscope_current; if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } name = tkidentifier; } else { if (result->x8) return 1; #line 2760 CError_ASSERT(result->nspace_0); if (tk != TK_IDENTIFIER) { CError_Error(107); return 0; } name = tkidentifier; if (result->x1D) { if (result->nspace_0->theclass) return CScope_FindClassMember(result, result->nspace_0, name, 1) != 0; else return CScope_FindQualifiedTag(result, result->nspace_0, name); } } CScope_NSIteratorInit(&iterator, result->nspace_0, result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG || list->object->otype == OT_TYPE) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } } while (CScope_NSIteratorNext(&iterator)); result->name_4 = name; return 1; } } Boolean CScope_FindObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name) { CScopeNSIterator iterator; NameSpaceObjectList *list; memclrw(result, sizeof(CScopeParseResult)); CScope_NSIteratorInit(&iterator, nspace, result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (copts.cplusplus || list->object->otype != OT_TYPETAG) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } } while (CScope_NSIteratorNext(&iterator)); return 0; } Boolean CScope_FindNonClassObject(NameSpace *nspace, CScopeParseResult *result, HashNameNode *name) { CScopeNSIterator iterator; NameSpaceObjectList *list; memclrw(result, sizeof(CScopeParseResult)); CScope_NSIteratorInit(&iterator, nspace, result); do { for (list = CScope_NSIteratorNonClassFind(&iterator, name); list; list = list->next) { if (copts.cplusplus || list->object->otype != OT_TYPETAG) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return CScope_SetupParseNameResult(result, list, name); } } } while (CScope_NSIteratorNext(&iterator)); return 0; } NameSpaceObjectList *CScope_FindObjectList(CScopeParseResult *result, HashNameNode *name) { CScopeNSIterator iterator; NameSpaceObjectList *list; memclrw(result, sizeof(CScopeParseResult)); CScope_NSIteratorInit(&iterator, cscope_current, result); do { for (list = CScope_NSIteratorFind(&iterator, name); list; list = list->next) { if (copts.cplusplus || list->object->otype != OT_TYPETAG) { result->nspace_0 = iterator.lookup ? iterator.lookup->nspace : iterator.nspace; return list; } } } while (CScope_NSIteratorNext(&iterator)); return 0; } Boolean CScope_PossibleTypeName(HashNameNode *name) { CScopeParseResult result; CScopeNSIterator iterator; NameSpaceObjectList *list; memclrw(&result, sizeof(CScopeParseResult)); CScope_NSIteratorInit(&iterator, cscope_current, &result); do { if ((list = CScope_NSIteratorFind(&iterator, name))) { switch (list->object->otype) { case OT_TYPE: case OT_NAMESPACE: return 1; case OT_TYPETAG: if (copts.cplusplus) return 1; break; default: return 0; } } } while (CScope_NSIteratorNext(&iterator)); return 0; } Boolean CScope_FindClassMemberObject(TypeClass *tclass, CScopeParseResult *result, HashNameNode *name) { NameSpaceObjectList *list; memclrw(result, sizeof(CScopeParseResult)); if (CScope_FindClassMember(result, tclass->nspace, name, 0)) { list = result->nsol_14; result->nsol_14 = NULL; if (list && list->object->otype == OT_OBJECT) return CScope_SetupParseNameResult(result, list, name); } return 0; } void CScope_InitObjectIterator(CScopeObjectIterator *iterator, NameSpace *nspace) { memclrw(iterator, sizeof(CScopeObjectIterator)); iterator->nspace = nspace; if (!iterator->nspace->is_hash) iterator->nextname = nspace->data.list; else iterator->nextname = nspace->data.hash[0]; } ObjBase *CScope_NextObjectIteratorObject(CScopeObjectIterator *iterator) { ObjBase *obj; do { if (iterator->currlist) { do { obj = iterator->currlist->object; if (obj->otype == OT_OBJECT) { iterator->currlist = iterator->currlist->next; return obj; } } while ((iterator->currlist = iterator->currlist->next)); } if (iterator->nextname) { iterator->currlist = &iterator->nextname->first; iterator->nextname = iterator->nextname->next; } else { if (!iterator->nspace->is_hash || ++iterator->hashindex >= 1024) return NULL; iterator->nextname = iterator->nspace->data.hash[iterator->hashindex]; } } while (1); } NameSpaceObjectList *CScope_NextObjectIteratorObjectList(CScopeObjectIterator *iterator) { NameSpaceName *nsname; do { if ((nsname = iterator->nextname)) { iterator->nextname = nsname->next; return &nsname->first; } else { if (!iterator->nspace->is_hash || ++iterator->hashindex >= 1024) return NULL; iterator->nextname = iterator->nspace->data.hash[iterator->hashindex]; } } while (1); } void CScope_DefineTypeTag(NameSpace *nspace, HashNameNode *name, Type *type) { ObjTypeTag *ott; ott = galloc(sizeof(ObjTypeTag)); memclrw(ott, sizeof(ObjTypeTag)); ott->otype = OT_TYPETAG; ott->access = nspace->theclass ? global_access : ACCESSPUBLIC; ott->type = type; CScope_AddObject(nspace, name, OBJ_BASE(ott)); } Type *CScope_GetLocalTagType(NameSpace *nspace, HashNameNode *name) { NameSpaceObjectList *list; for (list = CScope_FindQualName(nspace, name); list; list = list->next) { if (list->object->otype == OT_TYPETAG) return OBJ_TYPE_TAG(list->object)->type; } return NULL; } Boolean CScope_FindTypeName(NameSpace *nspace, HashNameNode *name, CScopeParseResult *result) { CScopeNSIterator iterator; NameSpaceObjectList *list; NameSpaceObjectList *scan; memclrw(result, sizeof(CScopeParseResult)); CScope_NSIteratorInit(&iterator, nspace, result); do { list = CScope_NSIteratorFind(&iterator, name); for (scan = list; scan; scan = scan->next) { switch (scan->object->otype) { case OT_NAMESPACE: result->nspace_0 = OBJ_NAMESPACE(scan->object)->nspace; return 1; case OT_TYPE: case OT_TYPETAG: return CScope_SetupParseNameResult(result, scan, name); default: return 0; } } } while (CScope_NSIteratorNext(&iterator)); return 0; } static NameSpaceObjectList *CScope_GetLocalObjects(NameSpaceObjectList *objs) { NameSpaceObjectList *list; NameSpaceObjectList **ptr; list = objs; while (list) { if (list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DALIAS) { list = CScope_CopyNameSpaceObjectList(objs); ptr = &list; while (*ptr) { if ((*ptr)->object->otype == OT_OBJECT && OBJECT((*ptr)->object)->datatype == DALIAS) *ptr = (*ptr)->next; else ptr = &(*ptr)->next; } return list; } else { list = list->next; } } return objs; } NameSpaceObjectList *CScope_GetLocalObject(NameSpace *nspace, HashNameNode *name) { NameSpaceObjectList *list; if ((list = CScope_FindQualName(nspace, name))) { switch (list->object->otype) { case OT_OBJECT: return CScope_GetLocalObjects(list); default: CError_Error(122, name->name); return NULL; case OT_TYPETAG: break; } } return NULL; } static BClassList *CScope_GetBaseAccessPathEnd(BClassList *list) { BClassList *best = list; ClassList *scan; do { if (!list->next) return best; for (scan = TYPE_CLASS(list->type)->bases; scan; scan = scan->next) { if (TYPE_CLASS(list->next->type) == scan->base) break; } if (!scan) best = list->next; list = list->next; } while (1); } BClassList *CScope_GetClassAccessPath(BClassList *list, TypeClass *tclass) { BClassList *scan; BClassList *list2; if (!list) return NULL; list = CScope_GetBaseAccessPathEnd(list); for (scan = list; scan; scan = scan->next) { if (scan->type == (Type *) tclass) return scan; } if ((list2 = CScope_GetAccessPath(tclass, TYPE_CLASS(list->type)))) { for (scan = list2; scan; scan = scan->next) { if (scan->type == list->type) { scan->next = list->next; return list2; } } #line 3217 CError_FATAL(); } return NULL; } static Boolean CScope_FixMemberResult(TypeClass *tclass, CScopeParseResult *result) { if (!(result->bcl_18 = CScope_GetClassAccessPath(result->bcl_18, tclass))) { if (result->name_4) CError_Error(150, result->name_4->name); else CError_Error(328); return 0; } else { return 1; } } Boolean CScope_ParseMemberName(TypeClass *tclass, CScopeParseResult *result, Boolean flag) { HashNameNode *name; NameSpaceObjectList *list; short t; Boolean dtorflag; if (tk == TK_COLON_COLON) { restart: if (!CScope_ParseExprName(result)) return 0; if (result->x8 && result->x8->type == TYPETEMPLATE && TYPE_TEMPLATE(result->x8)->dtype == TEMPLDEP_QUALNAME) { if (flag) return 1; CError_Error(340, TYPE_TEMPLATE(result->x8)->u.qual.name->name); result->x8 = NULL; return 0; } if (result->x1C) return 1; else return CScope_FixMemberResult(tclass, result); } if (tk == TK_IDENTIFIER) { name = tkidentifier; t = lookahead(); tkidentifier = name; switch (t) { case TK_COLON_COLON: memclrw(result, sizeof(CScopeParseResult)); if (!CScope_FindClassMember(result, tclass->nspace, name, 2)) goto restart; break; case '<': if (flag) goto restart; break; } } else if (tk == '~') { memclrw(result, sizeof(CScopeParseResult)); if (CScope_CheckDtorName(tclass, &dtorflag)) { if (dtorflag) { result->x1C = 1; return 1; } if (!(list = CScope_FindQualifiedName(result, tclass->nspace, destructor_name_node, &result->nspace_0))) { CError_Error(140, CError_GetNameString(result->nspace_0, destructor_name_node)); return 0; } else { return CScope_SetupParseNameResult(result, list, destructor_name_node); } } return 0; } memclrw(result, sizeof(CScopeParseResult)); return CScope_ParseQualifiedName(result, tclass->nspace); } static void CScope_AddUsingObject(BClassList *bcl, NameSpace *nspace, ObjBase *obj, HashNameNode *name, AccessType access) { NameSpaceObjectList *list; BClassList *pathcopy; TypeClass *tclass; ObjBase *copy; Object *objscan; if (bcl) { if (!nspace->theclass) CError_Error(200); else CClass_CheckPathAccess(bcl, NULL, obj->access); } if (obj->otype == OT_TYPE) { if (!nspace->theclass) { if ((list = CScope_FindQualName(nspace, name)) && (list->object->otype == OT_TYPE) && (OBJ_TYPE(obj)->type == OBJ_TYPE(list->object)->type) && (OBJ_TYPE(obj)->qual == OBJ_TYPE(list->object)->qual)) return; } copy = galloc(sizeof(ObjType)); *OBJ_TYPE(copy) = *OBJ_TYPE(obj); copy->access = access; CScope_AddObject(nspace, name, copy); } else if (obj->otype == OT_TYPETAG) { if (!nspace->theclass) { if ((list = CScope_FindQualName(nspace, name)) && (list->object->otype == OT_TYPETAG) && (OBJ_TYPE_TAG(obj)->type == OBJ_TYPE_TAG(list->object)->type)) return; } copy = galloc(sizeof(ObjTypeTag)); *OBJ_TYPE_TAG(copy) = *OBJ_TYPE_TAG(obj); copy->access = access; CScope_AddObject(nspace, name, copy); } else if (obj->otype == OT_ENUMCONST) { copy = galloc(sizeof(ObjEnumConst)); *OBJ_ENUM_CONST(copy) = *OBJ_ENUM_CONST(obj); copy->access = access; CScope_AddObject(nspace, OBJ_ENUM_CONST(copy)->name, copy); } else if (obj->otype == OT_MEMBERVAR) { if (nspace->theclass) { copy = galloc(sizeof(ObjMemberVarPath)); *OBJ_MEMBER_VAR(copy) = *OBJ_MEMBER_VAR(obj); copy->access = access; pathcopy = CScope_GetClassAccessPath(CClass_GetPathCopy(bcl, 1), nspace->theclass); if (pathcopy && pathcopy->type == (Type *) nspace->theclass) { OBJ_MEMBER_VAR_PATH(copy)->has_path = 1; OBJ_MEMBER_VAR_PATH(copy)->path = pathcopy; } else { CError_Error(221); } CScope_AddObject(nspace, OBJ_MEMBER_VAR(copy)->name, copy); } else { CError_Error(221); } } else if (obj->otype == OT_OBJECT) { if (!nspace->theclass) { for (list = CScope_FindQualName(nspace, OBJECT(obj)->name); list; list = list->next) { if (list->object->otype == OT_OBJECT) { objscan = OBJECT(list->object); while (objscan->datatype == DALIAS) objscan = objscan->u.alias.object; if (OBJECT(obj) == objscan) return; } } } copy = galloc(sizeof(Object)); *OBJECT(copy) = *OBJECT(obj); copy->access = access; OBJECT(copy)->datatype = DALIAS; OBJECT(copy)->u.alias.object = OBJECT(obj); OBJECT(copy)->u.alias.member = NULL; OBJECT(copy)->u.alias.offset = 0; if (OBJECT(copy)->type->type == TYPEFUNC && (TYPE_FUNC(OBJECT(copy)->type)->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(OBJECT(copy)->type)->x26) { if (!(tclass = nspace->theclass) || !(OBJECT(copy)->u.alias.member = CScope_GetClassAccessPath( CClass_GetPathCopy(bcl, 1), tclass)) || (OBJECT(copy)->u.alias.member->type != (Type *) nspace->theclass)) { CError_Error(221); OBJECT(copy)->u.alias.member = NULL; } } CScope_AddObject(nspace, OBJECT(copy)->name, copy); } else { CError_Error(200); } } void CScope_AddClassUsingDeclaration(TypeClass *tclass, TypeClass *tclass2, HashNameNode *name, AccessType access) { CScopeParseResult result; NameSpaceObjectList *scan; memclrw(&result, sizeof(CScopeParseResult)); if (!CScope_FindClassMember(&result, tclass2->nspace, name, 0) || !CScope_FixMemberResult(tclass, &result)) { CError_Error(340, name->name); return; } if (result.nsol_14) { for (scan = result.nsol_14; scan; scan = scan->next) { switch (scan->object->otype) { case OT_ENUMCONST: case OT_MEMBERVAR: case OT_OBJECT: CScope_AddUsingObject(result.bcl_18, tclass->nspace, scan->object, result.name_4, access); break; } } } else { if (result.obj_10) CScope_AddUsingObject(result.bcl_18, tclass->nspace, result.obj_10, result.name_4, access); else CError_Error(340, name->name); } } void CScope_ParseUsingDeclaration(NameSpace *nspace, short access, Boolean flag) { // almost matches, slight bit of register weirdness CScopeParseResult result; if (nspace->theclass) { Boolean flag_r27 = (TYPE_CLASS(nspace->theclass)->flags & CLASS_FLAGS_100) ? 1 : 0; Boolean flag_r26 = 0; if (tk == TK_TYPENAME) { if (!flag_r27) CError_Error(200); flag_r26 = 1; tk = lex(); } if (!CScope_ParseMemberName(nspace->theclass, &result, flag_r27)) { CError_Error(200); return; } if (result.x8 && result.x8->type == TYPETEMPLATE && TYPE_TEMPLATE(result.x8)->dtype == TEMPLDEP_QUALNAME) { #line 3578 CError_ASSERT(flag_r27); if (flag_r26) { ObjType *objtype = galloc(sizeof(ObjType)); memclrw(objtype, sizeof(ObjType)); objtype->otype = OT_TYPE; objtype->access = access; objtype->type = result.x8; CScope_AddObject(nspace, TYPE_TEMPLATE(result.x8)->u.qual.name, OBJ_BASE(objtype)); } else { CTemplClass_RegisterUsingDecl(TEMPL_CLASS(nspace->theclass), result.x8, access); } if ((tk = lex()) != ';') CError_Error(123); return; } if (!result.x1D) { CError_Error(200); return; } } else { NameSpace *savenspace = cscope_current; cscope_current = nspace; if (!CScope_ParseExprName(&result) || !result.x1D) { cscope_current = savenspace; CError_Error(200); return; } else { cscope_current = savenspace; } } if (result.nsol_14) { NameSpaceObjectList *scan; for (scan = result.nsol_14; scan; scan = scan->next) { if (scan->object->otype == OT_OBJECT) CScope_AddUsingObject(result.bcl_18, nspace, scan->object, result.name_4, access); } } else { if (result.obj_10) CScope_AddUsingObject(result.bcl_18, nspace, result.obj_10, result.name_4, access); else CError_Error(200); } if ((tk = lex()) != ';') CError_Error(123); } static NameSpace *CScope_ParseQualifiedNamespaceSpecifier(NameSpace *nspace) { CScopeParseResult result; CScopeNSIterator iterator; NameSpaceObjectList *list; memclrw(&result, sizeof(CScopeParseResult)); if (tk == TK_COLON_COLON) { nspace = cscope_root; result.x1D = 1; tk = lex(); } do { if (tk != TK_IDENTIFIER) { CError_Error(107); break; } CScope_NSIteratorInit(&iterator, nspace, &result); do { if ((list = CScope_NSIteratorFind(&iterator, tkidentifier)) && list->object->otype == OT_NAMESPACE) { nspace = OBJ_NAMESPACE(list->object)->nspace; goto some_goto; } } while (CScope_NSIteratorNext(&iterator)); CError_Error(140, tkidentifier->name); some_goto: if ((tk = lex()) != TK_COLON_COLON) break; result.x1D = 1; tk = lex(); } while (1); return nspace; } void CScope_ParseNameSpaceAlias(HashNameNode *name) { NameSpaceObjectList *list; ObjNameSpace *objns; list = CScope_FindQualName(cscope_current, name); if (!list) { tk = lex(); objns = galloc(sizeof(ObjNameSpace)); memclrw(objns, sizeof(ObjNameSpace)); objns->otype = OT_NAMESPACE; objns->access = ACCESSPUBLIC; objns->nspace = CScope_ParseQualifiedNamespaceSpecifier(cscope_current); CScope_AddObject(cscope_current, name, OBJ_BASE(objns)); } else if (list->object->otype != OT_NAMESPACE) { CError_Error(320); tk = lex(); CScope_ParseQualifiedNamespaceSpecifier(cscope_current); } else { tk = lex(); if (CScope_ParseQualifiedNamespaceSpecifier(cscope_current) != OBJ_NAMESPACE(list->object)->nspace) CError_Error(122, name->name); } if (tk != ';') CError_Error(123); } void CScope_ParseUsingDirective(NameSpace *nspace) { NameSpace *target; NameSpaceList *list; target = CScope_ParseQualifiedNamespaceSpecifier(nspace); if (target != nspace) { for (list = nspace->usings; list; list = list->next) { if (list->nspace == target) break; } if (!list) { list = galloc(sizeof(NameSpaceList)); list->next = nspace->usings; list->nspace = target; nspace->usings = list; } } else { CError_Error(321); } if (tk != ';') CError_Error(123); }