summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/C/CScope.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CScope.c')
-rw-r--r--compiler_and_linker/FrontEnd/C/CScope.c2690
1 files changed, 2690 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CScope.c b/compiler_and_linker/FrontEnd/C/CScope.c
new file mode 100644
index 0000000..7423c07
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/C/CScope.c
@@ -0,0 +1,2690 @@
+#include "compiler.h"
+#include "compiler/CError.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 unknownFlag, 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 = !unknownFlag;
+}
+
+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)->unk6 == OBJ_TYPE(r30->object)->unk6))
+ 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)->unk6;
+ 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, void **unk6) {
+ 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 (unk6)
+ *unk6 = NULL;
+ return OBJ_TYPE_TAG(list->object)->type;
+ }
+ if (list->object->otype == OT_TYPE) {
+ if (unk6)
+ *unk6 = OBJ_TYPE(list->object)->unk6;
+ 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)->unk6 == OBJ_TYPE(list->object)->unk6))
+ 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, AccessType access) {
+ // 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);
+}