diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/C/CParser.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CParser.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/C/CParser.c | 3477 |
1 files changed, 3477 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CParser.c b/compiler_and_linker/FrontEnd/C/CParser.c new file mode 100644 index 0000000..b089e47 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CParser.c @@ -0,0 +1,3477 @@ +#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 "../Optimizer/IrOptimizer.h" +#include "../Optimizer/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_MANGLE_NAME; + + 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_EXPORT; + if (copts.cfm_internal) + object->flags = object->flags | OBJECT_INTERNAL; + } else if (copts.cfm_internal) { + object->flags = object->flags | OBJECT_INTERNAL; + } else { + if (copts.cfm_import) + object->flags = object->flags | OBJECT_IMPORT; + if (copts.cfm_export) + object->flags = object->flags | OBJECT_EXPORT; + if (copts.cfm_lib_export) + object->flags = object->flags | OBJECT_IMPORT | OBJECT_EXPORT; + } +} + +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->is_extern_c) + object->qual |= Q_MANGLE_NAME; + } + + 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->is_extern_c) + object->qual |= Q_MANGLE_NAME; + } + + 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; + NameResult 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_HANDLEOBJECT) { + 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_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + 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_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + 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_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + 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_IS_TEMPL)) + return CTemplTool_IsSameTemplateType(b, a); + if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_IS_TEMPL)) + 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_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + 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_IS_TEMPL)) { + 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_WEAK)) + 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_WEAK)) + 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)->vtbl_index; + return 1; + } + + return 0; +} + +Boolean is_pascal_object(Object *obj) { + return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_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_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_WEAK; + } 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; + NameResult pr; + + di->file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition(&di->file2, &di->sourceoffset); + + 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_CLASS, 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.type) { + if (IS_TYPE_TEMPLATE(pr.type)) { + switch (TYPE_TEMPLATE(pr.type)->dtype) { + case TEMPLDEP_ARGUMENT: + switch (TYPE_TEMPLATE(pr.type)->u.pid.type) { + case TPT_TYPE: + break; + case TPT_NONTYPE: + CError_Error(CErrorStr348); + pr.type = TYPE(&stsignedint); + break; + case TPT_TEMPLATE: + CError_Error(CErrorStr230); + pr.type = 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.type) && (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) { + if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 0)) { + if (di->x56) { + if (di->qual) + CError_Error(CErrorStr121); + di->thetype = pr.type; + di->x57 = 1; + tk = lex(); + return; + } else { + CError_Error(CErrorStr230); + pr.type = TYPE(&stsignedint); + } + } + } + + TypedefDeclInfo(di, pr.type, pr.qual); + 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->in_friend_decl)) { + di->x14 = pr.nsol_14; + if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) + 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->in_friend_decl)) { + di->x10 = OBJECT(pr.obj_10); + if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) + 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_UNION || (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_LAZY; +} + +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; + NameResult 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 qual; + UInt8 r28; + + if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) { + qual = 0; + r28 = 1; + } else if (!strcmp(tkstring, "C++")) { + qual = 0; + r28 = 0; + } else if (!strcmp(tkstring, "Pascal")) { + qual = Q_PASCAL; + r28 = 1; + } else { + CError_Error(CErrorStr121); + qual = 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->is_extern_c = r28; + di->qual = qual; + 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->is_extern_c = r28; + di->qual = qual; + 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(); +} |