MWCC/compiler_and_linker/unsorted/CParser.c

3481 lines
110 KiB
C

#include "compiler/CParser.h"
#include "compiler/CABI.h"
#include "compiler/CClass.h"
#include "compiler/CDecl.h"
#include "compiler/CError.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInit.h"
#include "compiler/CInline.h"
#include "compiler/CInt64.h"
#include "compiler/CIRTransform.h"
#include "compiler/CMachine.h"
#include "compiler/CMangler.h"
#include "compiler/CObjC.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CScope.h"
#include "compiler/CSOM.h"
#include "compiler/CTemplateNew.h"
#include "compiler/CTemplateTools.h"
#include "compiler/CodeGen.h"
#include "compiler/CompilerTools.h"
#include "compiler/IrOptimizer.h"
#include "compiler/IroPointerAnalysis.h"
#include "compiler/ObjGenMachO.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/templates.h"
#include "cos.h"
FileOffsetInfo cparser_fileoffset;
TStreamElement symdecltoken;
ParserTryBlock *trychain;
Boolean inassembler;
Boolean dont_set_references;
TypeStruct ptmstruct;
TypeStruct catchinfostruct;
Boolean in_assembler;
Boolean illegalimplicitconversion;
Boolean in_func_arglist;
NameSpaceName *newp_fobj;
NameSpaceName *newa_fobj;
NameSpaceName *delp_fobj;
NameSpaceName *dela_fobj;
Object *newh_func;
Object *delh_func;
Object *copy_func;
Object *clear_func;
Object *Rgtid_func;
Object *Rdync_func;
Object *rt_ptmf_cast;
Object *rt_ptmf_cmpr;
Object *rt_ptmf_test;
Object *rt_ptmf_call;
Object *rt_ptmf_scall;
Object *rt_ptmf_call4;
Object *rt_ptmf_scall4;
Object *rt_ptmf_null;
Object *rt_som_new;
Object *rt_som_newcheck;
Object *rt_som_check;
Object *rt_som_glue1;
Object *rt_som_glue2;
Object *rt_som_glue3;
Object *carr_func;
Object *cnar_func;
Object *darr_func;
Object *dnar_func;
Object *dnar3_func;
Object *Xgreg_func;
Object *Xthrw_func;
Object *Xicth_func;
Object *Xecth_func;
Object *Xunex_func;
COpts copts;
GList name_mangle_list;
HashNameNode *no_name_node;
HashNameNode *temp_argument_name;
HashNameNode *this_name_node;
HashNameNode *self_name_node;
HashNameNode *vptr_name_node;
CallbackAction *callbackactions;
Boolean fatalerrors;
Boolean anyerrors;
jmp_buf errorreturn;
static HashNameNode *uniquenamespacename;
static SInt32 uniqueid;
struct ClassAction {
struct ClassAction *next;
TypeClass *tclass;
};
static struct ClassAction *cparser_classactions;
struct ParentCleanup {
struct ParentCleanup *next;
TypeClass *tclass;
};
static struct ParentCleanup *cparser_parentcleanup;
struct SFuncList {
struct SFuncList *next;
Object *func;
Object *obj;
ENode *expr;
};
static struct SFuncList *cparser_sfunclist;
char string[256];
SInt32 compilererrornum;
SInt32 compilererrfile;
SInt32 compilererrline;
Type sttemplexpr = {TYPETEMPLDEPEXPR, 0};
Type stillegal = {TYPEILLEGAL, 1};
Type stvoid = {TYPEVOID, 0};
TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0};
TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0};
// forward declarations
static void CParser_ParseDeclaration(DeclInfo *di);
Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) {
Object *obj;
FuncArg *args;
FuncArg *arg;
TypeFunc *tfunc;
va_list va;
args = NULL;
if (argcount) {
va_start(va, argcount);
while (--argcount >= 0) {
if (args) {
arg->next = CParser_NewFuncArg();
arg = arg->next;
} else {
arg = CParser_NewFuncArg();
args = arg;
}
arg->type = va_arg(va, Type *);
}
va_end(va);
}
obj = CParser_NewFunctionObject(NULL);
tfunc = galloc(sizeof(TypeFunc));
memclrw(tfunc, sizeof(TypeFunc));
tfunc->type = TYPEFUNC;
tfunc->functype = rettype;
tfunc->args = args;
CDecl_SetFuncFlags(tfunc, 0);
obj->name = name;
obj->type = TYPE(tfunc);
if (flag == 1)
obj->qual = Q_80000;
return obj;
}
Boolean CParser_IsPublicRuntimeObject(Object *obj) {
if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next)
return 1;
if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next)
return 1;
if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next)
return 1;
if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next)
return 1;
return CodeGen_IsPublicRuntimeObject(obj);
}
Object *CParser_FindPublicRuntimeObject(HashNameNode *name) {
NameSpaceObjectList *list = CScope_FindName(cscope_root, name);
if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG))
return OBJECT(list->object);
else
return NULL;
}
Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) {
if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW))))
return 0;
if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY))))
return 0;
if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE))))
return 0;
if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY))))
return 0;
newh_func->name = GetHashNameNodeExport("__new_hdl");
delh_func->name = GetHashNameNodeExport("__del_hdl");
copy_func->name = GetHashNameNodeExport("__copy");
clear_func->name = GetHashNameNodeExport("__clear");
Rgtid_func->name = GetHashNameNodeExport("__get_typeid");
Rdync_func->name = GetHashNameNodeExport("__dynamic_cast");
rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast");
rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr");
rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test");
rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call");
rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall");
rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4");
rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4");
rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null");
rt_som_new->name = GetHashNameNodeExport("__som_new");
rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new");
rt_som_check->name = GetHashNameNodeExport("__som_check_ev");
rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4");
rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5");
rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_");
carr_func->name = GetHashNameNodeExport("__construct_array");
cnar_func->name = GetHashNameNodeExport("__construct_new_array");
darr_func->name = GetHashNameNodeExport("__destroy_arr");
dnar_func->name = GetHashNameNodeExport("__destroy_new_array");
dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3");
Xgreg_func->name = GetHashNameNodeExport("__register_global_object");
Xthrw_func->name = GetHashNameNodeExport("__throw");
Xicth_func->name = GetHashNameNodeExport("__init__catch");
Xecth_func->name = GetHashNameNodeExport("__end__catch");
Xunex_func->name = GetHashNameNodeExport("__unexpected");
CMangler_Setup();
no_name_node = GetHashNameNodeExport("@no_name@");
temp_argument_name = GetHashNameNodeExport("@temp_ptr@");
this_name_node = GetHashNameNodeExport("this");
self_name_node = GetHashNameNodeExport("self");
vptr_name_node = GetHashNameNodeExport("__vptr$");
CSOM_Setup(is_precompiler);
return CodeGen_ReInitRuntimeObjects(is_precompiler);
}
static void CParser_SetupRuntimeObjects(void) {
ExceptSpecList *exspecs;
Type *sizet;
Object *func;
exspecs = galloc(sizeof(ExceptSpecList));
memclrw(exspecs, sizeof(ExceptSpecList));
sizet = CABI_GetSizeTType();
func = CParser_NewRTFunc(
TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1,
1, sizet);
CScope_AddGlobalObject(func);
func = CParser_NewRTFunc(
TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1,
1, sizet);
CScope_AddGlobalObject(func);
func = CParser_NewRTFunc(
TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1,
1, &void_ptr);
CError_ASSERT(379, IS_TYPE_FUNC(func->type));
TYPE_FUNC(func->type)->exspecs = exspecs;
CScope_AddGlobalObject(func);
func = CParser_NewRTFunc(
TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1,
1, &void_ptr);
CError_ASSERT(387, IS_TYPE_FUNC(func->type));
TYPE_FUNC(func->type)->exspecs = exspecs;
CScope_AddGlobalObject(func);
newh_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 0,
1, sizet);
delh_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
Rgtid_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 0,
2, &void_ptr, &stsignedlong);
Rdync_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 0,
5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort);
copy_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 2,
3, &void_ptr, &void_ptr, sizet);
clear_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 2,
2, &void_ptr, sizet);
rt_ptmf_cast = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 2,
3, &stsignedlong, &void_ptr, &void_ptr);
rt_ptmf_cmpr = CParser_NewRTFunc(
TYPE(&stsignedlong), NULL, 2,
2, &void_ptr, &void_ptr);
rt_ptmf_test = CParser_NewRTFunc(
TYPE(&stsignedlong), NULL, 2,
1, &void_ptr);
rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_ptmf_null = CParser_NewGlobalDataObject(NULL);
rt_ptmf_null->type = &stvoid;
rt_som_new = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 2,
3, &void_ptr, &stsignedlong, &stsignedlong);
rt_som_newcheck = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
rt_som_check = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0);
carr_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet);
cnar_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 0,
5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet);
darr_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
4, &void_ptr, &void_ptr, sizet, sizet);
dnar_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
2, &void_ptr, &void_ptr);
dnar3_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort);
Xgreg_func = CParser_NewRTFunc(
TYPE(&void_ptr), NULL, 0,
3, &void_ptr, &void_ptr, &void_ptr);
Xthrw_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
3, &void_ptr, &void_ptr, &void_ptr);
Xicth_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
Xecth_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
Xunex_func = CParser_NewRTFunc(
TYPE(&stvoid), NULL, 0,
1, &void_ptr);
CodeGen_SetupRuntimeObjects();
CError_ASSERT(534, CParser_ReInitRuntimeObjects(0));
}
void CParser_Setup(void) {
CScope_Setup();
name_mangle_list.data = NULL;
if (InitGList(&name_mangle_list, 256))
CError_NoMem();
void_ptr.size = 4;
CError_Init();
CInit_Init();
CClass_Init();
CIRTrans_Setup();
CObjC_Setup();
CInline_Init();
in_assembler = 0;
in_func_arglist = 0;
CParser_SetUniqueID(1);
dont_set_references = 0;
copts.side_effects = 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(125);
//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(204);
return 0;
}
tk = '(';
break;
case '[':
if ((tk = lex()) != ']') {
CError_Error(204);
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(204);
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;
ptr++;
}
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(char *a, 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->mainFileSpec, 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->mainFileSpec, 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.export)
object->flags |= OBJECT_FLAGS_40;
if (copts.internal)
object->flags |= OBJECT_FLAGS_10;
} else if (copts.internal) {
object->flags |= OBJECT_FLAGS_10;
} else {
if (copts.import)
object->flags |= OBJECT_FLAGS_20;
if (copts.export)
object->flags |= OBJECT_FLAGS_40;
if (copts.lib_export)
object->flags |= OBJECT_FLAGS_20 | OBJECT_FLAGS_40;
}
}
void CParser_UpdateObject(Object *object, DeclInfo *declinfo) {
if (declinfo && declinfo->section)
object->section = declinfo->section;
CParser_SetCFMFlags(object, declinfo);
CodeGen_UpdateObject(object);
}
Object *CParser_NewObject(DeclInfo *declinfo) {
Object *object = galloc(sizeof(Object));
memclrw(object, sizeof(Object));
CParser_SetCFMFlags(object, declinfo);
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->section = SECT_DEFAULT;
return object;
}
Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) {
Object *object = lalloc(sizeof(Object));
memclrw(object, sizeof(Object));
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->datatype = DLOCAL;
if (declinfo) {
object->type = declinfo->thetype;
object->name = declinfo->name;
object->qual = declinfo->qual;
object->sclass = declinfo->storageclass;
}
if (add_to_locals) {
ObjectList *list = lalloc(sizeof(ObjectList));
list->object = object;
list->next = locals;
locals = list;
}
return object;
}
Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) {
Object *object = galloc(sizeof(Object));
memclrw(object, sizeof(Object));
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->section = SECT_DEFAULT;
object->datatype = DDATA;
object->nspace = cscope_current;
if (declinfo) {
object->type = declinfo->thetype;
object->name = declinfo->name;
object->qual = declinfo->qual;
object->sclass = declinfo->storageclass;
if (copts.cplusplus && !declinfo->x4E)
object->qual |= Q_80000;
}
CParser_UpdateObject(object, declinfo);
return object;
}
Object *CParser_NewCompilerDefDataObject(void) {
Object *object = galloc(sizeof(Object));
memclrw(object, sizeof(Object));
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->section = SECT_DEFAULT;
object->datatype = DDATA;
object->nspace = cscope_root;
return object;
}
Object *CParser_NewFunctionObject(DeclInfo *declinfo) {
Object *object = galloc(sizeof(Object));
memclrw(object, sizeof(Object));
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->section = SECT_DEFAULT;
object->datatype = DFUNC;
object->nspace = cscope_current;
if (declinfo) {
object->type = declinfo->thetype;
object->name = declinfo->name;
object->qual = declinfo->qual;
object->sclass = declinfo->storageclass;
if (copts.cplusplus && !declinfo->x4E)
object->qual |= Q_80000;
}
CParser_UpdateObject(object, declinfo);
return object;
}
Object *CParser_NewCompilerDefFunctionObject(void) {
Object *object = galloc(sizeof(Object));
memclrw(object, sizeof(Object));
object->otype = OT_OBJECT;
object->access = ACCESSPUBLIC;
object->section = SECT_DEFAULT;
object->datatype = DFUNC;
object->nspace = cscope_root;
return object;
}
Object *CParser_NewAliasObject(Object *object, SInt32 offset) {
Object *alias = galloc(sizeof(Object));
*alias = *object;
alias->datatype = DALIAS;
alias->u.alias.object = object;
alias->u.alias.member = NULL;
alias->u.alias.offset = offset;
CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias));
return alias;
}
FuncArg *CParser_NewFuncArg(void) {
FuncArg *arg = galloc(sizeof(FuncArg));
memclrw(arg, sizeof(FuncArg));
return arg;
}
Type *atomtype(void) {
switch (tksize) {
default:
CError_FATAL(1145);
case ATOM_VOID: return &stvoid;
case ATOM_CHAR: return TYPE(&stchar);
case ATOM_WCHAR: return TYPE(&stwchar);
case ATOM_UCHAR: return TYPE(&stunsignedchar);
case ATOM_SHORT: return TYPE(&stsignedshort);
case ATOM_USHORT: return TYPE(&stunsignedshort);
case ATOM_INT: return TYPE(&stsignedint);
case ATOM_UINT: return TYPE(&stunsignedint);
case ATOM_LONG: return TYPE(&stsignedlong);
case ATOM_ULONG: return TYPE(&stunsignedlong);
case ATOM_LONGLONG: return TYPE(&stsignedlonglong);
case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong);
case ATOM_FLOAT: return TYPE(&stfloat);
case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble);
case ATOM_DOUBLE: return TYPE(&stdouble);
case ATOM_LONGDOUBLE: return TYPE(&stlongdouble);
}
}
Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) {
NameSpaceObjectList *list;
NameSpaceObjectList *scan;
NameSpaceObjectList mylist;
CScopeParseResult pr;
Boolean first_time;
Boolean retry_flag;
Object *obj;
Type *sizet;
list = NULL;
*outflag = 0;
if (IS_TYPE_CLASS(type) && !flag2) {
HashNameNode *name;
name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name;
if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) {
if (pr.obj_10) {
mylist.next = NULL;
mylist.object = pr.obj_10;
list = &mylist;
} else {
CError_ASSERT(1202, pr.nsol_14);
list = pr.nsol_14;
}
} else if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) {
CError_ASSERT(1210, !args && !flag1);
return delh_func;
}
}
first_time = 1;
retry_flag = flag1;
while (1) {
if (!args) {
for (scan = list; scan; scan = scan->next) {
obj = OBJECT(scan->object);
if (
obj->otype == OT_OBJECT &&
IS_TYPE_FUNC(obj->type) &&
TYPE_FUNC(obj->type)->args &&
!TYPE_FUNC(obj->type)->args->next &&
is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr))
)
return obj;
}
CError_ASSERT(1231, first_time);
sizet = CABI_GetSizeTType();
for (scan = list; scan; scan = scan->next) {
obj = OBJECT(scan->object);
if (
obj->otype == OT_OBJECT &&
IS_TYPE_FUNC(obj->type) &&
TYPE_FUNC(obj->type)->args &&
TYPE_FUNC(obj->type)->args->next &&
!TYPE_FUNC(obj->type)->args->next->next &&
is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) &&
TYPE_FUNC(obj->type)->args->next->type == sizet
) {
*outflag = 1;
return obj;
}
}
} else {
for (scan = list; scan; scan = scan->next) {
obj = OBJECT(scan->object);
if (
obj->otype == OT_OBJECT &&
IS_TYPE_FUNC(obj->type) &&
TYPE_FUNC(obj->type)->args &&
TYPE_FUNC(obj->type)->args->next &&
is_arglistsame(TYPE_FUNC(obj->type)->args->next, args)
) {
*outflag = 1;
return obj;
}
}
if (!first_time)
return NULL;
}
if (list)
CError_Warning(375, type, 0);
list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first;
first_time = 0;
}
}
static Boolean oldstylecompatible(FuncArg *arg) {
if (copts.ignore_oldstyle)
return 1;
while (arg) {
if (arg == &elipsis)
return 0;
switch (arg->type->type) {
case TYPEINT:
if (TYPE_INTEGRAL(arg->type)->integral < IT_INT)
return 0;
break;
case TYPEFLOAT:
if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE)
return 0;
break;
}
arg = arg->next;
}
return 1;
}
static Boolean is_arglistequal(FuncArg *a, FuncArg *b) {
if (a == &oldstyle) {
if (b == &oldstyle)
return 1;
else
return oldstylecompatible(b);
} else {
if (b == &oldstyle)
return oldstylecompatible(a);
}
while (1) {
if (a == &elipsis || b == &elipsis)
return 1;
if (!a)
return !b;
if (!b)
return 0;
if (copts.mpwc_relax && !copts.cplusplus) {
if (!is_typeequal(a->type, b->type))
return 0;
} else {
if (!is_typesame(a->type, b->type))
return 0;
}
if (a->type->type == TYPEPOINTER && a->qual != b->qual)
return 0;
a = a->next;
b = b->next;
}
}
short is_memberpointerequal(Type *a, Type *b) {
FuncArg *arg_a;
FuncArg *arg_b;
if (a->type != b->type)
return 0;
if (!IS_TYPE_FUNC(a))
return is_typeequal(a, b);
if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
return 0;
if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
return 0;
CError_ASSERT(1345, arg_a = TYPE_FUNC(a)->args);
CError_ASSERT(1346, arg_b = TYPE_FUNC(b)->args);
if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80)
CError_ASSERT(1351, arg_a = arg_a->next);
if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80)
CError_ASSERT(1355, arg_b = arg_b->next);
if (arg_a->qual != arg_b->qual)
return 0;
return is_arglistsame(arg_a->next, arg_b->next);
}
short is_typeequal(Type *a, Type *b) {
restart:
if (a->type != b->type)
return 0;
switch (a->type) {
case TYPEVOID:
return 1;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPECLASS:
return a == b;
case TYPESTRUCT:
return a == b;
case TYPEPOINTER:
if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid)
return 1;
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
if (copts.mpwc_relax && !copts.cplusplus)
return 1;
goto restart;
case TYPEMEMBERPOINTER:
if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2)
return 0;
return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
case TYPEARRAY:
if (a->size && b->size && a->size != b->size)
return 0;
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
goto restart;
case TYPEFUNC:
if (copts.cplusplus || !copts.cpp_extensions) {
if (copts.mpwc_relax && !copts.cplusplus) {
if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
return 0;
} else {
if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
return 0;
}
if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
return 0;
}
return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
case TYPETEMPLATE:
return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
default:
CError_FATAL(1441);
return 0;
}
}
short iscpp_typeequal(Type *a, Type *b) {
restart:
if (a->type != b->type)
return 0;
switch (a->type) {
case TYPEVOID:
return 1;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPECLASS:
return a == b;
case TYPESTRUCT:
return a == b;
case TYPEPOINTER:
if (TYPE_POINTER(b)->target == &stvoid) {
if (TYPE_POINTER(a)->target == &stvoid)
return 1;
else
return -1;
}
if (TYPE_POINTER(a)->target == &stvoid) {
illegalimplicitconversion = 1;
return 0;
}
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
goto restart;
case TYPEMEMBERPOINTER:
if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2)
return 0;
return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
case TYPEARRAY:
if (a->size && b->size && a->size != b->size)
return 0;
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
goto restart;
case TYPEFUNC:
if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
return 0;
if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
return 0;
return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
case TYPETEMPLATE:
return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
default:
CError_FATAL(1500);
return 0;
}
}
short CParser_CompareArgLists(FuncArg *a, FuncArg *b) {
Boolean r30;
r30 = 0;
if (a == &oldstyle) {
if (b == &oldstyle)
return 1;
else
return 2;
}
if (b == &oldstyle)
return 2;
while (1) {
if (a == &elipsis) {
if (b != &elipsis)
return 0;
break;
}
if (b == &elipsis)
return 0;
if (a == NULL) {
if (b)
return 0;
break;
}
if (b == NULL)
return 0;
if (a->type->type == TYPEPOINTER) {
if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) {
if (IS_TYPE_REFERENCE(b->type)) {
if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target))
return 0;
if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
return 0;
} else {
if (!copts.old_argmatch)
return 0;
if (!is_typesame(TYPE_POINTER(a->type)->target, b->type))
return 0;
if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
return 0;
r30 = 1;
}
} else {
if (b->type->type == TYPEPOINTER) {
if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) {
if (!copts.old_argmatch)
return 0;
if (!is_typesame(a->type, TYPE_POINTER(b->type)->target))
return 0;
if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
return 0;
r30 = 1;
} else {
if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target))
return 0;
if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)))
return 0;
}
} else {
return 0;
}
}
} else {
if (b->type->type == TYPEPOINTER) {
if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) {
if (!copts.old_argmatch)
return 0;
if (!is_typesame(a->type, TYPE_POINTER(b->type)->target))
return 0;
r30 = 1;
} else {
return 0;
}
} else {
if (!is_typesame(a->type, b->type))
return 0;
}
}
a = a->next;
b = b->next;
}
if (r30)
return 2;
return 1;
}
Boolean is_arglistsame(FuncArg *a, FuncArg *b) {
if (a == &oldstyle) {
if (b == &oldstyle)
return 1;
else
return oldstylecompatible(b);
} else {
if (b == &oldstyle)
return oldstylecompatible(a);
}
while (1) {
if (!a || !b || a == &elipsis || b == &elipsis)
return a == b;
if (a->type->type == TYPEPOINTER) {
if (b->type->type != TYPEPOINTER ||
(a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) ||
!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) ||
IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type)))
return 0;
} else {
if (!is_typesame(a->type, b->type))
return 0;
}
a = a->next;
b = b->next;
}
}
short is_typesame(Type *a, Type *b) {
restart:
if (a->type != b->type) {
if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_FLAGS_100))
return CTemplTool_IsSameTemplateType(b, a);
if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_FLAGS_100))
return CTemplTool_IsSameTemplateType(a, b);
return 0;
}
switch (a->type) {
case TYPEVOID:
return 1;
case TYPEINT:
case TYPEFLOAT:
case TYPEENUM:
case TYPECLASS:
return a == b;
case TYPETEMPLATE:
return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b));
case TYPESTRUCT:
return a == b;
case TYPEPOINTER:
if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)))
return 0;
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
goto restart;
case TYPEMEMBERPOINTER:
if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2))
return 0;
if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)))
return 0;
return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1);
case TYPEARRAY:
if (a->size != b->size)
return 0;
a = TYPE_POINTER(a)->target;
b = TYPE_POINTER(b)->target;
goto restart;
case TYPEFUNC:
if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype))
return 0;
if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual)
return 0;
if ((TYPE_FUNC(a)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)) != (TYPE_FUNC(b)->flags & (FUNC_FLAGS_F0000000 | FUNC_FLAGS_PASCAL)))
return 0;
return is_arglistsame(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args);
default:
CError_FATAL(1709);
return 0;
}
}
Type *CParser_GetBoolType(void) {
if (copts.cplusplus && copts.booltruefalse)
return TYPE(&stbool);
else
return TYPE(&stsignedint);
}
Type *CParser_GetWCharType(void) {
if (copts.cplusplus && copts.wchar_type)
return TYPE(&stwchar);
else
return TYPE(&stsignedint);
}
short CParser_GetOperator(ENodeType t) {
switch (t) {
default:
CError_FATAL(1748);
case EMONMIN: return '-';
case EBINNOT: return '~';
case ELOGNOT: return '!';
case EADD: return '+';
case ESUB: return '-';
case EMUL: return '*';
case EDIV: return '/';
case EMODULO: return '%';
case EAND: return '&';
case EXOR: return '^';
case EOR: return '|';
case ESHL: return TK_SHL;
case ESHR: return TK_SHR;
case ELESS: return '<';
case EGREATER: return '>';
case ELESSEQU: return TK_LESS_EQUAL;
case EGREATEREQU: return TK_GREATER_EQUAL;
case EEQU: return TK_LOGICAL_EQ;
case ENOTEQU: return TK_LOGICAL_NE;
}
}
Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) {
if ((a & Q_CONST) && !(b & Q_CONST)) {
return ((a & Q_VOLATILE) || !(b & Q_VOLATILE));
} else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) {
return ((a & Q_CONST) || !(b & Q_CONST));
}
return 0;
}
Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) {
if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE)))
return 1;
if ((a & Q_CONST) && !(b & Q_CONST)) {
return ((a & Q_VOLATILE) || !(b & Q_VOLATILE));
} else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) {
return ((a & Q_CONST) || !(b & Q_CONST));
}
return 0;
}
Boolean is_unsigned(Type *type) {
if (IS_TYPE_ENUM(type))
type = TYPE_ENUM(type)->enumtype;
if (
(type == TYPE(&stunsignedchar)) ||
(type == TYPE(&stunsignedshort)) ||
(type == TYPE(&stunsignedint)) ||
(type == TYPE(&stunsignedlong)) ||
(type == TYPE(&stunsignedlonglong)) ||
(type == TYPE(&stbool)) ||
(copts.unsignedchars && (type == TYPE(&stchar))) ||
(type->type == TYPEPOINTER))
return 1;
return 0;
}
StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) {
StructMember *member;
for (member = tstruct->members; member; member = member->next) {
if (member->name == name)
return member;
}
return NULL;
}
void appendmember(TypeStruct *tstruct, StructMember *member) {
StructMember *last;
if (!tstruct->members) {
tstruct->members = member;
return;
}
for (last = tstruct->members; last->next; last = last->next) {}
last->next = member;
}
static void CParser_InsertTryBlock(ParserTryBlock *block) {
block->cscope_current = cscope_current;
block->cscope_currentclass = cscope_currentclass;
block->cscope_currentfunc = cscope_currentfunc;
block->ctempl_curinstance = ctempl_curinstance;
block->cerror_locktoken = cerror_locktoken;
block->cscope_is_member_func = cscope_is_member_func;
block->next = trychain;
trychain = block;
}
static void CParser_RemoveTryBlock(ParserTryBlock *block) {
cscope_current = block->cscope_current;
cscope_currentclass = block->cscope_currentclass;
cscope_currentfunc = block->cscope_currentfunc;
ctempl_curinstance = block->ctempl_curinstance;
cerror_locktoken = block->cerror_locktoken;
cscope_is_member_func = block->cscope_is_member_func;
trychain = block->next;
}
static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) {
Boolean result;
DeclInfo declinfo;
struct ParserTryBlock tryblock;
switch (tk) {
case TK_IDENTIFIER:
case TK_COLON_COLON:
break;
case TK_VOID:
case TK_CHAR:
case TK_SHORT:
case TK_INT:
case TK_LONG:
case TK_FLOAT:
case TK_DOUBLE:
case TK_SIGNED:
case TK_UNSIGNED:
case TK_UNK_113:
case TK_UNK_114:
case TK_UNK_115:
case TK_UNK_116:
case TK_UNK_117:
case TK_UNK_118:
case TK_UNK_119:
case TK_UNK_11A:
case TK_BOOL:
case TK_WCHAR_T:
if (lookahead() != '(')
return 1;
break;
default:
return 1;
}
result = 0;
CParser_InsertTryBlock(&tryblock);
if (setjmp(tryblock.jmpbuf) == 0) {
memclrw(&declinfo, sizeof(DeclInfo));
CParser_GetDeclSpecs(&declinfo, 0);
if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) {
if (flag1) {
declinfo.x46 = flag3;
scandeclarator(&declinfo);
if (!(flag2 && declinfo.name)) {
if (!token) {
if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>')
result = 1;
} else {
result = (tk == token);
}
}
} else {
result = 1;
}
}
}
CParser_RemoveTryBlock(&tryblock);
return result;
}
Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) {
SInt32 state;
if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector")))
return 0;
} else {
if (!copts.cplusplus)
return 1;
}
CPrep_TokenStreamGetState(&state);
if (TryIsDeclaration(flag1, flag2, flag3, token)) {
CPrep_TokenStreamSetCurState(&state);
return 1;
} else {
CPrep_TokenStreamSetCurState(&state);
return 0;
}
}
Boolean islookaheaddeclaration(void) {
SInt32 state;
CPrep_TokenStreamGetState(&state);
tk = lex();
if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) {
if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) {
CPrep_TokenStreamSetCurState(&state);
return 0;
}
} else {
if (!copts.cplusplus) {
CPrep_TokenStreamSetCurState(&state);
return 1;
}
}
if (TryIsDeclaration(1, 1, 0, ')')) {
CPrep_TokenStreamSetCurState(&state);
return 1;
} else {
CPrep_TokenStreamSetCurState(&state);
return 0;
}
}
Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) {
SInt32 state;
DeclInfo di;
struct ParserTryBlock tryblock;
memclrw(&di, sizeof(DeclInfo));
CPrep_TokenStreamGetState(&state);
CParser_InsertTryBlock(&tryblock);
if (setjmp(tryblock.jmpbuf) == 0) {
if (copts.cplusplus)
di.x55 = 1;
if (flag) {
di.x56 = 1;
*flag = 0;
}
CParser_GetDeclSpecs(&di, 0);
if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_FLAGS_100)) {
CParser_RemoveTryBlock(&tryblock);
*qual = di.qual;
*flag = 1;
return di.thetype;
}
if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT &&
TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) {
CParser_RemoveTryBlock(&tryblock);
*qual = di.qual;
*flag = 1;
return di.thetype;
}
scandeclarator(&di);
if (!di.name) {
CParser_RemoveTryBlock(&tryblock);
*qual = di.qual;
return di.thetype;
}
}
CPrep_TokenStreamSetCurState(&state);
CParser_RemoveTryBlock(&tryblock);
return 0;
}
Boolean CParser_TryFuncDecl(void) {
Boolean result;
SInt32 state;
DeclInfo di;
struct ParserTryBlock tryblock;
result = 0;
CPrep_TokenStreamGetState(&state);
CParser_InsertTryBlock(&tryblock);
if (setjmp(tryblock.jmpbuf) == 0) {
memclrw(&di, sizeof(DeclInfo));
di.thetype = &stvoid;
scandeclarator(&di);
if (IS_TYPE_FUNC(di.thetype))
result = 1;
}
CParser_RemoveTryBlock(&tryblock);
CPrep_TokenStreamSetCurState(&state);
return result;
}
Boolean CParser_TryParamList(Boolean flag) {
Boolean result;
SInt32 state;
struct ParserTryBlock tryblock;
result = 0;
CPrep_TokenStreamGetState(&state);
switch ((tk = lex())) {
case ')':
case TK_ELLIPSIS:
result = 1;
break;
default:
CParser_InsertTryBlock(&tryblock);
if (setjmp(tryblock.jmpbuf) == 0) {
if (CFunc_ParseFakeArgList(flag) || tk == ')')
result = 1;
}
CParser_RemoveTryBlock(&tryblock);
break;
}
CPrep_TokenStreamSetCurState(&state);
return result;
}
Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) {
switch (type->type) {
case TYPEARRAY:
TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual);
return type;
case TYPEPOINTER:
if (TYPE_POINTER(type)->qual & Q_CONST) {
TypePointer *newtype = galloc(sizeof(TypePointer));
*newtype = *TYPE_POINTER(type);
newtype->qual = 0;
return TYPE(newtype);
}
return type;
case TYPEMEMBERPOINTER:
if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) {
TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer));
*newtype = *TYPE_MEMBER_POINTER(type);
newtype->qual = 0;
return TYPE(newtype);
}
return type;
default:
*qual = 0;
return type;
}
}
UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) {
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
switch (type->type) {
case TYPEPOINTER:
qual = TYPE_POINTER(type)->qual;
break;
case TYPEMEMBERPOINTER:
qual = TYPE_MEMBER_POINTER(type)->qual;
break;
}
return qual;
}
UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) {
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
switch (type->type) {
case TYPEPOINTER:
qual = TYPE_POINTER(type)->qual;
break;
case TYPEMEMBERPOINTER:
qual = TYPE_MEMBER_POINTER(type)->qual;
break;
}
return qual & (Q_CONST | Q_VOLATILE);
}
Boolean CParser_IsConst(Type *type, UInt32 qual) {
while (IS_TYPE_ARRAY(type))
type = TYPE_POINTER(type)->target;
switch (type->type) {
case TYPEPOINTER:
qual = TYPE_POINTER(type)->qual;
break;
case TYPEMEMBERPOINTER:
qual = TYPE_MEMBER_POINTER(type)->qual;
break;
}
return qual & Q_CONST;
}
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) ? 1 : 0;
}
Boolean is_const_object(Object *obj) {
return CParser_IsConst(obj->type, obj->qual);
}
Boolean is_volatile_object(Object *obj) {
return CParser_IsVolatile(obj->type, obj->qual);
}
Boolean CParserIsConstExpr(ENode *expr) {
return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS);
}
Boolean CParserIsVolatileExpr(ENode *expr) {
return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS);
}
Boolean CParser_HasInternalLinkage(const Object *obj) {
NameSpace *nspace;
for (nspace = obj->nspace; nspace; nspace = nspace->parent) {
if (nspace->is_unnamed)
return 1;
}
if (obj->datatype == DLOCAL)
return 1;
if (obj->qual & (Q_20000 | Q_OVERLOAD))
return 0;
if (obj->sclass == TK_STATIC)
return 1;
// this feels *wrong* but it's the only way to match this function that I can see
if (obj->qual & Q_INLINE)
((Object *) obj)->qual |= Q_20000;
return 0;
}
Boolean CParser_HasInternalLinkage2(const Object *obj) {
if (obj->datatype == DLOCAL)
return 1;
if (obj->qual & (Q_20000 | Q_OVERLOAD))
return 0;
if (obj->sclass == TK_STATIC)
return 1;
// this feels *wrong* but it's the only way to match this function that I can see
if (obj->qual & Q_INLINE)
((Object *) obj)->qual |= Q_20000;
return 0;
}
Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) {
if (obj->datatype == DVFUNC) {
*tclass = TYPE_METHOD(obj->type)->theclass;
*index = TYPE_METHOD(obj->type)->x1E;
return 1;
}
return 0;
}
Boolean is_pascal_object(Object *obj) {
return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_PASCAL);
}
Boolean is_cfm_type(Type *type) {
return 0;
}
Boolean CParser_IsVTableObject(Object *obj) {
return
obj->datatype == DDATA &&
obj->nspace &&
obj->nspace->theclass &&
obj->nspace->theclass->vtable &&
obj->nspace->theclass->vtable->object == obj;
}
static Type *getthetype(short token, short size, short signedness) {
switch (token) {
case 0:
case TK_INT:
if (signedness == 1) {
switch (size) {
case 1: return TYPE(&stunsignedshort);
case 2: return TYPE(&stunsignedlong);
case 3: return TYPE(&stunsignedlonglong);
default: return TYPE(&stunsignedint);
}
} else {
switch (size) {
case 1: return TYPE(&stsignedshort);
case 2: return TYPE(&stsignedlong);
case 3: return TYPE(&stsignedlonglong);
default: return TYPE(&stsignedint);
}
}
case TK_BOOL:
return TYPE(&stbool);
case TK_WCHAR_T:
return TYPE(&stwchar);
case TK_CHAR:
switch (signedness) {
case 1: return TYPE(&stunsignedchar);
default: return TYPE(&stchar);
case -1: return TYPE(&stsignedchar);
}
case TK_DOUBLE:
switch (size) {
case 1: return TYPE(&stshortdouble);
case 2: return TYPE(&stlongdouble);
default: return TYPE(&stdouble);
}
case TK_FLOAT:
return TYPE(&stfloat);
case TK_VOID:
return TYPE(&stvoid);
default:
CError_Error(121);
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(114);
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(121);
return;
}
tk = lookahead();
if (tk == ',') {
lex();
tk = lookahead();
}
}
lex();
if (tk != ')')
CError_Error(121);
}
void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) {
CInt64 val64;
SInt32 val;
do {
if ((tk = lex()) != '(') {
CError_Error(121);
return;
}
if ((tk = lex()) != '(') {
CError_Error(121);
return;
}
if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) {
CError_Error(121);
return;
}
if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) {
if ((tk = lex()) != '(') {
CError_Error(121);
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(124);
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(149);
}
} 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(359);
}
if (tk != ')') {
CError_Error(121);
return;
}
} else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) {
if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype))
TYPE_FUNC(declinfo->thetype)->flags |= FUNC_FLAGS_NOTHROW;
else
CError_Error(359);
} else if (!strcmp("function_summary", tkidentifier->name)) {
CParser_ParseAttributeFunctionSummary(declinfo);
} else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) {
CError_Error(359);
} 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(359);
if ((tk = lex()) != '(') {
CError_Warning(114);
return;
}
tk = lex();
if ((tk = lex()) != ',') {
CError_Warning(116);
return;
}
tk = lex();
if ((tk = lex()) != ',') {
CError_Warning(116);
return;
}
tk = lex();
if ((tk = lex()) != ')') {
CError_Warning(115);
return;
}
} else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) {
CError_Warning(359);
if ((tk = lex()) != '(') {
CError_Warning(114);
return;
}
tk = lex();
if ((tk = lex()) != ')') {
CError_Warning(115);
return;
}
} else {
CError_Error(359);
}
if ((tk = lex()) != ')') {
CError_Error(121);
return;
}
if ((tk = lex()) != ')') {
CError_Error(121);
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(121);
if (tk != ')')
CError_ErrorSkip(115);
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(144);
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(107);
else
declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
} else if (!strcmp("internal", tkidentifier->name)) {
declinfo->exportflags |= EXPORT_FLAGS_INTERNAL;
} else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) {
declinfo->exportflags |= EXPORT_FLAGS_IMPORT;
} else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) {
declinfo->exportflags |= EXPORT_FLAGS_EXPORT;
} else if (!strcmp("lib_export", tkidentifier->name)) {
declinfo->exportflags |= EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT;
} else if (!strcmp("weak", tkidentifier->name)) {
declinfo->qual |= Q_OVERLOAD;
} else {
CodeGen_ParseDeclSpec(tkidentifier, declinfo);
}
}
static int CParser_GetVectorDeclSpec(Type **type) {
tk = lex();
switch (tk) {
case TK_CHAR:
tk = lex();
switch (tk) {
case TK_BOOL:
*type = TYPE(&stvectorboolchar);
tk = lex();
return 1;
case TK_UNSIGNED:
*type = TYPE(&stvectorunsignedchar);
tk = lex();
return 1;
case TK_SIGNED:
*type = TYPE(&stvectorsignedchar);
tk = lex();
return 1;
case TK_IDENTIFIER:
if (tkidentifier == GetHashNameNode("bool")) {
*type = TYPE(&stvectorboolchar);
tk = lex();
return 1;
}
default:
CError_Error(121);
}
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(121);
}
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(121);
}
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(121);
}
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(121);
}
break;
case TK_IDENTIFIER:
if (tkidentifier == GetHashNameNode("bool")) {
*type = TYPE(&stvectorboolshort);
tk = lex();
if (tk == TK_INT)
tk = lex();
return 1;
}
default:
CError_Error(121);
}
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(121);
}
break;
case TK_IDENTIFIER:
if (tkidentifier == GetHashNameNode("bool")) {
*type = TYPE(&stvectorboollong);
tk = lex();
if (tk == TK_INT)
tk = lex();
return 1;
}
default:
CError_Error(121);
}
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(121);
}
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(121);
}
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(121);
}
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(230);
return 0;
}
if (nspace->theclass == TYPE_CLASS(tmclass))
break;
nspace = nspace->parent;
}
}
return 1;
}
static Boolean CParser_IsAltiVecPrefix(void) {
HashNameNode *save = tkidentifier;
switch (lookahead()) {
case TK_CHAR:
case TK_SHORT:
case TK_INT:
case TK_LONG:
case TK_FLOAT:
case TK_SIGNED:
case TK_UNSIGNED:
case TK_BOOL:
return 1;
case TK_IDENTIFIER:
if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel"))
return 1;
}
tkidentifier = save;
return 0;
}
void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) {
short typesize;
short signedness;
short typetoken;
Boolean r24;
Boolean r23;
SInt32 state;
CScopeParseResult pr;
di->file = CPrep_BrowserCurrentFile();
CPrep_BrowserFilePosition(
(CPrepFileInfo **) &di->file2,
&di->x60);
r24 = 1;
r23 = copts.cplusplus;
typetoken = 0;
signedness = 0;
typesize = 0;
restart:
switch (tk) {
case TK_AUTO:
case TK_REGISTER:
case TK_STATIC:
case TK_EXTERN:
case TK_TYPEDEF:
case TK_MUTABLE:
if (di->storageclass)
CError_Error(121);
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(114);
CParser_ParseDeclSpec(di, 0);
if ((tk = lex()) != ')')
CError_Error(115);
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(121);
typesize = 1;
break;
case TK_LONG:
if (copts.longlong) {
if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)
CError_Error(121);
if (typesize) {
if (typesize != 2 || typetoken == TK_DOUBLE)
CError_Error(121);
typesize = 3;
} else {
typesize = 2;
}
} else {
if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE))
CError_Error(121);
typesize = 2;
}
break;
case TK_SIGNED:
if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR))
CError_Error(121);
signedness = -1;
break;
case TK_UNSIGNED:
if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR))
CError_Error(121);
signedness = 1;
break;
case TK_VOID:
if (typetoken || typesize || signedness)
CError_Error(121);
typetoken = TK_VOID;
break;
case TK_FLOAT:
if (typetoken || typesize || signedness)
CError_Error(121);
typetoken = TK_FLOAT;
break;
case TK_BOOL:
if (typetoken || typesize)
CError_Error(121);
typetoken = TK_BOOL;
break;
case TK_CHAR:
if (typetoken || typesize)
CError_Error(121);
typetoken = TK_CHAR;
break;
case TK_WCHAR_T:
if (typetoken || typesize || signedness)
CError_Error(121);
typetoken = TK_WCHAR_T;
break;
case TK_INT:
if (typetoken)
CError_Error(121);
typetoken = TK_INT;
break;
case TK_DOUBLE:
if (typetoken || signedness)
CError_Error(121);
typetoken = TK_DOUBLE;
break;
case TK_STRUCT:
if (typetoken || signedness || typesize)
CError_Error(121);
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(121);
tk = lex();
CDecl_ParseClass(di, CLASS_MODE_2, 1, 0);
if (tk == TK_UU_ATTRIBUTE_UU)
CParser_ParseAttribute(di->thetype, NULL);
if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) {
typetoken = -1;
goto restart;
}
return;
case TK_UNION:
if (typetoken || signedness || typesize)
CError_Error(121);
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(121);
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(121);
di->x53 = 1;
tk = lex();
if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) {
CError_Error(121);
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(121);
handle_vector:
if (CParser_GetVectorDeclSpec(&di->thetype)) {
if (tk == TK_CONST) {
if (di->qual == 0) {
di->qual |= Q_CONST;
tk = lex();
} else {
CError_Error(121);
}
}
if (tk == TK_VOLATILE) {
if (di->qual == 0) {
di->qual |= Q_VOLATILE;
tk = lex();
} else {
CError_Error(121);
}
}
return;
}
break;
case TK_UU_TYPEOF_UU:
if (typetoken || signedness || typesize)
CError_Error(121);
CParser_ParseTypeOf(di);
typetoken = -1;
goto bailOut;
case TK_IDENTIFIER:
if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) {
if (CParser_IsAltiVecPrefix())
goto handle_vector;
}
if (!typetoken && !signedness && !typesize) {
if (copts.objective_c && !strcmp(tkidentifier->name, "id")) {
di->thetype = CObjC_ParseID();
typetoken = -1;
goto bailOut;
}
some_shared_label:
CPrep_TokenStreamGetState(&state);
if (CScope_ParseDeclName(&pr)) {
if (pr.x8) {
if (IS_TYPE_TEMPLATE(pr.x8)) {
switch (TYPE_TEMPLATE(pr.x8)->dtype) {
case TEMPLDEP_ARGUMENT:
switch (TYPE_TEMPLATE(pr.x8)->u.pid.type) {
case TPT_TYPE:
break;
case TPT_NONTYPE:
CError_Error(348);
pr.x8 = TYPE(&stsignedint);
break;
case TPT_TEMPLATE:
CError_Error(230);
pr.x8 = TYPE(&stsignedint);
break;
default:
CError_FATAL(4109);
}
break;
case TEMPLDEP_QUALNAME:
if (!di->x53 && !pr.x20 && di->x55)
CError_Error(355);
break;
case TEMPLDEP_TEMPLATE:
case TEMPLDEP_ARRAY:
case TEMPLDEP_QUALTEMPL:
case TEMPLDEP_BITFIELD:
break;
default:
CError_FATAL(4136);
}
}
if (IS_TYPE_CLASS(pr.x8) && (TYPE_CLASS(pr.x8)->flags & CLASS_FLAGS_100)) {
if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.x8), 0)) {
if (di->x56) {
if (di->qual)
CError_Error(121);
di->thetype = pr.x8;
di->x57 = 1;
tk = lex();
return;
} else {
CError_Error(230);
pr.x8 = TYPE(&stsignedint);
}
}
}
TypedefDeclInfo(di, pr.x8, pr.xC);
di->x49 = pr.x20;
typetoken = -1;
tk = lex();
if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo)
di->thetype = CObjC_ParseTypeProtocol(TYPE_CLASS(di->thetype));
goto bailOut;
} else if (pr.nsol_14) {
if (pr.x1D) {
if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->x4C)) {
di->x14 = pr.nsol_14;
if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000))
r23 = 0;
} else {
CError_Error(121);
}
}
} else if (pr.obj_10) {
switch (pr.obj_10->otype) {
case OT_OBJECT:
if (pr.x1D) {
if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->x4C)) {
di->x10 = OBJECT(pr.obj_10);
if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_FLAGS_1000) | FUNC_FLAGS_2000))
r23 = 0;
} else {
CError_Error(121);
}
}
break;
case OT_ENUMCONST:
case OT_MEMBERVAR:
CError_Error(121);
break;
default:
CError_FATAL(4217);
}
} else if (pr.name_4) {
if (copts.cplusplus)
CError_Error(121);
} 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(121);
else
CError_Warning(349);
}
}
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(216);
if (typetoken >= 0)
di->thetype = getthetype(typetoken, typesize, signedness);
return;
}
tk = lex();
bailOut:
r24 = 0;
goto restart;
}
void CParser_RegisterNonGlobalClass(TypeClass *tclass) {
struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup));
p->next = cparser_parentcleanup;
p->tclass = tclass;
cparser_parentcleanup = p;
}
void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) {
struct SFuncList *p = lalloc(sizeof(struct SFuncList));
p->next = cparser_sfunclist;
p->func = func;
p->obj = NULL;
p->expr = expr;
cparser_sfunclist = p;
}
void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) {
struct SFuncList *p = lalloc(sizeof(struct SFuncList));
p->next = cparser_sfunclist;
p->func = func;
p->obj = obj;
p->expr = NULL;
cparser_sfunclist = p;
}
static void CParser_FreeLocalHeap(void) {
struct SFuncList *s;
struct ParentCleanup *p;
while ((s = cparser_sfunclist)) {
cparser_sfunclist = s->next;
if (s->expr)
CFunc_GenerateSingleExprFunc(s->func, s->expr);
else
CFunc_GenerateDummyCtorFunc(s->func, s->obj);
}
if (cparser_parentcleanup) {
if (!CInline_CanFreeLHeap())
return;
for (p = cparser_parentcleanup; p; p = p->next) {
while (!p->tclass->nspace->parent->is_global)
p->tclass->nspace->parent = p->tclass->nspace->parent->parent;
}
cparser_parentcleanup = NULL;
}
freelheap();
}
static void CParser_GlobalCleanup(Boolean flag) {
Boolean working;
do {
CParser_FreeLocalHeap();
working = 0;
if (flag) {
if (cparser_classactions) {
CClass_ClassAction(cparser_classactions->tclass);
cparser_classactions = cparser_classactions->next;
working = 1;
} else if (CTempl_Instantiate()) {
working = 1;
}
}
while (CInline_GenerateDeferredFuncs()) {
CParser_FreeLocalHeap();
working = 1;
}
} while (working);
}
Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) {
return IS_TYPE_CLASS(di->thetype) &&
((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_1 || (flag && copts.cpp_extensions))) &&
IsTempName(TYPE_CLASS(di->thetype)->classname);
}
void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) {
ObjMemberVar *ivar;
Object *obj;
Object *ivar_obj;
if (!CParser_IsAnonymousUnion(di, 0)) {
if (copts.warn_emptydecl) {
switch (di->thetype->type) {
case TYPEENUM:
case TYPESTRUCT:
case TYPECLASS:
if (!di->storageclass && !di->qual)
return;
}
CError_Warning(216);
}
return;
}
if (!flag && di->storageclass != TK_STATIC)
CError_Error(177);
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 |= OBJECT_FLAGS_8;
}
void CParser_NewClassAction(TypeClass *tclass) {
struct ClassAction *act = galloc(sizeof(struct ClassAction));
act->next = cparser_classactions;
act->tclass = tclass;
cparser_classactions = act;
}
void CParser_CallBackAction(Object *obj) {
CallbackAction *act;
for (act = callbackactions; act; act = act->next) {
if (act->obj == obj) {
CParser_NewClassAction(act->tclass);
return;
}
}
CError_FATAL(4551);
}
static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) {
while (list) {
if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type))
if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1)
return OBJECT(list->object);
list = list->next;
}
return NULL;
}
Object *CParser_ParseObject(void) {
DeclInfo di;
CScopeParseResult pr;
NameSpaceObjectList *list;
Object *obj;
memclrw(&di, sizeof(DeclInfo));
CParser_GetDeclSpecs(&di, 1);
scandeclarator(&di);
if (di.name && (list = CScope_FindObjectList(&pr, di.name))) {
if (list->object->otype == OT_OBJECT) {
if (IS_TYPE_FUNC(di.thetype))
return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype));
if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual)
return OBJECT(list->object);
obj = OBJECT(list->object);
CError_Error(249, 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(177);
di.storageclass = 0;
}
if (tk != ';')
scandeclaratorlist(&di);
else
CParser_CheckAnonymousUnion(&di, 0);
tk = lex();
} else {
CError_Error(102);
}
}
static void CParser_ParseLinkageSpecification(DeclInfo *di) {
UInt32 r29;
UInt8 r28;
if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) {
r29 = 0;
r28 = 1;
} else if (!strcmp(tkstring, "C++")) {
r29 = 0;
r28 = 0;
} else if (!strcmp(tkstring, "Pascal")) {
r29 = 8;
r28 = 1;
} else {
CError_Error(121);
r29 = 0;
r28 = 1;
}
if ((tk = lex()) == '{') {
while (1) {
if ((tk = lex()) == 0) {
CError_Error(130);
return;
}
if (tk == '}')
break;
CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL);
symdecloffset = cparser_fileoffset.tokenline;
symdecltoken = *CPrep_CurStreamElement();
memclrw(di, sizeof(DeclInfo));
di->x4E = r28;
di->qual = r29;
CParser_ParseDeclaration(di);
}
} else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) {
tk = lex();
CParser_ParseLinkageSpecification(di);
} else {
memclrw(di, sizeof(DeclInfo));
di->x4E = r28;
di->qual = r29;
CParser_GetDeclSpecs(di, 1);
if (di->storageclass != TK_TYPEDEF) {
if (di->storageclass && copts.pedantic)
CError_Warning(177);
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(107);
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(320);
else
nspace = OBJ_NAMESPACE(list->object)->nspace;
}
if (tk != '{') {
CError_Error(135);
return;
}
CScope_SetNameSpaceScope(nspace, &save);
while (1) {
if ((tk = lex()) == 0) {
CError_Error(130);
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(190);
if ((tk = lex()) != TK_TEMPLATE) {
CError_Error(121);
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(177);
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(385);
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.ANSI_strict)
CError_Error(102);
}
CInit_DefineTentativeData();
copts.defer_codegen = 0;
CParser_GlobalCleanup(1);
if (cparamblkptr->isPrecompiling != 1) {
CInline_Finish();
CParser_GlobalCleanup(1);
}
CClass_GenThunks();
if (cparamblkptr->isPrecompiling != 1)
CObjC_GenerateModule();
CSOM_Cleanup();
CInit_DefineTentativeData();
}