#include "compiler/CParser.h" #include "compiler/CABI.h" #include "compiler/CClass.h" #include "compiler/CDecl.h" #include "compiler/CError.h" #include "compiler/CExpr.h" #include "compiler/CFunc.h" #include "compiler/CInit.h" #include "compiler/CInline.h" #include "compiler/CInt64.h" #include "compiler/CIRTransform.h" #include "compiler/CMachine.h" #include "compiler/CMangler.h" #include "compiler/CObjC.h" #include "compiler/CPrep.h" #include "compiler/CPrepTokenizer.h" #include "compiler/CScope.h" #include "compiler/CSOM.h" #include "compiler/CTemplateNew.h" #include "compiler/CTemplateTools.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/IrOptimizer.h" #include "compiler/IroPointerAnalysis.h" #include "compiler/ObjGenMachO.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/templates.h" #include "cos.h" FileOffsetInfo cparser_fileoffset; TStreamElement symdecltoken; ParserTryBlock *trychain; Boolean inassembler; Boolean dont_set_references; TypeStruct ptmstruct; TypeStruct catchinfostruct; Boolean in_assembler; Boolean illegalimplicitconversion; Boolean in_func_arglist; NameSpaceName *newp_fobj; NameSpaceName *newa_fobj; NameSpaceName *delp_fobj; NameSpaceName *dela_fobj; Object *newh_func; Object *delh_func; Object *copy_func; Object *clear_func; Object *Rgtid_func; Object *Rdync_func; Object *rt_ptmf_cast; Object *rt_ptmf_cmpr; Object *rt_ptmf_test; Object *rt_ptmf_call; Object *rt_ptmf_scall; Object *rt_ptmf_call4; Object *rt_ptmf_scall4; Object *rt_ptmf_null; Object *rt_som_new; Object *rt_som_newcheck; Object *rt_som_check; Object *rt_som_glue1; Object *rt_som_glue2; Object *rt_som_glue3; Object *carr_func; Object *cnar_func; Object *darr_func; Object *dnar_func; Object *dnar3_func; Object *Xgreg_func; Object *Xthrw_func; Object *Xicth_func; Object *Xecth_func; Object *Xunex_func; CompilerLinkerOptions copts; GList name_mangle_list; HashNameNode *no_name_node; HashNameNode *temp_argument_name; HashNameNode *this_name_node; HashNameNode *self_name_node; HashNameNode *vptr_name_node; CallbackAction *callbackactions; Boolean fatalerrors; Boolean anyerrors; jmp_buf errorreturn; static HashNameNode *uniquenamespacename; static SInt32 uniqueid; struct ClassAction { struct ClassAction *next; TypeClass *tclass; }; static struct ClassAction *cparser_classactions; struct ParentCleanup { struct ParentCleanup *next; TypeClass *tclass; }; static struct ParentCleanup *cparser_parentcleanup; struct SFuncList { struct SFuncList *next; Object *func; Object *obj; ENode *expr; }; static struct SFuncList *cparser_sfunclist; char string[256]; SInt32 compilererrornum; SInt32 compilererrfile; SInt32 compilererrline; Type sttemplexpr = {TYPETEMPLDEPEXPR, 0}; Type stillegal = {TYPEILLEGAL, 1}; Type stvoid = {TYPEVOID, 0}; TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0}; TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0}; // forward declarations static void CParser_ParseDeclaration(DeclInfo *di); Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) { Object *obj; FuncArg *args; FuncArg *arg; TypeFunc *tfunc; va_list va; args = NULL; if (argcount) { va_start(va, argcount); while (--argcount >= 0) { if (args) { arg->next = CParser_NewFuncArg(); arg = arg->next; } else { arg = CParser_NewFuncArg(); args = arg; } arg->type = va_arg(va, Type *); } va_end(va); } obj = CParser_NewFunctionObject(NULL); tfunc = galloc(sizeof(TypeFunc)); memclrw(tfunc, sizeof(TypeFunc)); tfunc->type = TYPEFUNC; tfunc->functype = rettype; tfunc->args = args; CDecl_SetFuncFlags(tfunc, 0); obj->name = name; obj->type = TYPE(tfunc); if (flag == 1) obj->qual = Q_80000; return obj; } Boolean CParser_IsPublicRuntimeObject(Object *obj) { if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next) return 1; if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next) return 1; if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next) return 1; if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next) return 1; return CodeGen_IsPublicRuntimeObject(obj); } Object *CParser_FindPublicRuntimeObject(HashNameNode *name) { NameSpaceObjectList *list = CScope_FindName(cscope_root, name); if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG)) return OBJECT(list->object); else return NULL; } Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) { if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW)))) return 0; if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY)))) return 0; if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE)))) return 0; if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY)))) return 0; newh_func->name = GetHashNameNodeExport("__new_hdl"); delh_func->name = GetHashNameNodeExport("__del_hdl"); copy_func->name = GetHashNameNodeExport("__copy"); clear_func->name = GetHashNameNodeExport("__clear"); Rgtid_func->name = GetHashNameNodeExport("__get_typeid"); Rdync_func->name = GetHashNameNodeExport("__dynamic_cast"); rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast"); rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr"); rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test"); rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call"); rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall"); rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4"); rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4"); rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null"); rt_som_new->name = GetHashNameNodeExport("__som_new"); rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new"); rt_som_check->name = GetHashNameNodeExport("__som_check_ev"); rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4"); rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5"); rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_"); carr_func->name = GetHashNameNodeExport("__construct_array"); cnar_func->name = GetHashNameNodeExport("__construct_new_array"); darr_func->name = GetHashNameNodeExport("__destroy_arr"); dnar_func->name = GetHashNameNodeExport("__destroy_new_array"); dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3"); Xgreg_func->name = GetHashNameNodeExport("__register_global_object"); Xthrw_func->name = GetHashNameNodeExport("__throw"); Xicth_func->name = GetHashNameNodeExport("__init__catch"); Xecth_func->name = GetHashNameNodeExport("__end__catch"); Xunex_func->name = GetHashNameNodeExport("__unexpected"); CMangler_Setup(); no_name_node = GetHashNameNodeExport("@no_name@"); temp_argument_name = GetHashNameNodeExport("@temp_ptr@"); this_name_node = GetHashNameNodeExport("this"); self_name_node = GetHashNameNodeExport("self"); vptr_name_node = GetHashNameNodeExport("__vptr$"); CSOM_Setup(is_precompiler); return CodeGen_ReInitRuntimeObjects(is_precompiler); } static void CParser_SetupRuntimeObjects(void) { ExceptSpecList *exspecs; Type *sizet; Object *func; exspecs = galloc(sizeof(ExceptSpecList)); memclrw(exspecs, sizeof(ExceptSpecList)); sizet = CABI_GetSizeTType(); func = CParser_NewRTFunc( TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1, 1, sizet); CScope_AddGlobalObject(func); func = CParser_NewRTFunc( TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1, 1, sizet); CScope_AddGlobalObject(func); func = CParser_NewRTFunc( TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1, 1, &void_ptr); CError_ASSERT(379, IS_TYPE_FUNC(func->type)); TYPE_FUNC(func->type)->exspecs = exspecs; CScope_AddGlobalObject(func); func = CParser_NewRTFunc( TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1, 1, &void_ptr); CError_ASSERT(387, IS_TYPE_FUNC(func->type)); TYPE_FUNC(func->type)->exspecs = exspecs; CScope_AddGlobalObject(func); newh_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 0, 1, sizet); delh_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); Rgtid_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 0, 2, &void_ptr, &stsignedlong); Rdync_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 0, 5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort); copy_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 2, 3, &void_ptr, &void_ptr, sizet); clear_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 2, 2, &void_ptr, sizet); rt_ptmf_cast = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 2, 3, &stsignedlong, &void_ptr, &void_ptr); rt_ptmf_cmpr = CParser_NewRTFunc( TYPE(&stsignedlong), NULL, 2, 2, &void_ptr, &void_ptr); rt_ptmf_test = CParser_NewRTFunc( TYPE(&stsignedlong), NULL, 2, 1, &void_ptr); rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_ptmf_null = CParser_NewGlobalDataObject(NULL); rt_ptmf_null->type = &stvoid; rt_som_new = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 2, 3, &void_ptr, &stsignedlong, &stsignedlong); rt_som_newcheck = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); rt_som_check = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); carr_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); cnar_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 0, 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); darr_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 4, &void_ptr, &void_ptr, sizet, sizet); dnar_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 2, &void_ptr, &void_ptr); dnar3_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort); Xgreg_func = CParser_NewRTFunc( TYPE(&void_ptr), NULL, 0, 3, &void_ptr, &void_ptr, &void_ptr); Xthrw_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 3, &void_ptr, &void_ptr, &void_ptr); Xicth_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); Xecth_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); Xunex_func = CParser_NewRTFunc( TYPE(&stvoid), NULL, 0, 1, &void_ptr); CodeGen_SetupRuntimeObjects(); CError_ASSERT(534, CParser_ReInitRuntimeObjects(0)); } void CParser_Setup(void) { CScope_Setup(); name_mangle_list.data = NULL; if (InitGList(&name_mangle_list, 256)) CError_NoMem(); void_ptr.size = 4; CError_Init(); CInit_Init(); CClass_Init(); CIRTrans_Setup(); CObjC_Setup(); CInline_Init(); in_assembler = 0; in_func_arglist = 0; CParser_SetUniqueID(1); dont_set_references = 0; copts.sideeffects = 1; cparser_classactions = NULL; name_obj_check = NULL; callbackactions = NULL; init_expressions = NULL; cparser_sfunclist = NULL; trychain = NULL; cparser_parentcleanup = NULL; memclrw(&cparser_fileoffset, sizeof(FileOffsetInfo)); memclrw(&catchinfostruct, sizeof(TypeStruct)); catchinfostruct.type = TYPESTRUCT; catchinfostruct.size = 24; catchinfostruct.stype = STRUCT_TYPE_STRUCT; catchinfostruct.align = 4; memclrw(&ptmstruct, sizeof(TypeStruct)); ptmstruct.type = TYPESTRUCT; ptmstruct.size = 12; ptmstruct.stype = STRUCT_TYPE_STRUCT; ptmstruct.align = 4; CMach_Configure(); CTempl_Setup(); uniquenamespacename = NULL; disallowgreaterthan = 0; CParser_SetupRuntimeObjects(); } void CParser_Cleanup(void) { CTempl_Cleanup(); CIRTrans_Cleanup(); CObjC_Cleanup(); CScope_Cleanup(); FreeGList(&name_mangle_list); } short GetPrec(short token) { switch (token) { case '%': case '*': case '/': return 11; case '+': case '-': return 10; case TK_SHL: case TK_SHR: return 9; case '<': case '>': case TK_LESS_EQUAL: case TK_GREATER_EQUAL: return 8; case TK_LOGICAL_EQ: case TK_LOGICAL_NE: return 7; case '&': return 6; case '^': return 5; case '|': return 4; case TK_LOGICAL_AND: return 3; case TK_LOGICAL_OR: return 2; default: return 0; } } Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2) { HashNameNode *name; switch ((tk = lex())) { case TK_NEW: case TK_DELETE: if (lookahead() == '[') { lex(); if (lex() != ']') CError_Error(CErrorStr125); //if (tk == TK_NEW) // tk = TK_NEW_ARRAY; //else // tk = TK_DELETE_ARRAY; tk = (tk == TK_NEW) ? TK_NEW_ARRAY : TK_DELETE_ARRAY; } break; case '(': if ((tk = lex()) != ')') { CError_Error(CErrorStr204); return 0; } tk = '('; break; case '[': if ((tk = lex()) != ']') { CError_Error(CErrorStr204); return 0; } tk = '['; break; } if ((name = CMangler_OperatorName(tk))) { if (token) *token = tk; tk = lex(); tkidentifier = name; return 1; } if (flag1) { if (flag2) { DeclInfo declinfo; memclrw(&declinfo, sizeof(DeclInfo)); conversion_type_name(&declinfo); tkidentifier = CMangler_ConversionFuncName(declinfo.thetype, declinfo.qual); } if (token) *token = 0; return 1; } else { CError_Error(CErrorStr204); return 0; } } SInt32 CParser_GetUniqueID(void) { return uniqueid++; } void CParser_PrintUniqueID(char *buf) { SInt32 id; char mybuf[16]; char *ptr; ptr = mybuf; id = CParser_GetUniqueID(); while (id) { *(ptr++) = '0' + (id - ((id / 10) * 10)); id = id / 10; } while (ptr > mybuf) *(buf++) = *(--ptr); *buf = 0; } void CParser_SetUniqueID(SInt32 id) { uniqueid = id; } HashNameNode *CParser_GetUniqueName(void) { char buf[20]; buf[0] = '@'; CParser_PrintUniqueID(buf + 1); return GetHashNameNodeExport(buf); } HashNameNode *CParser_NameConcat(const char *a, const char *b) { char mybuf[256]; char *buf; char *dst; int len; len = strlen(a) + strlen(b); if (len > (sizeof(mybuf) - 1)) { buf = lalloc(len + 1); dst = buf; } else { buf = mybuf; dst = buf; } while (*a) *(dst++) = *(a++); while (*b) *(dst++) = *(b++); *dst = 0; return GetHashNameNodeExport(buf); } HashNameNode *CParser_AppendUniqueName(char *prefix) { char buf[256]; char *dst; int i; dst = buf; for (i = 0; *prefix && i < 240; i++) { *(dst++) = *(prefix++); } *(dst++) = '$'; CParser_PrintUniqueID(dst); return GetHashNameNodeExport(buf); } HashNameNode *CParser_AppendUniqueNameFile(char *prefix) { Str255 filename; char buf[256]; char *src; char *dst; char c; int i; int j; int len; dst = buf; for (i = 0; *prefix && i < 200; i++) { *(dst++) = *(prefix++); } *(dst++) = '$'; CParser_PrintUniqueID(dst); while (*dst) { dst++; i++; } COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); src = (char *) &filename[1]; len = filename[0]; for (j = 0; j < len && i < 255; j++, i++) { c = *(src++); if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) c = '_'; *(dst++) = c; } dst[0] = 0; return GetHashNameNodeExport(buf); } static HashNameNode *CParser_GetUnnamedNameSpaceName(void) { Str255 filename; char buf[256]; char *src; char *dst; char c; int i; int len; if (!uniquenamespacename) { strcpy(buf, "@unnamed@"); dst = buf + strlen(buf); COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); src = (char *) &filename[1]; len = filename[0]; for (i = 0; i < len && dst < &buf[254]; i++) { c = *(src++); if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) c = '_'; *(dst++) = c; } dst[0] = '@'; dst[1] = 0; uniquenamespacename = GetHashNameNodeExport(buf); } return uniquenamespacename; } Boolean IsTempName(HashNameNode *name) { return !name || (name->name[0] == '@') || (name->name[0] == '$'); } static void CParser_SetCFMFlags(Object *object, DeclInfo *declinfo) { if (declinfo && declinfo->exportflags) object->flags |= declinfo->exportflags; if (object->datatype == DDATA) { if (copts.cfm_export) object->flags = object->flags | OBJECT_FLAGS_40; if (copts.cfm_internal) object->flags = object->flags | OBJECT_FLAGS_10; } else if (copts.cfm_internal) { object->flags = object->flags | OBJECT_FLAGS_10; } else { if (copts.cfm_import) object->flags = object->flags | OBJECT_FLAGS_20; if (copts.cfm_export) object->flags = object->flags | OBJECT_FLAGS_40; if (copts.cfm_lib_export) object->flags = object->flags | OBJECT_FLAGS_20 | OBJECT_FLAGS_40; } } void CParser_UpdateObject(Object *object, DeclInfo *declinfo) { if (declinfo && declinfo->section) object->section = declinfo->section; CParser_SetCFMFlags(object, declinfo); CodeGen_UpdateObject(object); } Object *CParser_NewObject(DeclInfo *declinfo) { Object *object = galloc(sizeof(Object)); memclrw(object, sizeof(Object)); CParser_SetCFMFlags(object, declinfo); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->section = SECT_DEFAULT; return object; } Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) { Object *object = lalloc(sizeof(Object)); memclrw(object, sizeof(Object)); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->datatype = DLOCAL; if (declinfo) { object->type = declinfo->thetype; object->name = declinfo->name; object->qual = declinfo->qual; object->sclass = declinfo->storageclass; } if (add_to_locals) { ObjectList *list = lalloc(sizeof(ObjectList)); list->object = object; list->next = locals; locals = list; } return object; } Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) { Object *object = galloc(sizeof(Object)); memclrw(object, sizeof(Object)); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->section = SECT_DEFAULT; object->datatype = DDATA; object->nspace = cscope_current; if (declinfo) { object->type = declinfo->thetype; object->name = declinfo->name; object->qual = declinfo->qual; object->sclass = declinfo->storageclass; if (copts.cplusplus && !declinfo->x4E) object->qual |= Q_80000; } CParser_UpdateObject(object, declinfo); return object; } Object *CParser_NewCompilerDefDataObject(void) { Object *object = galloc(sizeof(Object)); memclrw(object, sizeof(Object)); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->section = SECT_DEFAULT; object->datatype = DDATA; object->nspace = cscope_root; return object; } Object *CParser_NewFunctionObject(DeclInfo *declinfo) { Object *object = galloc(sizeof(Object)); memclrw(object, sizeof(Object)); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->section = SECT_DEFAULT; object->datatype = DFUNC; object->nspace = cscope_current; if (declinfo) { object->type = declinfo->thetype; object->name = declinfo->name; object->qual = declinfo->qual; object->sclass = declinfo->storageclass; if (copts.cplusplus && !declinfo->x4E) object->qual |= Q_80000; } CParser_UpdateObject(object, declinfo); return object; } Object *CParser_NewCompilerDefFunctionObject(void) { Object *object = galloc(sizeof(Object)); memclrw(object, sizeof(Object)); object->otype = OT_OBJECT; object->access = ACCESSPUBLIC; object->section = SECT_DEFAULT; object->datatype = DFUNC; object->nspace = cscope_root; return object; } Object *CParser_NewAliasObject(Object *object, SInt32 offset) { Object *alias = galloc(sizeof(Object)); *alias = *object; alias->datatype = DALIAS; alias->u.alias.object = object; alias->u.alias.member = NULL; alias->u.alias.offset = offset; CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias)); return alias; } FuncArg *CParser_NewFuncArg(void) { FuncArg *arg = galloc(sizeof(FuncArg)); memclrw(arg, sizeof(FuncArg)); return arg; } Type *atomtype(void) { switch (tksize) { default: CError_FATAL(1145); case ATOM_VOID: return &stvoid; case ATOM_CHAR: return TYPE(&stchar); case ATOM_WCHAR: return TYPE(&stwchar); case ATOM_UCHAR: return TYPE(&stunsignedchar); case ATOM_SHORT: return TYPE(&stsignedshort); case ATOM_USHORT: return TYPE(&stunsignedshort); case ATOM_INT: return TYPE(&stsignedint); case ATOM_UINT: return TYPE(&stunsignedint); case ATOM_LONG: return TYPE(&stsignedlong); case ATOM_ULONG: return TYPE(&stunsignedlong); case ATOM_LONGLONG: return TYPE(&stsignedlonglong); case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong); case ATOM_FLOAT: return TYPE(&stfloat); case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble); case ATOM_DOUBLE: return TYPE(&stdouble); case ATOM_LONGDOUBLE: return TYPE(&stlongdouble); } } Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) { NameSpaceObjectList *list; NameSpaceObjectList *scan; NameSpaceObjectList mylist; CScopeParseResult pr; Boolean first_time; Boolean retry_flag; Object *obj; Type *sizet; list = NULL; *outflag = 0; if (IS_TYPE_CLASS(type) && !flag2) { HashNameNode *name; name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name; if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { if (pr.obj_10) { mylist.next = NULL; mylist.object = pr.obj_10; list = &mylist; } else { CError_ASSERT(1202, pr.nsol_14); list = pr.nsol_14; } } else if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) { CError_ASSERT(1210, !args && !flag1); return delh_func; } } first_time = 1; retry_flag = flag1; while (1) { if (!args) { for (scan = list; scan; scan = scan->next) { obj = OBJECT(scan->object); if ( obj->otype == OT_OBJECT && IS_TYPE_FUNC(obj->type) && TYPE_FUNC(obj->type)->args && !TYPE_FUNC(obj->type)->args->next && is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) ) return obj; } CError_ASSERT(1231, first_time); sizet = CABI_GetSizeTType(); for (scan = list; scan; scan = scan->next) { obj = OBJECT(scan->object); if ( obj->otype == OT_OBJECT && IS_TYPE_FUNC(obj->type) && TYPE_FUNC(obj->type)->args && TYPE_FUNC(obj->type)->args->next && !TYPE_FUNC(obj->type)->args->next->next && is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) && TYPE_FUNC(obj->type)->args->next->type == sizet ) { *outflag = 1; return obj; } } } else { for (scan = list; scan; scan = scan->next) { obj = OBJECT(scan->object); if ( obj->otype == OT_OBJECT && IS_TYPE_FUNC(obj->type) && TYPE_FUNC(obj->type)->args && TYPE_FUNC(obj->type)->args->next && is_arglistsame(TYPE_FUNC(obj->type)->args->next, args) ) { *outflag = 1; return obj; } } if (!first_time) return NULL; } if (list) CError_Warning(CErrorStr375, type, 0); list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first; first_time = 0; } } static Boolean oldstylecompatible(FuncArg *arg) { if (copts.ignore_oldstyle) return 1; while (arg) { if (arg == &elipsis) return 0; switch (arg->type->type) { case TYPEINT: if (TYPE_INTEGRAL(arg->type)->integral < IT_INT) return 0; break; case TYPEFLOAT: if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE) return 0; break; } arg = arg->next; } return 1; } static Boolean is_arglistequal(FuncArg *a, FuncArg *b) { if (a == &oldstyle) { if (b == &oldstyle) return 1; else return oldstylecompatible(b); } else { if (b == &oldstyle) return oldstylecompatible(a); } while (1) { if (a == &elipsis || b == &elipsis) return 1; if (!a) return !b; if (!b) return 0; if (copts.mpwc_relax && !copts.cplusplus) { if (!is_typeequal(a->type, b->type)) return 0; } else { if (!is_typesame(a->type, b->type)) return 0; } if (a->type->type == TYPEPOINTER && a->qual != b->qual) return 0; a = a->next; b = b->next; } } short is_memberpointerequal(Type *a, Type *b) { FuncArg *arg_a; FuncArg *arg_b; if (a->type != b->type) return 0; if (!IS_TYPE_FUNC(a)) return is_typeequal(a, b); if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) return 0; if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) return 0; CError_ASSERT(1345, arg_a = TYPE_FUNC(a)->args); CError_ASSERT(1346, arg_b = TYPE_FUNC(b)->args); if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80) CError_ASSERT(1351, arg_a = arg_a->next); if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80) CError_ASSERT(1355, arg_b = arg_b->next); if (arg_a->qual != arg_b->qual) return 0; return is_arglistsame(arg_a->next, arg_b->next); } short is_typeequal(Type *a, Type *b) { restart: if (a->type != b->type) return 0; switch (a->type) { case TYPEVOID: return 1; case TYPEINT: case TYPEFLOAT: case TYPEENUM: case TYPECLASS: return a == b; case TYPESTRUCT: return a == b; case TYPEPOINTER: if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid) return 1; a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; if (copts.mpwc_relax && !copts.cplusplus) return 1; goto restart; case TYPEMEMBERPOINTER: if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) return 0; return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); case TYPEARRAY: if (a->size && b->size && a->size != b->size) return 0; a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; goto restart; case TYPEFUNC: if (copts.cplusplus || !copts.cpp_extensions) { if (copts.mpwc_relax && !copts.cplusplus) { if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) return 0; } else { if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) return 0; } if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) return 0; } return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); case TYPETEMPLATE: return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); default: CError_FATAL(1441); return 0; } } short iscpp_typeequal(Type *a, Type *b) { restart: if (a->type != b->type) return 0; switch (a->type) { case TYPEVOID: return 1; case TYPEINT: case TYPEFLOAT: case TYPEENUM: case TYPECLASS: return a == b; case TYPESTRUCT: return a == b; case TYPEPOINTER: if (TYPE_POINTER(b)->target == &stvoid) { if (TYPE_POINTER(a)->target == &stvoid) return 1; else return -1; } if (TYPE_POINTER(a)->target == &stvoid) { illegalimplicitconversion = 1; return 0; } a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; goto restart; case TYPEMEMBERPOINTER: if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) return 0; return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); case TYPEARRAY: if (a->size && b->size && a->size != b->size) return 0; a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; goto restart; case TYPEFUNC: if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) return 0; if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) return 0; return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); case TYPETEMPLATE: return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); default: CError_FATAL(1500); return 0; } } short CParser_CompareArgLists(FuncArg *a, FuncArg *b) { Boolean r30; r30 = 0; if (a == &oldstyle) { if (b == &oldstyle) return 1; else return 2; } if (b == &oldstyle) return 2; while (1) { if (a == &elipsis) { if (b != &elipsis) return 0; break; } if (b == &elipsis) return 0; if (a == NULL) { if (b) return 0; break; } if (b == NULL) return 0; if (a->type->type == TYPEPOINTER) { if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) { if (IS_TYPE_REFERENCE(b->type)) { if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) return 0; if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) return 0; } else { if (!copts.old_argmatch) return 0; if (!is_typesame(TYPE_POINTER(a->type)->target, b->type)) return 0; if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) return 0; r30 = 1; } } else { if (b->type->type == TYPEPOINTER) { if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { if (!copts.old_argmatch) return 0; if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) return 0; if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) return 0; r30 = 1; } else { if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) return 0; if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) return 0; } } else { return 0; } } } else { if (b->type->type == TYPEPOINTER) { if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { if (!copts.old_argmatch) return 0; if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) return 0; r30 = 1; } else { return 0; } } else { if (!is_typesame(a->type, b->type)) return 0; } } a = a->next; b = b->next; } if (r30) return 2; return 1; } Boolean is_arglistsame(FuncArg *a, FuncArg *b) { if (a == &oldstyle) { if (b == &oldstyle) return 1; else return oldstylecompatible(b); } else { if (b == &oldstyle) return oldstylecompatible(a); } while (1) { if (!a || !b || a == &elipsis || b == &elipsis) return a == b; if (a->type->type == TYPEPOINTER) { if (b->type->type != TYPEPOINTER || (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) || !is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) return 0; } else { if (!is_typesame(a->type, b->type)) return 0; } a = a->next; b = b->next; } } short is_typesame(Type *a, Type *b) { restart: if (a->type != b->type) { if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_FLAGS_100)) return CTemplTool_IsSameTemplateType(b, a); if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_FLAGS_100)) return CTemplTool_IsSameTemplateType(a, b); return 0; } switch (a->type) { case TYPEVOID: return 1; case TYPEINT: case TYPEFLOAT: case TYPEENUM: case TYPECLASS: return a == b; case TYPETEMPLATE: return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); case TYPESTRUCT: return a == b; case TYPEPOINTER: if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) return 0; a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; goto restart; case TYPEMEMBERPOINTER: if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2)) return 0; if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) return 0; return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); case TYPEARRAY: if (a->size != b->size) return 0; a = TYPE_POINTER(a)->target; b = TYPE_POINTER(b)->target; goto restart; case TYPEFUNC: if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) return 0; if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual) return 0; if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL))) return 0; return is_arglistsame(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); default: CError_FATAL(1709); return 0; } } Type *CParser_GetBoolType(void) { if (copts.cplusplus && copts.booltruefalse) return TYPE(&stbool); else return TYPE(&stsignedint); } Type *CParser_GetWCharType(void) { if (copts.cplusplus && copts.wchar_type) return TYPE(&stwchar); else return TYPE(&stsignedint); } short CParser_GetOperator(ENodeType t) { switch (t) { default: CError_FATAL(1748); case EMONMIN: return '-'; case EBINNOT: return '~'; case ELOGNOT: return '!'; case EADD: return '+'; case ESUB: return '-'; case EMUL: return '*'; case EDIV: return '/'; case EMODULO: return '%'; case EAND: return '&'; case EXOR: return '^'; case EOR: return '|'; case ESHL: return TK_SHL; case ESHR: return TK_SHR; case ELESS: return '<'; case EGREATER: return '>'; case ELESSEQU: return TK_LESS_EQUAL; case EGREATEREQU: return TK_GREATER_EQUAL; case EEQU: return TK_LOGICAL_EQ; case ENOTEQU: return TK_LOGICAL_NE; } } Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) { if ((a & Q_CONST) && !(b & Q_CONST)) { return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { return ((a & Q_CONST) || !(b & Q_CONST)); } return 0; } Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) { if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE))) return 1; if ((a & Q_CONST) && !(b & Q_CONST)) { return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { return ((a & Q_CONST) || !(b & Q_CONST)); } return 0; } Boolean is_unsigned(Type *type) { if (IS_TYPE_ENUM(type)) type = TYPE_ENUM(type)->enumtype; if ( (type == TYPE(&stunsignedchar)) || (type == TYPE(&stunsignedshort)) || (type == TYPE(&stunsignedint)) || (type == TYPE(&stunsignedlong)) || (type == TYPE(&stunsignedlonglong)) || (type == TYPE(&stbool)) || (copts.unsigned_char && (type == TYPE(&stchar))) || (type->type == TYPEPOINTER)) return 1; return 0; } StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) { StructMember *member; for (member = tstruct->members; member; member = member->next) { if (member->name == name) return member; } return NULL; } void appendmember(TypeStruct *tstruct, StructMember *member) { StructMember *last; if (!tstruct->members) { tstruct->members = member; return; } for (last = tstruct->members; last->next; last = last->next) {} last->next = member; } static void CParser_InsertTryBlock(ParserTryBlock *block) { block->cscope_current = cscope_current; block->cscope_currentclass = cscope_currentclass; block->cscope_currentfunc = cscope_currentfunc; block->ctempl_curinstance = ctempl_curinstance; block->cerror_locktoken = cerror_locktoken; block->cscope_is_member_func = cscope_is_member_func; block->next = trychain; trychain = block; } static void CParser_RemoveTryBlock(ParserTryBlock *block) { cscope_current = block->cscope_current; cscope_currentclass = block->cscope_currentclass; cscope_currentfunc = block->cscope_currentfunc; ctempl_curinstance = block->ctempl_curinstance; cerror_locktoken = block->cerror_locktoken; cscope_is_member_func = block->cscope_is_member_func; trychain = block->next; } static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) { Boolean result; DeclInfo declinfo; struct ParserTryBlock tryblock; switch (tk) { case TK_IDENTIFIER: case TK_COLON_COLON: break; case TK_VOID: case TK_CHAR: case TK_SHORT: case TK_INT: case TK_LONG: case TK_FLOAT: case TK_DOUBLE: case TK_SIGNED: case TK_UNSIGNED: case TK_UNK_113: case TK_UNK_114: case TK_UNK_115: case TK_UNK_116: case TK_UNK_117: case TK_UNK_118: case TK_UNK_119: case TK_UNK_11A: case TK_BOOL: case TK_WCHAR_T: if (lookahead() != '(') return 1; break; default: return 1; } result = 0; CParser_InsertTryBlock(&tryblock); if (setjmp(tryblock.jmpbuf) == 0) { memclrw(&declinfo, sizeof(DeclInfo)); CParser_GetDeclSpecs(&declinfo, 0); if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) { if (flag1) { declinfo.x46 = flag3; scandeclarator(&declinfo); if (!(flag2 && declinfo.name)) { if (!token) { if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>') result = 1; } else { result = (tk == token); } } } else { result = 1; } } } CParser_RemoveTryBlock(&tryblock); return result; } Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) { SInt32 state; if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) return 0; } else { if (!copts.cplusplus) return 1; } CPrep_TokenStreamGetState(&state); if (TryIsDeclaration(flag1, flag2, flag3, token)) { CPrep_TokenStreamSetCurState(&state); return 1; } else { CPrep_TokenStreamSetCurState(&state); return 0; } } Boolean islookaheaddeclaration(void) { SInt32 state; CPrep_TokenStreamGetState(&state); tk = lex(); if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) { CPrep_TokenStreamSetCurState(&state); return 0; } } else { if (!copts.cplusplus) { CPrep_TokenStreamSetCurState(&state); return 1; } } if (TryIsDeclaration(1, 1, 0, ')')) { CPrep_TokenStreamSetCurState(&state); return 1; } else { CPrep_TokenStreamSetCurState(&state); return 0; } } Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) { SInt32 state; DeclInfo di; struct ParserTryBlock tryblock; memclrw(&di, sizeof(DeclInfo)); CPrep_TokenStreamGetState(&state); CParser_InsertTryBlock(&tryblock); if (setjmp(tryblock.jmpbuf) == 0) { if (copts.cplusplus) di.x55 = 1; if (flag) { di.x56 = 1; *flag = 0; } CParser_GetDeclSpecs(&di, 0); if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_100)) { CParser_RemoveTryBlock(&tryblock); *qual = di.qual; *flag = 1; return di.thetype; } if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) { CParser_RemoveTryBlock(&tryblock); *qual = di.qual; *flag = 1; return di.thetype; } scandeclarator(&di); if (!di.name) { CParser_RemoveTryBlock(&tryblock); *qual = di.qual; return di.thetype; } } CPrep_TokenStreamSetCurState(&state); CParser_RemoveTryBlock(&tryblock); return 0; } Boolean CParser_TryFuncDecl(void) { Boolean result; SInt32 state; DeclInfo di; struct ParserTryBlock tryblock; result = 0; CPrep_TokenStreamGetState(&state); CParser_InsertTryBlock(&tryblock); if (setjmp(tryblock.jmpbuf) == 0) { memclrw(&di, sizeof(DeclInfo)); di.thetype = &stvoid; scandeclarator(&di); if (IS_TYPE_FUNC(di.thetype)) result = 1; } CParser_RemoveTryBlock(&tryblock); CPrep_TokenStreamSetCurState(&state); return result; } Boolean CParser_TryParamList(Boolean flag) { Boolean result; SInt32 state; struct ParserTryBlock tryblock; result = 0; CPrep_TokenStreamGetState(&state); switch ((tk = lex())) { case ')': case TK_ELLIPSIS: result = 1; break; default: CParser_InsertTryBlock(&tryblock); if (setjmp(tryblock.jmpbuf) == 0) { if (CFunc_ParseFakeArgList(flag) || tk == ')') result = 1; } CParser_RemoveTryBlock(&tryblock); break; } CPrep_TokenStreamSetCurState(&state); return result; } Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) { switch (type->type) { case TYPEARRAY: TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual); return type; case TYPEPOINTER: if (TYPE_POINTER(type)->qual & Q_CONST) { TypePointer *newtype = galloc(sizeof(TypePointer)); *newtype = *TYPE_POINTER(type); newtype->qual = 0; return TYPE(newtype); } return type; case TYPEMEMBERPOINTER: if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) { TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer)); *newtype = *TYPE_MEMBER_POINTER(type); newtype->qual = 0; return TYPE(newtype); } return type; default: *qual = 0; return type; } } UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) { while (IS_TYPE_ARRAY(type)) type = TYPE_POINTER(type)->target; switch (type->type) { case TYPEPOINTER: qual = TYPE_POINTER(type)->qual; break; case TYPEMEMBERPOINTER: qual = TYPE_MEMBER_POINTER(type)->qual; break; } return qual; } UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) { while (IS_TYPE_ARRAY(type)) type = TYPE_POINTER(type)->target; switch (type->type) { case TYPEPOINTER: qual = TYPE_POINTER(type)->qual; break; case TYPEMEMBERPOINTER: qual = TYPE_MEMBER_POINTER(type)->qual; break; } return qual & (Q_CONST | Q_VOLATILE); } Boolean CParser_IsConst(Type *type, UInt32 qual) { while (IS_TYPE_ARRAY(type)) type = TYPE_POINTER(type)->target; switch (type->type) { case TYPEPOINTER: qual = TYPE_POINTER(type)->qual; break; case TYPEMEMBERPOINTER: qual = TYPE_MEMBER_POINTER(type)->qual; break; } return (qual & Q_CONST) != 0; } Boolean CParser_IsVolatile(Type *type, UInt32 qual) { while (IS_TYPE_ARRAY(type)) type = TYPE_POINTER(type)->target; switch (type->type) { case TYPEPOINTER: qual = TYPE_POINTER(type)->qual; break; case TYPEMEMBERPOINTER: qual = TYPE_MEMBER_POINTER(type)->qual; break; } return (qual & Q_VOLATILE) != 0; } Boolean is_const_object(Object *obj) { return CParser_IsConst(obj->type, obj->qual); } Boolean is_volatile_object(Object *obj) { return CParser_IsVolatile(obj->type, obj->qual); } Boolean CParserIsConstExpr(ENode *expr) { return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS); } Boolean CParserIsVolatileExpr(ENode *expr) { return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS); } Boolean CParser_HasInternalLinkage(const Object *obj) { NameSpace *nspace; for (nspace = obj->nspace; nspace; nspace = nspace->parent) { if (nspace->is_unnamed) return 1; } if (obj->datatype == DLOCAL) return 1; if (obj->qual & (Q_20000 | Q_OVERLOAD)) return 0; if (obj->sclass == TK_STATIC) return 1; // this feels *wrong* but it's the only way to match this function that I can see if (obj->qual & Q_INLINE) ((Object *) obj)->qual |= Q_20000; return 0; } Boolean CParser_HasInternalLinkage2(const Object *obj) { if (obj->datatype == DLOCAL) return 1; if (obj->qual & (Q_20000 | Q_OVERLOAD)) return 0; if (obj->sclass == TK_STATIC) return 1; // this feels *wrong* but it's the only way to match this function that I can see if (obj->qual & Q_INLINE) ((Object *) obj)->qual |= Q_20000; return 0; } Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) { if (obj->datatype == DVFUNC) { *tclass = TYPE_METHOD(obj->type)->theclass; *index = TYPE_METHOD(obj->type)->x1E; return 1; } return 0; } Boolean is_pascal_object(Object *obj) { return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_PASCAL); } Boolean is_cfm_type(Type *type) { return 0; } Boolean CParser_IsVTableObject(Object *obj) { return obj->datatype == DDATA && obj->nspace && obj->nspace->theclass && obj->nspace->theclass->vtable && obj->nspace->theclass->vtable->object == obj; } static Type *getthetype(short token, short size, short signedness) { switch (token) { case 0: case TK_INT: if (signedness == 1) { switch (size) { case 1: return TYPE(&stunsignedshort); case 2: return TYPE(&stunsignedlong); case 3: return TYPE(&stunsignedlonglong); default: return TYPE(&stunsignedint); } } else { switch (size) { case 1: return TYPE(&stsignedshort); case 2: return TYPE(&stsignedlong); case 3: return TYPE(&stsignedlonglong); default: return TYPE(&stsignedint); } } case TK_BOOL: return TYPE(&stbool); case TK_WCHAR_T: return TYPE(&stwchar); case TK_CHAR: switch (signedness) { case 1: return TYPE(&stunsignedchar); default: return TYPE(&stchar); case -1: return TYPE(&stsignedchar); } case TK_DOUBLE: switch (size) { case 1: return TYPE(&stshortdouble); case 2: return TYPE(&stlongdouble); default: return TYPE(&stdouble); } case TK_FLOAT: return TYPE(&stfloat); case TK_VOID: return TYPE(&stvoid); default: CError_Error(CErrorStr121); return TYPE(&stvoid); } } void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual) { if (type->type == TYPEPOINTER) { if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(type))) { declinfo->thetype = type; declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); declinfo->qual |= qual; return; } declinfo->thetype = galloc(sizeof(TypePointer)); *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); TYPE_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); } else if (type->type == TYPEMEMBERPOINTER) { declinfo->thetype = galloc(sizeof(TypeMemberPointer)); *TYPE_MEMBER_POINTER(declinfo->thetype) = *TYPE_MEMBER_POINTER(type); TYPE_MEMBER_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); } else { declinfo->thetype = type; declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size) { declinfo->thetype = galloc(sizeof(TypePointer)); *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); } } declinfo->x49 = 1; } static void CParser_ParseAttributeFunctionSummary(DeclInfo *declinfo) { Boolean flag; if ((tk = lex()) != '(') { CError_Error(CErrorStr114); return; } flag = 1; tk = lookahead(); while (tk == TK_IDENTIFIER) { if (flag && !strcmp(tkidentifier->name, "entry_points_to")) { PointerAnalysis_ParseEntryPointsToSpecifier(declinfo); } else if (!strcmp(tkidentifier->name, "exit_points_to")) { PointerAnalysis_ParseExitPointsToSpecifier(declinfo); flag = 0; } else if (!strcmp(tkidentifier->name, "function_modifies")) { PointerAnalysis_ParseFunctionModifiesSpecifier(declinfo); flag = 0; } else { lex(); CError_Error(CErrorStr121); return; } tk = lookahead(); if (tk == ',') { lex(); tk = lookahead(); } } lex(); if (tk != ')') CError_Error(CErrorStr121); } void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) { CInt64 val64; SInt32 val; do { if ((tk = lex()) != '(') { CError_Error(CErrorStr121); return; } if ((tk = lex()) != '(') { CError_Error(CErrorStr121); return; } if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) { CError_Error(CErrorStr121); return; } if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) { if ((tk = lex()) != '(') { CError_Error(CErrorStr121); return; } tk = lex(); val64 = CExpr_IntegralConstExpr(); switch ((val = CInt64_GetULong(&val64))) { case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: case 0x80: case 0x100: case 0x200: case 0x400: case 0x800: case 0x1000: case 0x2000: break; default: CError_Error(CErrorStr124); return; } if (type) { if (IS_TYPE_STRUCT(type)) { if (val > TYPE_STRUCT(type)->align) { TYPE_STRUCT(type)->align = val; type->size += CABI_StructSizeAlignValue(type, type->size); } } else if (IS_TYPE_CLASS(type)) { if (val > TYPE_CLASS(type)->align) { TYPE_CLASS(type)->align = val; type->size += CABI_StructSizeAlignValue(type, type->size); } } else { CError_Error(CErrorStr149); } } else if (declinfo) { declinfo->qual &= ~Q_ALIGNED_MASK; switch (val) { case 1: declinfo->qual |= Q_ALIGNED_1; break; case 2: declinfo->qual |= Q_ALIGNED_2; break; case 4: declinfo->qual |= Q_ALIGNED_4; break; case 8: declinfo->qual |= Q_ALIGNED_8; break; case 16: declinfo->qual |= Q_ALIGNED_16; break; case 32: declinfo->qual |= Q_ALIGNED_32; break; case 64: declinfo->qual |= Q_ALIGNED_64; break; case 128: declinfo->qual |= Q_ALIGNED_128; break; case 256: declinfo->qual |= Q_ALIGNED_256; break; case 512: declinfo->qual |= Q_ALIGNED_512; break; case 1024: declinfo->qual |= Q_ALIGNED_1024; break; case 2048: declinfo->qual |= Q_ALIGNED_2048; break; case 4096: declinfo->qual |= Q_ALIGNED_4096; break; case 8192: declinfo->qual |= Q_ALIGNED_8192; break; default: CError_FATAL(2779); break; } } else { CError_Error(CErrorStr359); } if (tk != ')') { CError_Error(CErrorStr121); return; } } else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) { if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype)) TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_NOTHROW; else CError_Error(CErrorStr359); } else if (!strcmp("function_summary", tkidentifier->name)) { CParser_ParseAttributeFunctionSummary(declinfo); } else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) { CError_Error(CErrorStr359); } else if (!strcmp(tkidentifier->name, "unused") || !strcmp(tkidentifier->name, "__unused__")) { } else if (!strcmp(tkidentifier->name, "noreturn") || !strcmp(tkidentifier->name, "__noreturn__")) { } else if (tk == TK_CONST || !strcmp(tkidentifier->name, "__const__")) { } else if (!strcmp(tkidentifier->name, "format") || !strcmp(tkidentifier->name, "__format__")) { CError_Warning(CErrorStr359); if ((tk = lex()) != '(') { CError_Warning(CErrorStr114); return; } tk = lex(); if ((tk = lex()) != ',') { CError_Warning(CErrorStr116); return; } tk = lex(); if ((tk = lex()) != ',') { CError_Warning(CErrorStr116); return; } tk = lex(); if ((tk = lex()) != ')') { CError_Warning(CErrorStr115); return; } } else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) { CError_Warning(CErrorStr359); if ((tk = lex()) != '(') { CError_Warning(CErrorStr114); return; } tk = lex(); if ((tk = lex()) != ')') { CError_Warning(CErrorStr115); return; } } else { CError_Error(CErrorStr359); } if ((tk = lex()) != ')') { CError_Error(CErrorStr121); return; } if ((tk = lex()) != ')') { CError_Error(CErrorStr121); return; } tk = lex(); } while (tk == TK_UU_ATTRIBUTE_UU); } static void CParser_ParseTypeOf(DeclInfo *declinfo) { DeclInfo subdi; ENode *expr; if ((tk = lex()) == '(' && islookaheaddeclaration()) { tk = lex(); memclrw(&subdi, sizeof(DeclInfo)); CParser_GetDeclSpecs(&subdi, 0); scandeclarator(&subdi); if (subdi.name) CError_Error(CErrorStr121); if (tk != ')') CError_ErrorSkip(CErrorStr115); else tk = lex(); TypedefDeclInfo(declinfo, subdi.thetype, subdi.qual); } else { expr = unary_expression(); if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) CError_Error(CErrorStr144); TypedefDeclInfo(declinfo, expr->rtype, expr->flags & ENODE_FLAG_QUALS); } } void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag) { if ((tk = lex()) != TK_IDENTIFIER) { if (tk != TK_EXPORT) CError_Error(CErrorStr107); else declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; } else if (!strcmp("internal", tkidentifier->name)) { declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_INTERNAL; } else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) { declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT; } else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) { declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; } else if (!strcmp("lib_export", tkidentifier->name)) { declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT; } else if (!strcmp("weak", tkidentifier->name)) { declinfo->qual |= Q_OVERLOAD; } else { CodeGen_ParseDeclSpec(tkidentifier, declinfo); } } static int CParser_GetVectorDeclSpec(Type **type) { tk = lex(); switch (tk) { case TK_CHAR: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboolchar); tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedchar); tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedchar); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboolchar); tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_SIGNED: tk = lex(); switch (tk) { case TK_CHAR: *type = TYPE(&stvectorsignedchar); tk = lex(); return 1; case TK_SHORT: *type = TYPE(&stvectorsignedshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorsignedlong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorsignedshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorsignedlong); tk = lex(); return 1; default: *type = TYPE(&stvectorsignedlong); return 1; } default: CError_Error(CErrorStr121); } break; case TK_UNSIGNED: tk = lex(); switch (tk) { case TK_CHAR: *type = TYPE(&stvectorunsignedchar); tk = lex(); return 1; case TK_SHORT: *type = TYPE(&stvectorunsignedshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorunsignedlong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorunsignedshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorunsignedlong); tk = lex(); return 1; default: *type = TYPE(&stvectorunsignedlong); return 1; } default: CError_Error(CErrorStr121); } break; case TK_BOOL: tk = lex(); switch (tk) { case TK_CHAR: *type = TYPE(&stvectorboolchar); tk = lex(); return 1; case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); return 1; default: *type = TYPE(&stvectorboollong); return 1; } default: CError_Error(CErrorStr121); } break; case TK_SHORT: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedshort); tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedshort); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_LONG: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboollong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedlong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedlong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboollong); tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedlong); tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedlong); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboollong); tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboollong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_INT: tk = lex(); switch (tk) { case TK_BOOL: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); return 1; default: *type = TYPE(&stvectorboollong); return 1; } case TK_SIGNED: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorsignedshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorsignedlong); tk = lex(); return 1; default: *type = TYPE(&stvectorsignedlong); return 1; } case TK_UNSIGNED: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorunsignedshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorunsignedlong); tk = lex(); return 1; default: *type = TYPE(&stvectorunsignedlong); return 1; } case TK_SHORT: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboolshort); tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedshort); tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedshort); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboolshort); tk = lex(); return 1; } default: CError_Error(CErrorStr121); } break; case TK_LONG: tk = lex(); switch (tk) { case TK_BOOL: *type = TYPE(&stvectorboollong); tk = lex(); return 1; case TK_SIGNED: *type = TYPE(&stvectorsignedlong); tk = lex(); return 1; case TK_UNSIGNED: *type = TYPE(&stvectorunsignedlong); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { *type = TYPE(&stvectorboollong); tk = lex(); return 1; } } case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("bool")) { tk = lex(); switch (tk) { case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); return 1; case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); return 1; default: *type = TYPE(&stvectorboolshort); return 1; } } default: CError_Error(CErrorStr121); } break; case TK_FLOAT: *type = TYPE(&stvectorfloat); tk = lex(); return 1; case TK_IDENTIFIER: if (tkidentifier == GetHashNameNode("pixel") || tkidentifier == GetHashNameNode("__pixel")) { *type = TYPE(&stvectorpixel); tk = lex(); return 1; } if (tkidentifier == GetHashNameNode("bool")) { tk = lex(); switch (tk) { case TK_CHAR: *type = TYPE(&stvectorboolchar); tk = lex(); return 1; case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); if (tk == TK_INT) tk = lex(); return 1; case TK_INT: tk = lex(); switch (tk) { case TK_SHORT: *type = TYPE(&stvectorboolshort); tk = lex(); return 1; case TK_LONG: *type = TYPE(&stvectorboollong); tk = lex(); return 1; default: *type = TYPE(&stvectorboollong); return 1; } } } default: CError_Error(CErrorStr121); } return 0; } Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag) { NameSpace *nspace; if (tmclass->templ__params) { nspace = cscope_current; while (1) { if (!nspace) { if (flag) CError_Error(CErrorStr230); return 0; } if (nspace->theclass == TYPE_CLASS(tmclass)) break; nspace = nspace->parent; } } return 1; } static Boolean CParser_IsAltiVecPrefix(void) { HashNameNode *save = tkidentifier; switch (lookahead()) { case TK_CHAR: case TK_SHORT: case TK_INT: case TK_LONG: case TK_FLOAT: case TK_SIGNED: case TK_UNSIGNED: case TK_BOOL: return 1; case TK_IDENTIFIER: if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel")) return 1; } tkidentifier = save; return 0; } void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) { short typesize; short signedness; short typetoken; Boolean r24; Boolean r23; SInt32 state; CScopeParseResult pr; di->file = CPrep_BrowserCurrentFile(); CPrep_BrowserFilePosition( (CPrepFileInfo **) &di->file2, &di->x60); r24 = 1; r23 = copts.cplusplus; typetoken = 0; signedness = 0; typesize = 0; restart: switch (tk) { case TK_AUTO: case TK_REGISTER: case TK_STATIC: case TK_EXTERN: case TK_TYPEDEF: case TK_MUTABLE: if (di->storageclass) CError_Error(CErrorStr121); di->storageclass = tk; break; case TK_CONST: if (di->thetype) { if (di->thetype->type == TYPEPOINTER) { if (TYPE_POINTER(di->thetype)->qual & Q_CONST) CError_QualifierCheck(Q_CONST); TYPE_POINTER(di->thetype)->qual |= Q_CONST; break; } else if (di->thetype->type == TYPEMEMBERPOINTER) { if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_CONST) CError_QualifierCheck(Q_CONST); TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_CONST; break; } } if (di->qual & Q_CONST) CError_QualifierCheck(Q_CONST); di->qual |= Q_CONST; break; case TK_VOLATILE: if (di->thetype) { if (di->thetype->type == TYPEPOINTER) { if (TYPE_POINTER(di->thetype)->qual & Q_VOLATILE) CError_QualifierCheck(Q_VOLATILE); TYPE_POINTER(di->thetype)->qual |= Q_VOLATILE; break; } else if (di->thetype->type == TYPEMEMBERPOINTER) { if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_VOLATILE) CError_QualifierCheck(Q_VOLATILE); TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_VOLATILE; break; } } if (di->qual & Q_VOLATILE) CError_QualifierCheck(Q_VOLATILE); di->qual |= Q_VOLATILE; break; case TK_PASCAL: if (di->qual & Q_PASCAL) CError_QualifierCheck(Q_PASCAL); di->qual |= Q_PASCAL; break; case TK_EXPLICIT: CError_QualifierCheck(di->qual & Q_EXPLICIT); di->qual |= Q_EXPLICIT; break; case TK_VIRTUAL: CError_QualifierCheck(di->qual & Q_VIRTUAL); di->qual |= Q_VIRTUAL; break; case TK_IN: CError_QualifierCheck(di->qual & Q_IN); di->qual |= Q_IN; break; case TK_OUT: CError_QualifierCheck(di->qual & Q_OUT); di->qual |= Q_OUT; break; case TK_INOUT: CError_QualifierCheck(di->qual & Q_INOUT); di->qual |= Q_INOUT; break; case TK_BYCOPY: CError_QualifierCheck(di->qual & Q_BYCOPY); di->qual |= Q_BYCOPY; break; case TK_BYREF: CError_QualifierCheck(di->qual & Q_BYREF); di->qual |= Q_BYREF; break; case TK_ONEWAY: CError_QualifierCheck(di->qual & Q_ONEWAY); di->qual |= Q_ONEWAY; break; case TK_UU_DECLSPEC: if ((tk = lex()) != '(') CError_Error(CErrorStr114); CParser_ParseDeclSpec(di, 0); if ((tk = lex()) != ')') CError_Error(CErrorStr115); break; case TK_ASM: if (di->qual & Q_ASM) CError_QualifierCheck(Q_ASM); di->qual |= Q_ASM; break; case TK_INLINE: if (di->qual & Q_INLINE) CError_QualifierCheck(Q_INLINE); di->qual |= Q_INLINE; break; case TK_SHORT: if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) CError_Error(CErrorStr121); typesize = 1; break; case TK_LONG: if (copts.longlong) { if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE) CError_Error(CErrorStr121); if (typesize) { if (typesize != 2 || typetoken == TK_DOUBLE) CError_Error(CErrorStr121); typesize = 3; } else { typesize = 2; } } else { if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) CError_Error(CErrorStr121); typesize = 2; } break; case TK_SIGNED: if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) CError_Error(CErrorStr121); signedness = -1; break; case TK_UNSIGNED: if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) CError_Error(CErrorStr121); signedness = 1; break; case TK_VOID: if (typetoken || typesize || signedness) CError_Error(CErrorStr121); typetoken = TK_VOID; break; case TK_FLOAT: if (typetoken || typesize || signedness) CError_Error(CErrorStr121); typetoken = TK_FLOAT; break; case TK_BOOL: if (typetoken || typesize) CError_Error(CErrorStr121); typetoken = TK_BOOL; break; case TK_CHAR: if (typetoken || typesize) CError_Error(CErrorStr121); typetoken = TK_CHAR; break; case TK_WCHAR_T: if (typetoken || typesize || signedness) CError_Error(CErrorStr121); typetoken = TK_WCHAR_T; break; case TK_INT: if (typetoken) CError_Error(CErrorStr121); typetoken = TK_INT; break; case TK_DOUBLE: if (typetoken || signedness) CError_Error(CErrorStr121); typetoken = TK_DOUBLE; break; case TK_STRUCT: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); tk = lex(); scanstruct(di, STRUCT_TYPE_STRUCT); if (tk == TK_UU_ATTRIBUTE_UU) CParser_ParseAttribute(di->thetype, NULL); if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { typetoken = -1; goto restart; } return; case TK_CLASS: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); tk = lex(); CDecl_ParseClass(di, CLASS_MODE_2, 1, 0); if (tk == TK_UU_ATTRIBUTE_UU) CParser_ParseAttribute(di->thetype, NULL); if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { typetoken = -1; goto restart; } return; case TK_UNION: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); tk = lex(); scanstruct(di, STRUCT_TYPE_UNION); if (tk == TK_UU_ATTRIBUTE_UU) CParser_ParseAttribute(di->thetype, NULL); if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { typetoken = -1; goto restart; } return; case TK_ENUM: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); tk = lex(); scanenum(di); if (tk == TK_UU_ATTRIBUTE_UU) CParser_ParseAttribute(di->thetype, NULL); if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { typetoken = -1; goto restart; } return; case TK_TYPENAME: if (typetoken || signedness || typesize || di->x53) CError_Error(CErrorStr121); di->x53 = 1; tk = lex(); if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) { CError_Error(CErrorStr121); break; } goto some_shared_label; case TK_COLON_COLON: if (typetoken || signedness || typesize) goto switchDefault; goto some_shared_label; case TK_UU_VECTOR: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); handle_vector: if (CParser_GetVectorDeclSpec(&di->thetype)) { if (tk == TK_CONST) { if (di->qual == 0) { di->qual |= Q_CONST; tk = lex(); } else { CError_Error(CErrorStr121); } } if (tk == TK_VOLATILE) { if (di->qual == 0) { di->qual |= Q_VOLATILE; tk = lex(); } else { CError_Error(CErrorStr121); } } return; } break; case TK_UU_TYPEOF_UU: if (typetoken || signedness || typesize) CError_Error(CErrorStr121); CParser_ParseTypeOf(di); typetoken = -1; goto bailOut; case TK_IDENTIFIER: if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) { if (CParser_IsAltiVecPrefix()) goto handle_vector; } if (!typetoken && !signedness && !typesize) { if (copts.objective_c && !strcmp(tkidentifier->name, "id")) { di->thetype = CObjC_ParseID(); typetoken = -1; goto bailOut; } some_shared_label: CPrep_TokenStreamGetState(&state); if (CScope_ParseDeclName(&pr)) { if (pr.x8) { if (IS_TYPE_TEMPLATE(pr.x8)) { switch (TYPE_TEMPLATE(pr.x8)->dtype) { case TEMPLDEP_ARGUMENT: switch (TYPE_TEMPLATE(pr.x8)->u.pid.type) { case TPT_TYPE: break; case TPT_NONTYPE: CError_Error(CErrorStr348); pr.x8 = TYPE(&stsignedint); break; case TPT_TEMPLATE: CError_Error(CErrorStr230); pr.x8 = TYPE(&stsignedint); break; default: CError_FATAL(4109); } break; case TEMPLDEP_QUALNAME: if (!di->x53 && !pr.x20 && di->x55) CError_Error(CErrorStr355); break; case TEMPLDEP_TEMPLATE: case TEMPLDEP_ARRAY: case TEMPLDEP_QUALTEMPL: case TEMPLDEP_BITFIELD: break; default: CError_FATAL(4136); } } if (IS_TYPE_CLASS(pr.x8) && (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) { if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 0)) { if (di->x56) { if (di->qual) CError_Error(CErrorStr121); di->thetype = pr.x8; di->x57 = 1; tk = lex(); return; } else { CError_Error(CErrorStr230); pr.x8 = TYPE(&stsignedint); } } } TypedefDeclInfo(di, pr.x8, pr.xC); di->x49 = pr.x20; typetoken = -1; tk = lex(); if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo) di->thetype = CObjC_ParseTypeProtocol(TYPE_CLASS(di->thetype)); goto bailOut; } else if (pr.nsol_14) { if (pr.x1D) { if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->x4C)) { di->x14 = pr.nsol_14; if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000)) r23 = 0; } else { CError_Error(CErrorStr121); } } } else if (pr.obj_10) { switch (pr.obj_10->otype) { case OT_OBJECT: if (pr.x1D) { if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->x4C)) { di->x10 = OBJECT(pr.obj_10); if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000)) r23 = 0; } else { CError_Error(CErrorStr121); } } break; case OT_ENUMCONST: case OT_MEMBERVAR: CError_Error(CErrorStr121); break; default: CError_FATAL(4217); } } else if (pr.name_4) { if (copts.cplusplus) CError_Error(CErrorStr121); } else if (pr.x21) { CPrep_TokenStreamSetState(&state); CPrep_UnLex(); tk = lex(); r23 = 0; } else { CError_FATAL(4234); } } } default: switchDefault: if (!typetoken && !signedness && !typesize) { di->x4A = 1; if (r23) { if (!di->storageclass && !di->qual && !di->exportflags) CError_Error(CErrorStr121); else CError_Warning(CErrorStr349); } } if (typetoken >= 0) di->thetype = getthetype(typetoken, typesize, signedness); if (r24) di->x48 = 1; if (tk == TK_UU_ATTRIBUTE_UU) CParser_ParseAttribute(NULL, di); return; case ';': if (!typetoken && !signedness && !typesize && copts.warn_emptydecl) CError_Warning(CErrorStr216); if (typetoken >= 0) di->thetype = getthetype(typetoken, typesize, signedness); return; } tk = lex(); bailOut: r24 = 0; goto restart; } void CParser_RegisterNonGlobalClass(TypeClass *tclass) { struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup)); p->next = cparser_parentcleanup; p->tclass = tclass; cparser_parentcleanup = p; } void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) { struct SFuncList *p = lalloc(sizeof(struct SFuncList)); p->next = cparser_sfunclist; p->func = func; p->obj = NULL; p->expr = expr; cparser_sfunclist = p; } void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) { struct SFuncList *p = lalloc(sizeof(struct SFuncList)); p->next = cparser_sfunclist; p->func = func; p->obj = obj; p->expr = NULL; cparser_sfunclist = p; } static void CParser_FreeLocalHeap(void) { struct SFuncList *s; struct ParentCleanup *p; while ((s = cparser_sfunclist)) { cparser_sfunclist = s->next; if (s->expr) CFunc_GenerateSingleExprFunc(s->func, s->expr); else CFunc_GenerateDummyCtorFunc(s->func, s->obj); } if (cparser_parentcleanup) { if (!CInline_CanFreeLHeap()) return; for (p = cparser_parentcleanup; p; p = p->next) { while (!p->tclass->nspace->parent->is_global) p->tclass->nspace->parent = p->tclass->nspace->parent->parent; } cparser_parentcleanup = NULL; } freelheap(); } static void CParser_GlobalCleanup(Boolean flag) { Boolean working; do { CParser_FreeLocalHeap(); working = 0; if (flag) { if (cparser_classactions) { CClass_ClassAction(cparser_classactions->tclass); cparser_classactions = cparser_classactions->next; working = 1; } else if (CTempl_Instantiate()) { working = 1; } } while (CInline_GenerateDeferredFuncs()) { CParser_FreeLocalHeap(); working = 1; } } while (working); } Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) { return IS_TYPE_CLASS(di->thetype) && ((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_1 || (flag && copts.cpp_extensions))) && IsTempName(TYPE_CLASS(di->thetype)->classname); } void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) { ObjMemberVar *ivar; Object *obj; Object *ivar_obj; if (!CParser_IsAnonymousUnion(di, 0)) { if (copts.warn_emptydecl) { switch (di->thetype->type) { case TYPEENUM: case TYPESTRUCT: case TYPECLASS: if (!di->storageclass && !di->qual) return; } CError_Warning(CErrorStr216); } return; } if (!flag && di->storageclass != TK_STATIC) CError_Error(CErrorStr177); if (flag && di->storageclass != TK_STATIC) { obj = CParser_NewLocalDataObject(di, 1); obj->name = CParser_GetUniqueName(); CFunc_SetupLocalVarInfo(obj); obj->u.var.info->noregister = 1; } else { obj = CParser_NewGlobalDataObject(di); obj->name = CParser_GetUniqueName(); obj->nspace = cscope_root; obj->sclass = TK_STATIC; CInit_DeclareData(obj, NULL, NULL, obj->type->size); } for (ivar = TYPE_CLASS(di->thetype)->ivars; ivar; ivar = ivar->next) { ivar_obj = galloc(sizeof(Object)); *ivar_obj = *obj; ivar_obj->name = ivar->name; ivar_obj->type = ivar->type; ivar_obj->qual = ivar->qual; ivar_obj->datatype = DALIAS; ivar_obj->u.alias.object = obj; ivar_obj->u.alias.offset = ivar->offset; ivar_obj->u.alias.member = NULL; CScope_AddObject(cscope_current, ivar_obj->name, OBJ_BASE(ivar_obj)); } } void CParser_NewCallBackAction(Object *obj, TypeClass *tclass) { CallbackAction *act = galloc(sizeof(CallbackAction)); act->next = callbackactions; act->obj = obj; act->tclass = tclass; callbackactions = act; obj->flags = obj->flags | OBJECT_FLAGS_8; } void CParser_NewClassAction(TypeClass *tclass) { struct ClassAction *act = galloc(sizeof(struct ClassAction)); act->next = cparser_classactions; act->tclass = tclass; cparser_classactions = act; } void CParser_CallBackAction(Object *obj) { CallbackAction *act; for (act = callbackactions; act; act = act->next) { if (act->obj == obj) { CParser_NewClassAction(act->tclass); return; } } CError_FATAL(4551); } static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) { while (list) { if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type)) if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1) return OBJECT(list->object); list = list->next; } return NULL; } Object *CParser_ParseObject(void) { DeclInfo di; CScopeParseResult pr; NameSpaceObjectList *list; Object *obj; memclrw(&di, sizeof(DeclInfo)); CParser_GetDeclSpecs(&di, 1); scandeclarator(&di); if (di.name && (list = CScope_FindObjectList(&pr, di.name))) { if (list->object->otype == OT_OBJECT) { if (IS_TYPE_FUNC(di.thetype)) return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype)); if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual) return OBJECT(list->object); obj = OBJECT(list->object); CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, di.thetype, di.qual); } } return NULL; } void CParser_ParseGlobalDeclaration(void) { DeclInfo di; if (tk) { CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); symdecloffset = cparser_fileoffset.tokenline; symdecltoken = *CPrep_CurStreamElement(); memclrw(&di, sizeof(DeclInfo)); CParser_GetDeclSpecs(&di, 1); if (di.storageclass == TK_REGISTER || di.storageclass == TK_AUTO) { CError_Error(CErrorStr177); di.storageclass = 0; } if (tk != ';') scandeclaratorlist(&di); else CParser_CheckAnonymousUnion(&di, 0); tk = lex(); } else { CError_Error(CErrorStr102); } } static void CParser_ParseLinkageSpecification(DeclInfo *di) { UInt32 r29; UInt8 r28; if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) { r29 = 0; r28 = 1; } else if (!strcmp(tkstring, "C++")) { r29 = 0; r28 = 0; } else if (!strcmp(tkstring, "Pascal")) { r29 = 8; r28 = 1; } else { CError_Error(CErrorStr121); r29 = 0; r28 = 1; } if ((tk = lex()) == '{') { while (1) { if ((tk = lex()) == 0) { CError_Error(CErrorStr130); return; } if (tk == '}') break; CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); symdecloffset = cparser_fileoffset.tokenline; symdecltoken = *CPrep_CurStreamElement(); memclrw(di, sizeof(DeclInfo)); di->x4E = r28; di->qual = r29; CParser_ParseDeclaration(di); } } else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) { tk = lex(); CParser_ParseLinkageSpecification(di); } else { memclrw(di, sizeof(DeclInfo)); di->x4E = r28; di->qual = r29; CParser_GetDeclSpecs(di, 1); if (di->storageclass != TK_TYPEDEF) { if (di->storageclass && copts.pedantic) CError_Warning(CErrorStr177); if (!di->storageclass) di->storageclass = TK_EXTERN; } if (copts.cpp_extensions) di->x48 = 0; if (tk != ';') scandeclaratorlist(di); } } static void CParser_ParseNameSpace(DeclInfo *di) { NameSpace *nspace; ObjNameSpace *objns; HashNameNode *name; Boolean flag; CScopeSave save; NameSpaceObjectList *list; NameSpaceList *nsl; if ((tk = lex()) == TK_IDENTIFIER) { name = tkidentifier; flag = 0; if ((tk = lex()) == '=') { CScope_ParseNameSpaceAlias(name); return; } } else { if (tk != '{') { CError_Error(CErrorStr107); return; } name = CParser_GetUnnamedNameSpaceName(); flag = 1; } nspace = cscope_current; if (!(list = CScope_FindName(nspace, name))) { objns = galloc(sizeof(ObjNameSpace)); memclrw(objns, sizeof(ObjNameSpace)); objns->otype = OT_NAMESPACE; objns->access = ACCESSPUBLIC; if (flag) { nspace = CScope_NewListNameSpace(name, 1); nspace->is_unnamed = 1; nsl = galloc(sizeof(NameSpaceList)); nsl->next = cscope_current->usings; nsl->nspace = nspace; cscope_current->usings = nsl; } else { nspace = CScope_NewHashNameSpace(name); if (cscope_current->is_unnamed) nspace->is_unnamed = 1; } nspace->parent = cscope_current; objns->nspace = nspace; CScope_AddObject(cscope_current, name, OBJ_BASE(objns)); } else { if (list->object->otype != OT_NAMESPACE) CError_Error(CErrorStr320); else nspace = OBJ_NAMESPACE(list->object)->nspace; } if (tk != '{') { CError_Error(CErrorStr135); return; } CScope_SetNameSpaceScope(nspace, &save); while (1) { if ((tk = lex()) == 0) { CError_Error(CErrorStr130); break; } if (tk == '}') break; CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); symdecloffset = cparser_fileoffset.tokenline; symdecltoken = *CPrep_CurStreamElement(); memclrw(di, sizeof(DeclInfo)); CParser_ParseDeclaration(di); } CScope_RestoreScope(&save); } static void CParser_ParseDeclaration(DeclInfo *di) { switch (tk) { case TK_AT_INTERFACE: CObjC_ParseInterface(); break; case TK_AT_IMPLEMENTATION: CObjC_ParseImplementation(); break; case TK_AT_PROTOCOL: CObjC_ParseProtocol(); break; case TK_AT_CLASS: CObjC_ParseClassDeclaration(); break; case TK_NAMESPACE: CParser_ParseNameSpace(di); break; case TK_EXPORT: CError_Error(CErrorStr190); if ((tk = lex()) != TK_TEMPLATE) { CError_Error(CErrorStr121); return; } case TK_TEMPLATE: CTempl_Parse(NULL, 0); break; case TK_USING: if ((tk = lex()) == TK_NAMESPACE) { tk = lex(); CScope_ParseUsingDirective(cscope_current); } else { CScope_ParseUsingDeclaration(cscope_current, 0, 0); } break; case TK_EXTERN: if (copts.cplusplus) { di->storageclass = TK_EXTERN; if ((tk = lex()) == TK_STRING) { CParser_ParseLinkageSpecification(di); break; } } default: CParser_GetDeclSpecs(di, 1); if ((di->storageclass == TK_REGISTER || di->storageclass == TK_AUTO) != 0) { CError_Error(CErrorStr177); di->storageclass = 0; } if (tk != ';') scandeclaratorlist(di); else CParser_CheckAnonymousUnion(di, 0); CParser_GlobalCleanup(0); } } void cparser(void) { DeclInfo di; if (copts.crippled && copts.optimizationlevel > 1) { CError_Warning(CErrorStr385); copts.optimizationlevel = 1; CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } if ((tk = lex())) { do { CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); symdecloffset = cparser_fileoffset.tokenline; symdecltoken = *CPrep_CurStreamElement(); memclrw(&di, sizeof(DeclInfo)); CParser_ParseDeclaration(&di); } while (tk && (tk = lex())); } else { if (!copts.cplusplus && copts.ANSIstrict) CError_Error(CErrorStr102); } CInit_DefineTentativeData(); copts.defer_codegen = 0; CParser_GlobalCleanup(1); if (cparamblkptr->precompile != 1) { CInline_Finish(); CParser_GlobalCleanup(1); } CClass_GenThunks(); if (cparamblkptr->precompile != 1) CObjC_GenerateModule(); CSOM_Cleanup(); CInit_DefineTentativeData(); }