summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/C/CParser.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CParser.c')
-rw-r--r--compiler_and_linker/FrontEnd/C/CParser.c3477
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();
+}