#include "compiler/CPrec.h" #include "compiler/CError.h" #include "compiler/CFunc.h" #include "compiler/CInit.h" #include "compiler/CInline.h" #include "compiler/CMachine.h" #include "compiler/CObjC.h" #include "compiler/CParser.h" #include "compiler/CPrep.h" #include "compiler/CScope.h" #include "compiler/CSOM.h" #include "compiler/CTemplateNew.h" #include "compiler/CompilerTools.h" #include "compiler/Exceptions.h" #include "compiler/enode.h" #include "compiler/objc.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/som.h" #include "compiler/templates.h" #include "compiler/types.h" #include "cos.h" #include "compiler/CCompiler.h" #include "compiler/InlineAsm.h" #define RESOLVE_BUFFER(offset) ((void *) (((char *) cprec_buffer) + ((uintptr_t) (offset)))) #define RESOLVE_RAW_BUFFER(offset) ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset)))) #define RESOLVE_SAFE(offset) (!(offset) ? NULL : ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset))))) #ifdef __MWERKS__ #pragma options align=mac68k #endif typedef struct StaticData { struct StaticData *next; Object *object; void *buffer; OLinkList *links; SInt32 size; } StaticData; typedef struct Header { UInt32 magic; UInt16 version; UInt16 x6; char target; Boolean check_header_flags; Boolean cplusplus; UInt32 xC; UInt32 x10; UInt32 x14; UInt32 x18; UInt32 x1C; UInt32 x20; UInt32 x24; UInt32 x28; UInt32 x2C; UInt32 x30; UInt32 compressedPatchCount; UInt32 compressedPatchSize; UInt32 compressedPatchOffset; UInt32 builtinPatchSize; UInt32 builtinPatchOffset; UInt32 tokenStreamPatchSize; UInt32 tokenStreamPatchOffset; UInt32 root_names; NameSpaceList *usings; TemplClass *ctempl_templates; CSOMStub *csom_stubs; StaticData *cprec_staticdata; UInt32 uniqueID; CallbackAction *callbackactions; Type *cobjc_type_class; Type *cobjc_type_id; Type *cobjc_type_sel; ObjCSelector **cobjc_selhashtable; BClassList *cobjc_classdefs; ObjCProtocol *cobjc_protocols; UInt32 cobjc_selrefcount; UInt32 cobjc_classrefcount; UInt32 cobjc_stringcount; InitExpr *init_expressions; CI_Action *cinline_tactionlist; TemplateFunction *ctempl_templatefuncs; UInt32 x9C; UInt32 xA0; UInt32 xA4; UInt32 xA8; UInt32 xAC; UInt32 xB0; UInt32 xB4; UInt32 xB8; UInt32 xBC; UInt32 xC0; UInt32 xC4; UInt32 xC8; UInt32 xCC; UInt32 xD0; UInt32 xD4; UInt32 xD8; UInt32 xDC; UInt32 xE0; UInt32 xE4; HashNameNode *nametable[0x800]; Macro *macrotable[0x800]; NameSpaceName *root_nametable[0x400]; } Header; typedef struct Patch { struct Patch *next; SInt32 offset; } Patch; typedef struct AddrPatch { struct AddrPatch *next; void *addr; void *value; } AddrPatch; typedef struct BuiltIn { void *target; SInt32 idx; Patch *patches; } BuiltIn; static Boolean cprec_exportargnames; static Boolean cprec_dowrite; static OSErr cprec_ioerror; static void *cprec_rawbuffer; static void *cprec_buffer; static SInt32 cprec_zero_offset; static SInt32 cprec_offset; static int cprec_builtins; static void **cprec_builtin_array; typedef struct TokenPatch { struct TokenPatch *next; TStreamElement *tokens; SInt32 count; } TokenPatch; static TokenPatch *cprec_tokenpatches; static StaticData *cprec_staticdata; typedef struct PointerHash { struct PointerHash *next; TypePointer *tptr; TypePointer *prec_tptr; } PointerHash; static PointerHash **cprec_pointerhash; static BuiltIn *cprec_builtin; static Patch *cprec_patch_list; static AddrPatch **cprec_addrhash; static Header *cprec_header; static GList cprec_glist; static short cprec_refnum; char *precomp_target_str; #ifdef __MWERKS__ #pragma options align=reset #endif // Assorted forward declarations static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace); static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj); static Object *CPrec_GetObjectPatch(Object *obj); static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj); static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar); static Type *CPrec_GetTypePatch(Type *type); static ENode *CPrec_GetExpressionPatch(ENode *expr); static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth); static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst); static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg); static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol); static OSErr CPrec_FlushBufferCheck(void); void SetupPrecompiler(Boolean isPrecompiling) { cprec_refnum = 0; cprec_glist.data = NULL; cprec_header = NULL; cprec_staticdata = NULL; cprec_ioerror = noErr; } void CleanupPrecompiler(void) { if (cprec_refnum) { COS_FileClose(cprec_refnum); cprec_refnum = 0; } if (cprec_glist.data) FreeGList(&cprec_glist); } static OLinkList *CPrec_OLinkListCopy(OLinkList *list) { OLinkList *copy; if (!list) return NULL; copy = galloc(sizeof(OLinkList)); *copy = *list; copy->next = CPrec_OLinkListCopy(copy->next); return copy; } void PreComp_StaticData(Object *obj, const void *data, OLinkList *links, SInt32 size) { StaticData *entry; if (obj->sclass != TK_STATIC && !(obj->qual & (Q_20000 | Q_OVERLOAD))) CError_Error(CErrorStr180); entry = galloc(sizeof(StaticData)); entry->object = obj; entry->size = size; entry->next = cprec_staticdata; cprec_staticdata = entry; if (data) { entry->buffer = galloc(obj->type->size); memcpy(entry->buffer, data, obj->type->size); } else { entry->buffer = NULL; } entry->links = CPrec_OLinkListCopy(links); } static void CPrec_InitAddressHashTable(void) { cprec_addrhash = lalloc(0x4000 * sizeof(AddrPatch *)); memclrw(cprec_addrhash, 0x4000 * sizeof(AddrPatch *)); } static void CPrec_InitPointerHashTable(void) { cprec_pointerhash = lalloc(0x400 * sizeof(PointerHash *)); memclrw(cprec_pointerhash, 0x400 * sizeof(PointerHash *)); } static int CPrec_AddressHashVal(void *addr) { UInt32 v = (UInt32) addr; return ( v + ((unsigned char *) &v)[0] + ((unsigned char *) &v)[1] + ((unsigned char *) &v)[2] + ((unsigned char *) &v)[3] ) & 0x3FFF; } static AddrPatch *CPrec_FindAddrPatch(void *addr) { AddrPatch *scan; for (scan = cprec_addrhash[CPrec_AddressHashVal(addr)]; scan; scan = scan->next) { if (scan->addr == addr) return scan; } return NULL; } static AddrPatch *CPrec_NewAddrPatch(void *addr, void *value) { AddrPatch **loc; AddrPatch *patch; loc = cprec_addrhash + CPrec_AddressHashVal(addr); patch = lalloc(sizeof(AddrPatch)); patch->addr = addr; patch->value = value; patch->next = *loc; *loc = patch; return patch; } static void CPrec_SetupBuiltInArray(void) { int count1, count2; Boolean flag; void **array; #define REG_BUILTIN(a) \ if (!flag) { array[count2++] = (a); } else { count1++; } for (count2 = count1 = 0, flag = 1; ;) { REG_BUILTIN(cscope_root); REG_BUILTIN(&stvoid); REG_BUILTIN(&stbool); REG_BUILTIN(&stchar); REG_BUILTIN(&stsignedchar); REG_BUILTIN(&stunsignedchar); REG_BUILTIN(&stwchar); REG_BUILTIN(&stsignedshort); REG_BUILTIN(&stunsignedshort); REG_BUILTIN(&stsignedint); REG_BUILTIN(&stunsignedint); REG_BUILTIN(&stsignedlong); REG_BUILTIN(&stunsignedlong); REG_BUILTIN(&stsignedlonglong); REG_BUILTIN(&stunsignedlonglong); REG_BUILTIN(&stfloat); REG_BUILTIN(&stshortdouble); REG_BUILTIN(&stdouble); REG_BUILTIN(&stlongdouble); REG_BUILTIN(&elipsis); REG_BUILTIN(&oldstyle); REG_BUILTIN(&stillegal); REG_BUILTIN(&sttemplexpr); REG_BUILTIN(&stvoid); REG_BUILTIN(&void_ptr); REG_BUILTIN(&rt_func); REG_BUILTIN(&catchinfostruct); REG_BUILTIN(newh_func); REG_BUILTIN(delh_func); REG_BUILTIN(copy_func); REG_BUILTIN(clear_func); REG_BUILTIN(Rgtid_func); REG_BUILTIN(Rdync_func); REG_BUILTIN(rt_ptmf_cast); REG_BUILTIN(rt_ptmf_cmpr); REG_BUILTIN(rt_ptmf_test); REG_BUILTIN(rt_ptmf_call); REG_BUILTIN(rt_ptmf_scall); REG_BUILTIN(rt_ptmf_null); REG_BUILTIN(rt_som_glue1); REG_BUILTIN(rt_som_glue2); REG_BUILTIN(rt_som_glue3); REG_BUILTIN(rt_som_check); REG_BUILTIN(rt_som_new); REG_BUILTIN(rt_som_newcheck); REG_BUILTIN(rt_ptmf_call4); REG_BUILTIN(rt_ptmf_scall4); REG_BUILTIN(carr_func); REG_BUILTIN(cnar_func); REG_BUILTIN(darr_func); REG_BUILTIN(dnar_func); REG_BUILTIN(dnar3_func); REG_BUILTIN(Xgreg_func); REG_BUILTIN(Xthrw_func); REG_BUILTIN(Xicth_func); REG_BUILTIN(Xecth_func); REG_BUILTIN(Xunex_func); REG_BUILTIN(&stvectorunsignedchar); REG_BUILTIN(&stvectorsignedchar); REG_BUILTIN(&stvectorboolchar); REG_BUILTIN(&stvectorunsignedshort); REG_BUILTIN(&stvectorsignedshort); REG_BUILTIN(&stvectorboolshort); REG_BUILTIN(&stvectorunsignedlong); REG_BUILTIN(&stvectorsignedlong); REG_BUILTIN(&stvectorboollong); REG_BUILTIN(&stvectorfloat); REG_BUILTIN(&stvectorpixel); if (flag) { array = lalloc(sizeof(void *) * count1); cprec_builtin_array = array; cprec_builtins = count1; flag = 0; } else { return; } } } static void CPrec_SetupBuiltIn(void) { int x; CPrec_SetupBuiltInArray(); cprec_builtin = lalloc(sizeof(BuiltIn) * cprec_builtins); memclrw(cprec_builtin, sizeof(BuiltIn) * cprec_builtins); for (x = 0; x < cprec_builtins; x++) { cprec_builtin[x].target = cprec_builtin_array[x]; cprec_builtin[x].idx = ~x; CPrec_NewAddrPatch(cprec_builtin[x].target, (void *) cprec_builtin[x].idx); } } static void CPrec_NewPointerPatch(void *src, void *ptr) { if (cprec_dowrite) { Patch *patch = lalloc(sizeof(Patch)); patch->offset = (SInt32) src; CError_ASSERT(507, (patch->offset & 0x80000001) == 0); if ((SInt32) ptr < 0) { ptr = (void *) ~((SInt32) ptr); CError_ASSERT(513, (SInt32) ptr < cprec_builtins); patch->next = cprec_builtin[(SInt32) ptr].patches; cprec_builtin[(SInt32) ptr].patches = patch; ptr = NULL; } else { patch->next = cprec_patch_list; cprec_patch_list = patch; } src = (void *)((char *) src - cprec_zero_offset); CError_ASSERT(525, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); *((void **) (*cprec_glist.data + (SInt32) src)) = ptr; } } static void CPrec_ExistingPointerPatch(void *src, void *ptr) { if (cprec_dowrite) { AddrPatch *addrPatch; Patch *patch; CError_ASSERT(543, addrPatch = CPrec_FindAddrPatch(ptr)); patch = lalloc(sizeof(Patch)); patch->offset = (SInt32) src; patch->next = cprec_patch_list; cprec_patch_list = patch; CError_ASSERT(548, (patch->offset & 0x80000001) == 0); src = (void *)((char *) src - cprec_zero_offset); CError_ASSERT(552, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); *((void **) (*cprec_glist.data + (SInt32) src)) = addrPatch->value; } } static void CPrec_NamePatch(void *src, HashNameNode *name) { name->id = 1; CPrec_ExistingPointerPatch(src, name); } static void *CPrec_AppendAlign(void) { if (cprec_dowrite) { while (cprec_offset & 3) { AppendGListByte(&cprec_glist, 0); ++cprec_offset; } } return (void *) cprec_offset; } static UInt32 CPrec_AppendByte(UInt8 v) { if (cprec_dowrite) AppendGListByte(&cprec_glist, v); return cprec_offset++; } static UInt32 CPrec_AppendWord16(UInt16 v) { UInt32 offset; if (cprec_dowrite) AppendGListWord(&cprec_glist, v); offset = cprec_offset; cprec_offset += 2; return offset; } static UInt32 CPrec_AppendWord32(UInt32 v) { UInt32 offset; if (cprec_dowrite) AppendGListLong(&cprec_glist, v); offset = cprec_offset; cprec_offset += 4; return offset; } static UInt32 CPrec_AppendPointer(void *v) { UInt32 offset; if (cprec_dowrite) AppendGListLong(&cprec_glist, (SInt32) v); offset = cprec_offset; cprec_offset += 4; return offset; } static UInt32 CPrec_AppendPointerPatch(void *v) { AddrPatch *addrPatch; if (v) { CError_ASSERT(644, addrPatch = CPrec_FindAddrPatch(v)); if (cprec_dowrite) { Patch *patch = lalloc(sizeof(Patch)); patch->offset = cprec_offset; patch->next = cprec_patch_list; cprec_patch_list = patch; CError_ASSERT(651, (patch->offset & 0x80000001) == 0); } return CPrec_AppendPointer(addrPatch->value); } else { return CPrec_AppendPointer(NULL); } } static void CPrec_AppendNamePatch(HashNameNode *name) { if (name) { CPrec_AppendPointerPatch(name); name->id = 1; } } static void CPrec_AppendString(const char *str) { int len = strlen(str) + 1; if (cprec_dowrite) AppendGListData(&cprec_glist, str, len); cprec_offset += len; } static void CPrec_AppendData(const void *data, int len) { if (cprec_dowrite) AppendGListData(&cprec_glist, data, len); cprec_offset += len; } static void CPrec_RawMemPatch(void *source, const void *data, int len) { void *ptr = CPrec_AppendAlign(); CPrec_AppendData(data, len); CPrec_NewPointerPatch(source, ptr); } static void CPrec_DumpNameTable(void) { HashNameNode *name; int i; HashNameNode *p; HashNameNode *next; if (cprec_dowrite) { i = 0; do { name = name_hash_nodes[i]; while (name && name->id == 0) name = name->next; if (name) { p = CPrec_AppendAlign(); cprec_header->nametable[i] = p; while (1) { CPrec_NewAddrPatch(name, p); CPrec_AppendPointer(NULL); CPrec_AppendWord32(0); CPrec_AppendWord16(name->hashval); CPrec_AppendString(name->name); name = name->next; while (name && name->id == 0) name = name->next; if (!name) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(&p->next, next); p = next; } } } while (++i < 0x800); } else { i = 0; do { if ((name = name_hash_nodes[i])) { p = CPrec_AppendAlign(); while (1) { CPrec_NewAddrPatch(name, p); CPrec_AppendPointer(NULL); CPrec_AppendWord32(0); CPrec_AppendWord16(name->hashval); CPrec_AppendString(name->name); name = name->next; if (!name) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(&p->next, next); p = next; } } } while (++i < 0x800); } } static void CPrec_DumpMacroTable(void) { Macro *macro; int i; int j; Macro *p; Macro *next; i = 0; do { for (macro = macrohashtable[i]; macro; macro = macro->next) { if (macro->c) { CPrec_NewAddrPatch(macro->c, (void *) cprec_offset); CPrec_AppendString(macro->c); } } } while (++i < 0x800); i = 0; do { macro = macrohashtable[i]; if (macro) { p = CPrec_AppendAlign(); if (cprec_dowrite) cprec_header->macrotable[i] = p; while (1) { CPrec_AppendPointer(NULL); CPrec_AppendNamePatch(macro->name); CPrec_AppendPointerPatch(macro->c); CPrec_AppendWord16(macro->xC); CPrec_AppendByte(macro->is_special); CPrec_AppendByte(macro->xF); for (j = 1; j < (macro->xC & 0x7FFF); j++) CPrec_AppendNamePatch(macro->names[j - 1]); macro = macro->next; if (!macro) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(&p->next, next); p = next; } } } while (++i < 0x800); } static BClassList *CPrec_GetClassAccessPatch(BClassList *path) { AddrPatch *addrPatch; BClassList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(path))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(path, first); while (1) { CPrec_AppendData(path, sizeof(BClassList)); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(path->type)); if (!path->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; path = path->next; } return first; } static int CPrec_PointerHash(TypePointer *type) { Type *target; int work; FuncArg *arg; work = type->qual; target = type->target; restart: switch (target->type) { case TYPECLASS: if (TYPE_CLASS(target)->classname) work += TYPE_CLASS(target)->classname->hashval; break; case TYPEENUM: if (TYPE_ENUM(target)->enumname) work += TYPE_ENUM(target)->enumname->hashval; target = TYPE_ENUM(target)->enumtype; work += 3; case TYPEINT: case TYPEFLOAT: work += TYPE_INTEGRAL(target)->integral; break; case TYPEPOINTER: work += TYPE_POINTER(target)->qual; target = TYPE_POINTER(target)->target; goto restart; case TYPEARRAY: work += target->size; target = TYPE_POINTER(target)->target; goto restart; case TYPEFUNC: work += TYPE_FUNC(target)->functype->type; work += TYPE_FUNC(target)->functype->size; for (arg = TYPE_FUNC(target)->args; arg; arg = arg->next) { if (arg->type) { work += arg->type->type; work += arg->type->size; } } break; } work += target->type + target->size; return (work + (work >> 24) + (work >> 16) + (work >> 8)) & 0x3FF; } static TypePointer *CPrec_GetTypePointerPatch(TypePointer *tptr) { TypePointer *p; int hash; PointerHash *phash; TypePointer *scan1; TypePointer *scan2; if (tptr->qual & Q_100000) { p = CPrec_AppendAlign(); CPrec_NewAddrPatch(tptr, p); CPrec_AppendData(tptr, sizeof(TypeObjCID)); if (TYPE_OBJC_ID(tptr)->protocols) CPrec_NewPointerPatch(&TYPE_OBJC_ID(p)->protocols, CPrec_GetObjCProtocolListPatch(TYPE_OBJC_ID(tptr)->protocols)); } else { if (!copts.faster_pch_gen && cprec_dowrite && tptr->size > 0) { hash = CPrec_PointerHash(tptr); for (phash = cprec_pointerhash[hash]; phash; phash = phash->next) { scan1 = tptr; scan2 = phash->tptr; check_again: if (scan1->type == scan2->type && scan1->size == scan2->size && scan1->qual == scan2->qual) { scan1 = TYPE_POINTER(TPTR_TARGET(scan1)); scan2 = TYPE_POINTER(TPTR_TARGET(scan2)); if (scan1->type == TYPEPOINTER && scan1->type == TYPEARRAY) goto check_again; if (scan1 == scan2) return phash->prec_tptr; } } p = CPrec_AppendAlign(); CPrec_NewAddrPatch(tptr, p); phash = lalloc(sizeof(PointerHash)); phash->tptr = tptr; phash->prec_tptr = p; phash->next = cprec_pointerhash[hash]; cprec_pointerhash[hash] = phash; } else { p = CPrec_AppendAlign(); CPrec_NewAddrPatch(tptr, p); } CPrec_AppendData(tptr, sizeof(TypePointer)); } CPrec_NewPointerPatch(&p->target, CPrec_GetTypePatch(tptr->target)); return p; } static TypeEnum *CPrec_GetTypeEnumPatch(TypeEnum *type) { TypeEnum *p = CPrec_AppendAlign(); CPrec_NewAddrPatch(type, p); CPrec_AppendData(type, sizeof(TypeEnum)); if (type->nspace) CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(type->nspace)); if (type->enumlist) CPrec_NewPointerPatch(&p->enumlist, CPrec_GetObjEnumConstPatch(type->enumlist)); CPrec_NewPointerPatch(&p->enumtype, CPrec_GetTypePatch(type->enumtype)); if (type->enumname) CPrec_NamePatch(&p->enumname, type->enumname); return p; } static TypeBitfield *CPrec_GetTypeBitfieldPatch(TypeBitfield *type) { TypeBitfield *p = CPrec_AppendAlign(); CPrec_NewAddrPatch(type, p); CPrec_AppendData(type, sizeof(TypeBitfield)); CPrec_NewPointerPatch(&p->bitfieldtype, CPrec_GetTypePatch(type->bitfieldtype)); return p; } static TypeStruct *CPrec_GetTypeStructPatch(TypeStruct *tstruct) { StructMember *member; TypeStruct *p; StructMember *current, *next; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(tstruct, p); CPrec_AppendData(tstruct, sizeof(TypeStruct)); if (tstruct->name) CPrec_NamePatch(&p->name, tstruct->name); if ((member = tstruct->members)) { current = CPrec_AppendAlign(); CPrec_NewPointerPatch(&p->members, current); while (1) { CPrec_AppendData(member, sizeof(StructMember)); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(member->type)); CPrec_NamePatch(¤t->name, member->name); if (!member->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; member = member->next; } } return p; } static ExceptSpecList *CPrec_GetExceptSpecPatch(ExceptSpecList *exspec) { ExceptSpecList *first, *current, *next; first = current = CPrec_AppendAlign(); while (exspec) { CPrec_AppendData(exspec, sizeof(ExceptSpecList)); if (exspec->type) CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(exspec->type)); if (!exspec->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; exspec = exspec->next; } return first; } static FuncArg *CPrec_GetArgListPatch(FuncArg *lst, Boolean includeNames) { FuncArg *first, *current, *next; AddrPatch *addrPatch; if ((addrPatch = CPrec_FindAddrPatch(lst))) return addrPatch->value; first = current = CPrec_AppendAlign(); while (1) { if (!includeNames) lst->name = NULL; CPrec_AppendData(lst, sizeof(FuncArg)); if (includeNames && lst->name) CPrec_NamePatch(¤t->name, lst->name); if (lst->dexpr) CPrec_NewPointerPatch(¤t->dexpr, CPrec_GetExpressionPatch(lst->dexpr)); if (lst->type) CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(lst->type)); else CError_FATAL(1167); if (!lst->next) break; if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; lst = lst->next; CPrec_NewAddrPatch(lst, next); } return first; } static TypeFunc *CPrec_GetTypeFuncPatch(TypeFunc *type) { TypeFunc *p = CPrec_AppendAlign(); CPrec_NewAddrPatch(type, p); CPrec_AppendData(type, (type->flags & FUNC_FLAGS_METHOD) ? sizeof(TypeMethod) : sizeof(TypeFunc)); CPrec_NewPointerPatch(&p->functype, CPrec_GetTypePatch(type->functype)); if (type->args) CPrec_NewPointerPatch(&p->args, CPrec_GetArgListPatch(type->args, (type->flags & FUNC_FLAGS_900000) != 0)); if (type->exspecs) CPrec_NewPointerPatch(&p->exspecs, CPrec_GetExceptSpecPatch(type->exspecs)); if (type->flags & FUNC_FLAGS_METHOD) CPrec_NewPointerPatch(&TYPE_METHOD(p)->theclass, CPrec_GetTypePatch((Type *) TYPE_METHOD(type)->theclass)); return p; } static TypeMemberPointer *CPrec_GetTypeMemberPointerPatch(TypeMemberPointer *type) { TypeMemberPointer *p = CPrec_AppendAlign(); CPrec_NewAddrPatch(type, p); CPrec_AppendData(type, sizeof(TypeMemberPointer)); CPrec_NewPointerPatch(&p->ty1, CPrec_GetTypePatch(type->ty1)); CPrec_NewPointerPatch(&p->ty2, CPrec_GetTypePatch(type->ty2)); return p; } static TypeTemplDep *CPrec_GetTypeTemplDepPatch(TypeTemplDep *type) { TypeTemplDep *p = CPrec_AppendAlign(); CPrec_NewAddrPatch(type, p); CPrec_AppendData(type, sizeof(TypeTemplDep)); switch (type->dtype) { case TEMPLDEP_ARGUMENT: break; case TEMPLDEP_QUALNAME: CPrec_NewPointerPatch(&p->u.qual.type, CPrec_GetTypeTemplDepPatch(type->u.qual.type)); CPrec_NamePatch(&p->u.qual.name, type->u.qual.name); break; case TEMPLDEP_TEMPLATE: CPrec_NewPointerPatch(&p->u.templ.templ, CPrec_GetTypePatch((Type *) type->u.templ.templ)); CPrec_NewPointerPatch(&p->u.templ.args, CPrec_GetTemplateArgPatch(type->u.templ.args)); break; case TEMPLDEP_ARRAY: CPrec_NewPointerPatch(&p->u.array.type, CPrec_GetTypePatch(type->u.array.type)); CPrec_NewPointerPatch(&p->u.array.index, CPrec_GetExpressionPatch(type->u.array.index)); break; case TEMPLDEP_QUALTEMPL: CPrec_NewPointerPatch(&p->u.qualtempl.type, CPrec_GetTypeTemplDepPatch(type->u.qualtempl.type)); CPrec_NewPointerPatch(&p->u.qualtempl.args, CPrec_GetTemplateArgPatch(type->u.qualtempl.args)); break; case TEMPLDEP_BITFIELD: CPrec_NewPointerPatch(&p->u.bitfield.type, CPrec_GetTypePatch(type->u.bitfield.type)); CPrec_NewPointerPatch(&p->u.bitfield.size, CPrec_GetExpressionPatch(type->u.bitfield.size)); break; default: CError_FATAL(1295); } return p; } static ClassList *CPrec_GetClassListPatch(ClassList *cl) { AddrPatch *addrPatch; ClassList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(cl))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(cl, first); do { CPrec_AppendData(cl, sizeof(ClassList)); CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) cl->base)); if (!cl->next) break; if ((addrPatch = CPrec_FindAddrPatch(cl->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; cl = cl->next; } } while (1); return first; } static VClassList *CPrec_GetVClassListPatch(VClassList *vcl) { VClassList *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(vcl, sizeof(VClassList)); CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) vcl->base)); if (!vcl->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; vcl = vcl->next; } while (1); return first; } static ClassFriend *CPrec_GetClassFriendPatch(ClassFriend *cf) { ClassFriend *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(cf, sizeof(ClassFriend)); if (cf->isclass) CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetTypePatch((Type *) cf->u.theclass)); else CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetObjectPatch(cf->u.obj)); if (!cf->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; cf = cf->next; } while (1); return first; } static BClassList *CPrec_GetBClassListPatch(BClassList *bcl) { BClassList *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(bcl, sizeof(BClassList)); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch((Type *) bcl->type)); if (!bcl->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; bcl = bcl->next; } while (1); return first; } static VTable *CPrec_GetVTablePatch(VTable *vtbl) { VTable *p = CPrec_AppendAlign(); CPrec_AppendData(vtbl, sizeof(VTable)); if (vtbl->object) CPrec_NewPointerPatch(&p->object, CPrec_GetObjectPatch(vtbl->object)); if (vtbl->owner) CPrec_NewPointerPatch(&p->owner, CPrec_GetTypePatch((Type *) vtbl->owner)); return p; } static SOMReleaseOrder *CPrec_GetSOMReleaseOrderPatch(SOMReleaseOrder *sro) { SOMReleaseOrder *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(sro, sizeof(SOMReleaseOrder)); CPrec_NamePatch(¤t->name, sro->name); if (!sro->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; sro = sro->next; } while (1); return first; } static SOMInfo *CPrec_GetSOMInfoPatch(SOMInfo *som) { SOMInfo *p = CPrec_AppendAlign(); CPrec_AppendData(som, sizeof(SOMInfo)); if (som->metaclass) CPrec_NewPointerPatch(&p->metaclass, CPrec_GetTypePatch((Type *) som->metaclass)); if (som->classdataobject) CPrec_NewPointerPatch(&p->classdataobject, CPrec_GetObjectPatch(som->classdataobject)); if (som->order) CPrec_NewPointerPatch(&p->order, CPrec_GetSOMReleaseOrderPatch(som->order)); return p; } static ObjCMethodArg *CPrec_GetObjCMethodArgPatch(ObjCMethodArg *arg) { ObjCMethodArg *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(arg, sizeof(ObjCMethod)); if (arg->selector) CPrec_NamePatch(¤t->selector, arg->selector); if (arg->name) CPrec_NamePatch(¤t->name, arg->name); if (arg->type) CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(arg->type)); if (!arg->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; arg = arg->next; } while (1); return first; } static ObjCMethodList *CPrec_GetObjCMethodListPatch(ObjCMethodList *lst) { AddrPatch *addrPatch; ObjCMethodList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(lst))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(lst, first); do { CPrec_AppendData(lst, sizeof(ObjCMethodList)); if (lst->method) CPrec_NewPointerPatch(¤t->method, CPrec_GetObjCMethodPatch(lst->method)); if (!lst->next) break; if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; lst = lst->next; CPrec_NewAddrPatch(lst, next); } } while (1); return first; } static ObjCSelector *CPrec_GetObjCSelectorPatch(ObjCSelector *sel) { AddrPatch *addrPatch; ObjCSelector *current, *first, *next; if ((addrPatch = CPrec_FindAddrPatch(sel))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(sel, first); do { CPrec_AppendData(sel, sizeof(ObjCSelector)); if (sel->selobject) CPrec_NewPointerPatch(¤t->selobject, CPrec_GetObjectPatch(sel->selobject)); CPrec_NamePatch(¤t->name, sel->name); if (sel->methods) CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodListPatch(sel->methods)); if (!sel->next) break; if ((addrPatch = CPrec_FindAddrPatch(sel->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; sel = sel->next; CPrec_NewAddrPatch(sel, next); } } while (1); return first; } static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth) { // does not match - affected by weirdness where the arg goes into r31 instead of r28 AddrPatch *addrPatch; ObjCMethod *current, *first, *next; if ((addrPatch = CPrec_FindAddrPatch(meth))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(meth, first); do { CPrec_AppendData(meth, sizeof(ObjCMethod)); if (meth->object) CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(meth->object)); if (meth->functype) CPrec_NewPointerPatch(¤t->functype, CPrec_GetTypePatch((Type *) meth->functype)); if (meth->selector) CPrec_NewPointerPatch(¤t->selector, CPrec_GetObjCSelectorPatch(meth->selector)); if (meth->return_type) CPrec_NewPointerPatch(¤t->return_type, CPrec_GetTypePatch(meth->return_type)); if (meth->selector_args) CPrec_NewPointerPatch(¤t->selector_args, CPrec_GetObjCMethodArgPatch(meth->selector_args)); if (!meth->next) break; if ((addrPatch = CPrec_FindAddrPatch(meth->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; meth = meth->next; CPrec_NewAddrPatch(meth, next); } } while (1); return first; } static ObjCProtocol *CPrec_GetObjCProtocolPatch(ObjCProtocol *prot) { AddrPatch *addrPatch; ObjCProtocol *current, *first, *next; if ((addrPatch = CPrec_FindAddrPatch(prot))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(prot, first); do { CPrec_AppendData(prot, sizeof(ObjCProtocol)); CPrec_NamePatch(¤t->name, prot->name); if (prot->protocols) CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(prot->protocols)); if (prot->methods) CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(prot->methods)); if (prot->object) CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(prot->object)); if (!prot->next) break; if ((addrPatch = CPrec_FindAddrPatch(prot->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; prot = prot->next; CPrec_NewAddrPatch(prot, next); } } while (1); return first; } static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst) { AddrPatch *addrPatch; ObjCProtocolList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(lst))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(lst, first); do { CPrec_AppendData(lst, sizeof(ObjCProtocolList)); CPrec_NewPointerPatch(¤t->protocol, CPrec_GetObjCProtocolPatch(lst->protocol)); if (!lst->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; lst = lst->next; } while (1); return first; } static ObjCCategory *CPrec_GetObjCCategoryPatch(ObjCCategory *cat) { AddrPatch *addrPatch; ObjCCategory *current, *first, *next; if ((addrPatch = CPrec_FindAddrPatch(cat))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(cat, first); do { CPrec_AppendData(cat, sizeof(ObjCCategory)); CPrec_NamePatch(¤t->name, cat->name); if (cat->protocols) CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(cat->protocols)); if (cat->methods) CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(cat->methods)); if (!cat->next) break; if ((addrPatch = CPrec_FindAddrPatch(cat->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; cat = cat->next; CPrec_NewAddrPatch(cat, next); } } while (1); return first; } static ObjCInfo *CPrec_GetObjCInfoPatch(ObjCInfo *info) { ObjCInfo *p = CPrec_AppendAlign(); CPrec_AppendData(info, sizeof(ObjCInfo)); if (info->classobject) CPrec_NewPointerPatch(&p->classobject, CPrec_GetObjectPatch(info->classobject)); if (info->metaobject) CPrec_NewPointerPatch(&p->metaobject, CPrec_GetObjectPatch(info->metaobject)); if (info->classrefobj) CPrec_NewPointerPatch(&p->classrefobj, CPrec_GetObjectPatch(info->classrefobj)); if (info->methods) CPrec_NewPointerPatch(&p->methods, CPrec_GetObjCMethodPatch(info->methods)); if (info->protocols) CPrec_NewPointerPatch(&p->protocols, CPrec_GetObjCProtocolListPatch(info->protocols)); if (info->categories) CPrec_NewPointerPatch(&p->categories, CPrec_GetObjCCategoryPatch(info->categories)); return p; } static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg) { TemplArg *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(arg, sizeof(TemplArg)); switch (arg->pid.type) { case TPT_TYPE: if (arg->data.typeparam.type) CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(arg->data.typeparam.type)); break; case TPT_NONTYPE: if (arg->data.paramdecl.expr) CPrec_NewPointerPatch(¤t->data.paramdecl.expr, CPrec_GetExpressionPatch(arg->data.paramdecl.expr)); break; case TPT_TEMPLATE: if (arg->data.ttargtype) CPrec_NewPointerPatch(¤t->data.ttargtype, CPrec_GetTypePatch(arg->data.ttargtype)); break; default: CError_FATAL(1879); } if (!arg->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; arg = arg->next; } while (1); return first; } static TemplParam *CPrec_GetTemplateParamPatch(TemplParam *param) { // register swap issues TemplParam *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(param, sizeof(TemplParam)); if (param->name) CPrec_NamePatch(¤t->name, param->name); switch (param->pid.type) { case TPT_TYPE: if (param->data.typeparam.type) CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(param->data.typeparam.type)); break; case TPT_NONTYPE: CPrec_NewPointerPatch(¤t->data.paramdecl.type, CPrec_GetTypePatch(param->data.paramdecl.type)); if (param->data.paramdecl.defaultarg) CPrec_NewPointerPatch(¤t->data.paramdecl.defaultarg, CPrec_GetExpressionPatch(param->data.paramdecl.defaultarg)); break; case TPT_TEMPLATE: if (param->data.templparam.plist) CPrec_NewPointerPatch(¤t->data.templparam.plist, CPrec_GetTemplateParamPatch(param->data.templparam.plist)); CError_ASSERT(1953, !param->data.templparam.defaultarg); break; default: CError_FATAL(1958); } if (!param->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; param = param->next; } while (1); return first; } static TStreamElement *CPrec_GetTStreamPatch(TStreamElement *tokens, SInt32 count) { TStreamElement elem; TStreamElement *first, *current, *scan; SInt32 x; scan = tokens; x = 0; while (x < count) { elem = *scan; memclrw(scan, sizeof(TStreamElement)); scan->tokentype = elem.tokentype; switch (elem.tokentype) { case TK_IDENTIFIER: scan->data.tkidentifier = elem.data.tkidentifier; break; case TK_INTCONST: scan->subtype = elem.subtype; scan->data.tkintconst = elem.data.tkintconst; break; case TK_FLOATCONST: scan->subtype = elem.subtype; scan->data.tkfloatconst = elem.data.tkfloatconst; break; case TK_STRING: case TK_STRING_WIDE: scan->subtype = elem.subtype; scan->data.tkstring = elem.data.tkstring; break; } x++; scan++; } first = current = CPrec_AppendAlign(); CPrec_AppendData(tokens, count * sizeof(TStreamElement)); if (cprec_dowrite) { TokenPatch *tp = lalloc(sizeof(TokenPatch)); tp->tokens = current; tp->count = count; tp->next = cprec_tokenpatches; cprec_tokenpatches = tp; } x = 0; while (x < count) { switch (tokens->tokentype) { case TK_IDENTIFIER: CPrec_NamePatch(¤t->data.tkidentifier, tokens->data.tkidentifier); break; case TK_INTCONST: case TK_FLOATCONST: break; case TK_STRING: case TK_STRING_WIDE: CPrec_RawMemPatch(¤t->data.tkstring.data, tokens->data.tkstring.data, tokens->data.tkstring.size); break; case TK_EOL: break; default: if (tokens->tokentype < 0) CError_FATAL(2063); } x++; tokens++; current++; } return first; } static TemplFuncInstance *CPrec_GetTemplFuncInstancePatch(TemplFuncInstance *inst) { AddrPatch *addrPatch; TemplFuncInstance *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(inst))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(inst, first); do { CPrec_AppendData(inst, sizeof(TemplFuncInstance)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(inst->object)); CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(inst->args)); if (!inst->next) break; if ((addrPatch = CPrec_FindAddrPatch(inst->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; inst = inst->next; CPrec_NewAddrPatch(inst, next); } } while (1); return first; } static TemplateMember *CPrec_GetTemplateMemberPatch(TemplateMember *memb) { TemplateMember *current, *first, *next; first = current = CPrec_AppendAlign(); do { memclrw(&memb->fileoffset, sizeof(FileOffsetInfo)); memb->srcfile = NULL; memb->startoffset = 0; memb->endoffset = 0; CPrec_AppendData(memb, sizeof(TemplateMember)); if (memb->params) CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(memb->params)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(memb->object)); if (memb->stream.firsttoken) CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(memb->stream.firsttoken, memb->stream.tokens)); if (!memb->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; memb = memb->next; } while (1); return first; } static TemplPartialSpec *CPrec_GetTemplPartialSpecPatch(TemplPartialSpec *pspec) { TemplPartialSpec *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(pspec, sizeof(TemplPartialSpec)); if (pspec->templ) CPrec_NewPointerPatch(¤t->templ, CPrec_GetTypePatch((Type *) pspec->templ)); if (pspec->args) CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(pspec->args)); if (!pspec->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; pspec = pspec->next; } while (1); return first; } static TemplateFriend *CPrec_GetTemplateFriendPatch(TemplateFriend *frnd) { TemplateFriend *p; memclrw(&frnd->fileoffset, sizeof(FileOffsetInfo)); p = CPrec_AppendAlign(); CPrec_AppendData(frnd, sizeof(TemplateFriend)); if (frnd->decl.thetype) CPrec_NewPointerPatch(&p->decl.thetype, CPrec_GetTypePatch(frnd->decl.thetype)); if (frnd->decl.nspace) CPrec_NewPointerPatch(&p->decl.nspace, CPrec_GetNameSpacePatch(frnd->decl.nspace)); if (frnd->decl.name) CPrec_NamePatch(&p->decl.name, frnd->decl.name); if (frnd->decl.expltargs) CPrec_NewPointerPatch(&p->decl.expltargs, CPrec_GetTemplateArgPatch(frnd->decl.expltargs)); if (frnd->stream.firsttoken) CPrec_NewPointerPatch(&p->stream.firsttoken, CPrec_GetTStreamPatch(frnd->stream.firsttoken, frnd->stream.tokens)); return p; } static TemplateAction *CPrec_GetTemplateActionPatch(TemplateAction *act) { // register swap issue TemplateAction *current, *first, *next; first = current = CPrec_AppendAlign(); do { memclrw(&act->source_ref, sizeof(TStreamElement)); CPrec_AppendData(act, sizeof(TemplateAction)); switch (act->type) { case TAT_NESTEDCLASS: CPrec_NewPointerPatch(¤t->u.tclasstype, CPrec_GetTypePatch((Type *) act->u.tclasstype)); break; case TAT_ENUMTYPE: CPrec_NewPointerPatch(¤t->u.enumtype, CPrec_GetTypePatch((Type *) act->u.enumtype)); break; case TAT_FRIEND: CPrec_NewPointerPatch(¤t->u.tfriend, CPrec_GetTemplateFriendPatch(act->u.tfriend)); break; case TAT_ENUMERATOR: CPrec_NewPointerPatch(¤t->u.enumerator.objenumconst, CPrec_GetObjEnumConstPatch(act->u.enumerator.objenumconst)); if (act->u.enumerator.initexpr) CPrec_NewPointerPatch(¤t->u.enumerator.initexpr, CPrec_GetExpressionPatch(act->u.enumerator.initexpr)); break; case TAT_BASE: CPrec_NewPointerPatch(¤t->u.base.type, CPrec_GetTypePatch(act->u.base.type)); if (act->u.base.insert_after) CPrec_NewPointerPatch(¤t->u.base.insert_after, CPrec_GetClassListPatch(act->u.base.insert_after)); break; case TAT_OBJECTINIT: CPrec_NewPointerPatch(¤t->u.objectinit.object, CPrec_GetObjectPatch(act->u.objectinit.object)); CPrec_NewPointerPatch(¤t->u.objectinit.initexpr, CPrec_GetExpressionPatch(act->u.objectinit.initexpr)); break; case TAT_USINGDECL: CPrec_NewPointerPatch(¤t->u.usingdecl.type, CPrec_GetTypeTemplDepPatch(act->u.usingdecl.type)); break; case TAT_OBJECTDEF: CPrec_NewPointerPatch(¤t->u.refobj, CPrec_GetObjBasePatch(act->u.refobj)); break; default: CError_FATAL(2410); } if (!act->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; act = act->next; } while (1); return first; } static TemplateFunction *CPrec_GetTemplateFunctionPatch(TemplateFunction *tf) { // the same cursed register swaps AddrPatch *addrPatch; TemplateFunction *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(tf))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(tf, first); do { memclrw(&tf->deftoken, sizeof(TStreamElement)); tf->srcfile = NULL; tf->startoffset = 0; tf->endoffset = 0; CPrec_AppendData(tf, sizeof(TemplateFunction)); if (tf->unk4) CPrec_NewPointerPatch(¤t->unk4, CPrec_GetTemplateFunctionPatch(tf->unk4)); CPrec_NamePatch(¤t->name, tf->name); if (tf->params) CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(tf->params)); if (tf->stream.firsttoken) CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(tf->stream.firsttoken, tf->stream.tokens)); CPrec_NewPointerPatch(¤t->tfunc, CPrec_GetObjectPatch(tf->tfunc)); if (tf->instances) CPrec_NewPointerPatch(¤t->instances, CPrec_GetTemplFuncInstancePatch(tf->instances)); if (!tf->next) break; if ((addrPatch = CPrec_FindAddrPatch(tf->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; tf = tf->next; CPrec_NewAddrPatch(tf, next); } } while (1); return first; } static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { TypeClass *first, *current, *next; Boolean hasNextTempl, hasNextTemplInst; first = current = CPrec_AppendAlign(); do_over: hasNextTempl = hasNextTemplInst = 0; CPrec_NewAddrPatch(tclass, current); if (tclass->flags & CLASS_FLAGS_100) { // template class CPrec_AppendData(tclass, sizeof(TemplClass)); if (TEMPL_CLASS(tclass)->next) hasNextTempl = 1; if (TEMPL_CLASS(tclass)->templ_parent) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ_parent)); if (TEMPL_CLASS(tclass)->inst_parent) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->inst_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->inst_parent)); if (TEMPL_CLASS(tclass)->templ__params) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__params, CPrec_GetTemplateParamPatch(TEMPL_CLASS(tclass)->templ__params)); if (TEMPL_CLASS(tclass)->members) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->members, CPrec_GetTemplateMemberPatch(TEMPL_CLASS(tclass)->members)); if (TEMPL_CLASS(tclass)->instances) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->instances, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->instances)); if (TEMPL_CLASS(tclass)->pspec_owner) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspec_owner, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->pspec_owner)); if (TEMPL_CLASS(tclass)->pspecs) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspecs, CPrec_GetTemplPartialSpecPatch(TEMPL_CLASS(tclass)->pspecs)); if (TEMPL_CLASS(tclass)->actions) CPrec_NewPointerPatch(&TEMPL_CLASS(current)->actions, CPrec_GetTemplateActionPatch(TEMPL_CLASS(tclass)->actions)); } else if (tclass->flags & CLASS_FLAGS_800) { // template class instance CPrec_AppendData(tclass, sizeof(TemplClassInst)); if (TEMPL_CLASS_INST(tclass)->next) hasNextTemplInst = 1; if (TEMPL_CLASS_INST(tclass)->parent) CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->parent)); if (TEMPL_CLASS_INST(tclass)->templ) CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->templ, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->templ)); if (TEMPL_CLASS_INST(tclass)->inst_args) CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->inst_args, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->inst_args)); if (TEMPL_CLASS_INST(tclass)->oargs) CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->oargs, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->oargs)); } else { // base CPrec_AppendData(tclass, sizeof(TypeClass)); } if (tclass->nspace) CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(tclass->nspace)); if (tclass->classname) CPrec_NamePatch(¤t->classname, tclass->classname); if (tclass->bases) CPrec_NewPointerPatch(¤t->bases, CPrec_GetClassListPatch(tclass->bases)); if (tclass->vbases) CPrec_NewPointerPatch(¤t->vbases, CPrec_GetVClassListPatch(tclass->vbases)); if (tclass->ivars) CPrec_NewPointerPatch(¤t->ivars, CPrec_GetObjMemberVarPatch(tclass->ivars)); if (tclass->friends) CPrec_NewPointerPatch(¤t->friends, CPrec_GetClassFriendPatch(tclass->friends)); if (tclass->vtable) CPrec_NewPointerPatch(¤t->vtable, CPrec_GetVTablePatch(tclass->vtable)); if (tclass->sominfo) CPrec_NewPointerPatch(¤t->sominfo, CPrec_GetSOMInfoPatch(tclass->sominfo)); if (tclass->objcinfo) CPrec_NewPointerPatch(¤t->objcinfo, CPrec_GetObjCInfoPatch(tclass->objcinfo)); if (hasNextTempl) { AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS(tclass)->next); if (!addrPatch) { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, next); current = next; tclass = (TypeClass *) TEMPL_CLASS(tclass)->next; goto do_over; } else { CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, addrPatch->value); } } if (hasNextTemplInst) { AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS_INST(tclass)->next); if (!addrPatch) { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, next); current = next; tclass = (TypeClass *) TEMPL_CLASS_INST(tclass)->next; goto do_over; } else { CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, addrPatch->value); } } return first; } static Type *CPrec_GetTypePatch(Type *type) { AddrPatch *addrPatch = CPrec_FindAddrPatch(type); if (addrPatch) return addrPatch->value; switch (type->type) { case TYPEPOINTER: case TYPEARRAY: return (Type *) CPrec_GetTypePointerPatch(TYPE_POINTER(type)); case TYPEENUM: return (Type *) CPrec_GetTypeEnumPatch(TYPE_ENUM(type)); case TYPEBITFIELD: return (Type *) CPrec_GetTypeBitfieldPatch(TYPE_BITFIELD(type)); case TYPESTRUCT: return (Type *) CPrec_GetTypeStructPatch(TYPE_STRUCT(type)); case TYPEFUNC: return (Type *) CPrec_GetTypeFuncPatch(TYPE_FUNC(type)); case TYPEMEMBERPOINTER: return (Type *) CPrec_GetTypeMemberPointerPatch(TYPE_MEMBER_POINTER(type)); case TYPETEMPLATE: return (Type *) CPrec_GetTypeTemplDepPatch(TYPE_TEMPLATE(type)); case TYPECLASS: return (Type *) CPrec_GetTypeClassPatch(TYPE_CLASS(type)); case TYPEVOID: case TYPEINT: case TYPEFLOAT: case TYPELABEL: case TYPEOBJCID: case TYPETEMPLDEPEXPR: default: CError_FATAL(2796); return NULL; } } static ExceptionAction *CPrec_GetExceptionPatch(ExceptionAction *exc) { ExceptionAction *first, *current, *next; first = current = CPrec_AppendAlign(); repeat: CPrec_AppendData(exc, sizeof(ExceptionAction)); switch (exc->type) { case EAT_DESTROYLOCAL: CPrec_NewPointerPatch(¤t->data.destroy_local.dtor, CPrec_GetObjectPatch(exc->data.destroy_local.dtor)); break; case EAT_DESTROYLOCALCOND: CPrec_NewPointerPatch(¤t->data.destroy_local_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_cond.dtor)); break; case EAT_DESTROYLOCALOFFSET: CPrec_NewPointerPatch(¤t->data.destroy_local_offset.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_offset.dtor)); break; case EAT_DESTROYLOCALPOINTER: CPrec_NewPointerPatch(¤t->data.destroy_local_pointer.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_pointer.dtor)); break; case EAT_DESTROYLOCALARRAY: CPrec_NewPointerPatch(¤t->data.destroy_local_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_array.dtor)); break; case EAT_DESTROYPARTIALARRAY: break; case EAT_DESTROYMEMBER: case EAT_DESTROYBASE: CPrec_NewPointerPatch(¤t->data.destroy_member.dtor, CPrec_GetObjectPatch(exc->data.destroy_member.dtor)); break; case EAT_DESTROYMEMBERCOND: CPrec_NewPointerPatch(¤t->data.destroy_member_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_cond.dtor)); break; case EAT_DESTROYMEMBERARRAY: CPrec_NewPointerPatch(¤t->data.destroy_member_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_array.dtor)); break; case EAT_DELETEPOINTER: case EAT_DELETELOCALPOINTER: CPrec_NewPointerPatch(¤t->data.delete_pointer.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer.deletefunc)); break; case EAT_DELETEPOINTERCOND: CPrec_NewPointerPatch(¤t->data.delete_pointer_cond.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer_cond.deletefunc)); break; case EAT_CATCHBLOCK: if (exc->data.catch_block.catch_typeid) { CPrec_NewPointerPatch(¤t->data.catch_block.catch_typeid, CPrec_GetObjectPatch(exc->data.catch_block.catch_typeid)); CPrec_NewPointerPatch(¤t->data.catch_block.catch_type, CPrec_GetTypePatch(exc->data.catch_block.catch_type)); } break; case EAT_ACTIVECATCHBLOCK: break; case EAT_SPECIFICATION: if (exc->data.specification.unexp_id) { int x; char *ptrs; ptrs = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->data.specification.unexp_id, ptrs); CPrec_AppendData(exc->data.specification.unexp_id, sizeof(Object *) * exc->data.specification.unexp_ids); for (x = 0; x < exc->data.specification.unexp_ids; x++) { CPrec_NewPointerPatch(ptrs + x * sizeof(Object *), CPrec_GetObjectPatch(exc->data.specification.unexp_id[x])); } } break; case EAT_TERMINATE: break; default: CError_FATAL(2905); } if (exc->prev) { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->prev, next); current = next; exc = exc->prev; goto repeat; } return first; } static ENodeList *CPrec_GetExpressionListPatch(ENodeList *lst) { ENodeList *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(lst, sizeof(ENodeList)); CPrec_NewPointerPatch(¤t->node, CPrec_GetExpressionPatch(lst->node)); if (!lst->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; lst = lst->next; } while (1); return first; } static EMemberInfo *CPrec_GetEMemberInfoPatch(EMemberInfo *emember) { EMemberInfo *p; CError_FATAL(2953); p = CPrec_AppendAlign(); CPrec_AppendData(emember, sizeof(EMemberInfo)); if (emember->path) CPrec_NewPointerPatch(&p->path, CPrec_GetClassAccessPatch(emember->path)); if (emember->expr) CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(emember->expr)); CError_ASSERT(2968, !emember->templargs); CPrec_NewPointerPatch(&p->list, CPrec_GetNameSpaceObjectListPatch(emember->list)); return p; } static ENode *CPrec_GetExpressionPatch(ENode *expr) { ENode *p; if (ENODE_IS(expr, ETEMPLDEP) && expr->data.templdep.subtype == TDE_SOURCEREF) expr->data.templdep.u.sourceref.token = NULL; p = CPrec_AppendAlign(); CPrec_AppendData(expr, sizeof(ENode)); CPrec_NewPointerPatch(&p->rtype, CPrec_GetTypePatch(expr->rtype)); switch (expr->type) { ENODE_CASE_MONADIC: CPrec_NewPointerPatch(&p->data.monadic, CPrec_GetExpressionPatch(expr->data.monadic)); break; ENODE_CASE_DIADIC_ALL: CPrec_NewPointerPatch(&p->data.diadic.left, CPrec_GetExpressionPatch(expr->data.diadic.left)); CPrec_NewPointerPatch(&p->data.diadic.right, CPrec_GetExpressionPatch(expr->data.diadic.right)); break; case ECOND: CPrec_NewPointerPatch(&p->data.cond.cond, CPrec_GetExpressionPatch(expr->data.cond.cond)); CPrec_NewPointerPatch(&p->data.cond.expr1, CPrec_GetExpressionPatch(expr->data.cond.expr1)); CPrec_NewPointerPatch(&p->data.cond.expr2, CPrec_GetExpressionPatch(expr->data.cond.expr2)); break; case ESTRINGCONST: CPrec_RawMemPatch(&p->data.string.data, expr->data.string.data, expr->data.string.size); break; case EOBJREF: CPrec_NewPointerPatch(&p->data.objref, CPrec_GetObjectPatch(expr->data.objref)); break; case EOBJLIST: CPrec_NewPointerPatch(&p->data.objlist.list, CPrec_GetNameSpaceObjectListPatch(expr->data.objlist.list)); CError_ASSERT(3043, !expr->data.objlist.templargs); if (expr->data.objlist.name) CPrec_NamePatch(&p->data.objlist.name, expr->data.objlist.name); break; case EMFPOINTER: CPrec_NewPointerPatch(&p->data.mfpointer.accessnode, CPrec_GetExpressionPatch(expr->data.mfpointer.accessnode)); CPrec_NewPointerPatch(&p->data.mfpointer.mfpointer, CPrec_GetExpressionPatch(expr->data.mfpointer.mfpointer)); break; case ENULLCHECK: CPrec_NewPointerPatch(&p->data.nullcheck.nullcheckexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.nullcheckexpr)); CPrec_NewPointerPatch(&p->data.nullcheck.condexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.condexpr)); break; case ETEMP: CPrec_NewPointerPatch(&p->data.temp.type, CPrec_GetTypePatch(expr->data.temp.type)); break; case EFUNCCALL: case EFUNCCALLP: CPrec_NewPointerPatch(&p->data.funccall.funcref, CPrec_GetExpressionPatch(expr->data.funccall.funcref)); CPrec_NewPointerPatch(&p->data.funccall.functype, CPrec_GetTypePatch(TYPE(expr->data.funccall.functype))); if (expr->data.funccall.args) CPrec_NewPointerPatch(&p->data.funccall.args, CPrec_GetExpressionListPatch(expr->data.funccall.args)); break; case EMEMBER: CPrec_NewPointerPatch(&p->data.emember, CPrec_GetEMemberInfoPatch(expr->data.emember)); break; case ETEMPLDEP: switch (expr->data.templdep.subtype) { case TDE_PARAM: break; case TDE_SIZEOF: case TDE_ALIGNOF: CPrec_NewPointerPatch(&p->data.templdep.u.typeexpr.type, CPrec_GetTypePatch(expr->data.templdep.u.typeexpr.type)); break; case TDE_CAST: if (expr->data.templdep.u.cast.args) CPrec_NewPointerPatch(&p->data.templdep.u.cast.args, CPrec_GetExpressionListPatch(expr->data.templdep.u.cast.args)); CPrec_NewPointerPatch(&p->data.templdep.u.cast.type, CPrec_GetTypePatch(expr->data.templdep.u.cast.type)); break; case TDE_QUALNAME: CPrec_NamePatch(&p->data.templdep.u.qual.name, expr->data.templdep.u.qual.name); CPrec_NewPointerPatch(&p->data.templdep.u.qual.type, CPrec_GetTypePatch(TYPE(expr->data.templdep.u.qual.type))); break; case TDE_OBJ: CPrec_NewPointerPatch(&p->data.templdep.u.obj, CPrec_GetObjectPatch(expr->data.templdep.u.obj)); break; case TDE_SOURCEREF: CPrec_NewPointerPatch(&p->data.templdep.u.sourceref.expr, CPrec_GetExpressionPatch(expr->data.templdep.u.sourceref.expr)); break; case TDE_ADDRESS_OF: CPrec_NewPointerPatch(&p->data.templdep.u.monadic, CPrec_GetExpressionPatch(expr->data.templdep.u.monadic)); break; default: CError_FATAL(3136); } break; case EINTCONST: case EFLOATCONST: case EPRECOMP: case EARGOBJ: case ELOCOBJ: case ELABEL: case EINSTRUCTION: case EVECTOR128CONST: break; default: CError_FATAL(3142); } return p; } static CI_Switch *CPrec_GetSwitchInfoPatch(CI_Switch *si) { CI_Switch *p = CPrec_AppendAlign(); CPrec_AppendData(si, sizeof(CI_Switch) + sizeof(CI_SwitchCase) * (si->numcases - 1)); CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(si->expr)); CPrec_NewPointerPatch(&p->unkSwitch8, CPrec_GetTypePatch(si->unkSwitch8)); return p; } static InlineAsm *CPrec_GetInlineAsmPatch(InlineAsm *ia, SInt32 size) { InlineAsm *p; SInt32 index; SInt32 offset; Object *object; p = CPrec_AppendAlign(); CPrec_AppendData(ia, size); index = 0; while (1) { object = InlineAsm_GetObjectOffset(ia, index, &offset); if (!object) break; object = CPrec_GetObjectPatch(object); CPrec_NewPointerPatch((char *) p + offset, object); index++; } return p; } static CI_Statement *CPrec_GetStatementPatch(CI_Statement *stmt, short count) { short i; CI_Statement *first, *current; for (i = 0; i < count; i++) { stmt[i].sourcefilepath = NULL; stmt[i].sourceoffset = -1; } first = current = CPrec_AppendAlign(); CPrec_AppendData(stmt, sizeof(CI_Statement) * count); for (i = 0; i < count; i++) { if (stmt->dobjstack) CPrec_NewPointerPatch(¤t->dobjstack, CPrec_GetExceptionPatch(stmt->dobjstack)); switch (stmt->type) { case ST_EXPRESSION: case ST_RETURN: case ST_BEGINCATCH: case ST_ENDCATCH: case ST_ENDCATCHDTOR: if (stmt->u.expr) CPrec_NewPointerPatch(¤t->u.expr, CPrec_GetExpressionPatch(stmt->u.expr)); break; case ST_IFGOTO: case ST_IFNGOTO: CPrec_NewPointerPatch(¤t->u.ifgoto.expr, CPrec_GetExpressionPatch(stmt->u.ifgoto.expr)); break; case ST_SWITCH: CPrec_NewPointerPatch(¤t->u.switchdata, CPrec_GetSwitchInfoPatch(stmt->u.switchdata)); break; case ST_ASM: CPrec_NewPointerPatch(¤t->u.asmdata.data, CPrec_GetInlineAsmPatch(stmt->u.asmdata.data, stmt->u.asmdata.size)); break; case ST_NOP: case ST_LABEL: case ST_GOTO: break; default: CError_FATAL(3261); } current++; stmt++; } return first; } static CI_Var *CPrec_GetLocObjectPatch(CI_Var *obj, short count) { CI_Var *first, *current; short i; first = current = CPrec_AppendAlign(); CPrec_AppendData(obj, sizeof(CI_Var) * count); for (i = 0; i < count; i++) { CPrec_NamePatch(¤t->name, obj->name); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(obj->type)); current++; obj++; } return first; } static CI_FuncData *CPrec_GetInlineFuncPatch(CI_FuncData *ifunc) { CI_FuncData *p; memclrw(&ifunc->fileoffset, sizeof(FileOffsetInfo)); ifunc->symdecloffset = 0; ifunc->functionbodyoffset = 0; ifunc->functionbodypath = NULL; ifunc->symdeclend = 0; p = CPrec_AppendAlign(); CPrec_AppendData(ifunc, sizeof(CI_FuncData)); if (ifunc->numarguments) CPrec_NewPointerPatch(&p->arguments, CPrec_GetLocObjectPatch(ifunc->arguments, ifunc->numarguments)); if (ifunc->numlocals) CPrec_NewPointerPatch(&p->locals, CPrec_GetLocObjectPatch(ifunc->locals, ifunc->numlocals)); if (ifunc->numstatements) CPrec_NewPointerPatch(&p->statements, CPrec_GetStatementPatch(ifunc->statements, ifunc->numstatements)); return p; } static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj) { AddrPatch *addrPatch; ObjEnumConst *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(obj))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(obj, first); do { CPrec_AppendData(obj, sizeof(ObjEnumConst)); if (cprec_dowrite) { CError_ASSERT(3349, obj->access != 255); obj->access = 255; } CPrec_NamePatch(¤t->name, obj->name); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch( obj->type)); if (!obj->next) break; if ((addrPatch = CPrec_FindAddrPatch(obj->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; obj = obj->next; CPrec_NewAddrPatch(obj, next); } } while (1); return first; } static ObjType *CPrec_GetObjTypePatch(ObjType *obj) { AddrPatch *addrPatch; ObjType *p; if ((addrPatch = CPrec_FindAddrPatch(obj))) return addrPatch->value; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(obj, p); CPrec_AppendData(obj, sizeof(ObjType)); CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); return p; } static ObjTypeTag *CPrec_GetObjTypeTagPatch(ObjTypeTag *obj) { AddrPatch *addrPatch; ObjTypeTag *p; if ((addrPatch = CPrec_FindAddrPatch(obj))) return addrPatch->value; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(obj, p); CPrec_AppendData(obj, sizeof(ObjTypeTag)); CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); return p; } static ObjNameSpace *CPrec_GetObjNameSpacePatch(ObjNameSpace *obj) { AddrPatch *addrPatch; ObjNameSpace *p; if ((addrPatch = CPrec_FindAddrPatch(obj))) return addrPatch->value; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(obj, p); CPrec_AppendData(obj, sizeof(ObjNameSpace)); CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); return p; } static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar) { AddrPatch *addrPatch; ObjMemberVar *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(ivar))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(ivar, first); while (1) { if (ivar->has_path) { CPrec_AppendData(ivar, sizeof(ObjMemberVarPath)); if (OBJ_MEMBER_VAR_PATH(ivar)->path) CPrec_NewPointerPatch( &OBJ_MEMBER_VAR_PATH(current)->path, CPrec_GetClassAccessPatch(OBJ_MEMBER_VAR_PATH(ivar)->path)); } else { CPrec_AppendData(ivar, sizeof(ObjMemberVar)); } if (ivar->name) CPrec_NamePatch(¤t->name, ivar->name); CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(ivar->type)); if (!ivar->next) break; if ((addrPatch = CPrec_FindAddrPatch(ivar->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; ivar = ivar->next; CPrec_NewAddrPatch(ivar, current); } return first; } static DefArgCtorInfo *CPrec_GetDefArgCtorInfoPatch(DefArgCtorInfo *dac) { DefArgCtorInfo *p = CPrec_AppendAlign(); CPrec_AppendData(dac, sizeof(DefArgCtorInfo)); CPrec_NewPointerPatch(&p->default_func, CPrec_GetObjectPatch(dac->default_func)); CPrec_NewPointerPatch(&p->default_arg, CPrec_GetExpressionPatch(dac->default_arg)); return p; } static InlineXRef *CPrec_GetInlineXRefPatch(InlineXRef *ix) { InlineXRef *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(ix, sizeof(InlineXRef) + sizeof(XRefOffset) * (ix->numxrefs - 1)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ix->object)); if (!ix->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; ix = ix->next; } while (1); return first; } static Object *CPrec_GetObjectPatch(Object *obj) { AddrPatch *addrPatch; Object *p; if (CWUserBreak(cparams.context) != cwNoErr) CError_UserBreak(); if ((addrPatch = CPrec_FindAddrPatch(obj))) return addrPatch->value; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(obj, p); obj->toc = NULL; if ((obj->qual & Q_400000) && obj->datatype != DALIAS) { CPrec_AppendData(obj, sizeof(ObjectTemplated)); CPrec_NewPointerPatch(&OBJECT_TEMPL(p)->parent, CPrec_GetObjectPatch(OBJECT_TEMPL(obj)->parent)); } else { CPrec_AppendData(obj, sizeof(Object)); } if (obj->nspace) CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); if (obj->name) CPrec_NamePatch(&p->name, obj->name); CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); switch (obj->datatype) { case DABSOLUTE: break; case DLOCAL: CError_FATAL(3580); break; case DFUNC: case DVFUNC: if (IS_TEMPL_FUNC(obj->type)) CPrec_NewPointerPatch(&p->u.func.u.templ, CPrec_GetTemplateFunctionPatch(obj->u.func.u.templ)); else if ((obj->qual & Q_INLINE) && obj->u.func.u.ifuncdata) CPrec_NewPointerPatch(&p->u.func.u.ifuncdata, CPrec_GetInlineFuncPatch(obj->u.func.u.ifuncdata)); if (obj->u.func.defargdata) CPrec_NewPointerPatch(&p->u.func.defargdata, CPrec_GetDefArgCtorInfoPatch(obj->u.func.defargdata)); if (obj->u.func.linkname) CPrec_NamePatch(&p->u.func.linkname, obj->u.func.linkname); if (obj->u.func.inst) CPrec_NewPointerPatch(&p->u.func.inst, CPrec_GetTemplFuncInstancePatch(obj->u.func.inst)); break; case DDATA: CError_ASSERT(3622, !obj->u.data.info); if (obj->qual & Q_10000) { switch (obj->type->type) { case TYPEINT: case TYPEENUM: case TYPEPOINTER: break; case TYPEFLOAT: CPrec_RawMemPatch(&p->u.data.u.floatconst, obj->u.data.u.floatconst, sizeof(Float)); break; default: CError_FATAL(3638); } } if (obj->u.data.linkname) CPrec_NamePatch(&p->u.data.linkname, obj->u.data.linkname); break; case DINLINEFUNC: CPrec_RawMemPatch(&p->u.ifunc.data, obj->u.ifunc.data, obj->u.ifunc.size); if (obj->u.ifunc.xrefs) CPrec_NewPointerPatch(&p->u.ifunc.xrefs, CPrec_GetInlineXRefPatch(obj->u.ifunc.xrefs)); break; case DALIAS: CPrec_NewPointerPatch(&p->u.alias.object, CPrec_GetObjectPatch(obj->u.alias.object)); if (obj->u.alias.member) CPrec_NewPointerPatch(&p->u.alias.member, CPrec_GetClassAccessPatch(obj->u.alias.member)); break; default: CError_FATAL(3677); } if (cprec_dowrite) obj->datatype = -1; return p; } static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj) { switch (obj->otype) { default: CError_FATAL(3694); case OT_ENUMCONST: return (ObjBase *) CPrec_GetObjEnumConstPatch((ObjEnumConst *) obj); case OT_TYPE: return (ObjBase *) CPrec_GetObjTypePatch((ObjType *) obj); case OT_TYPETAG: return (ObjBase *) CPrec_GetObjTypeTagPatch((ObjTypeTag *) obj); case OT_NAMESPACE: return (ObjBase *) CPrec_GetObjNameSpacePatch((ObjNameSpace *) obj); case OT_MEMBERVAR: return (ObjBase *) CPrec_GetObjMemberVarPatch((ObjMemberVar *) obj); case OT_OBJECT: return (ObjBase *) CPrec_GetObjectPatch((Object *) obj); } } static ObjectList *CPrec_GetObjectListPatch(ObjectList *ol) { AddrPatch *addrPatch; ObjectList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(ol))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(ol, first); restart: CPrec_AppendData(ol, sizeof(ObjectList)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ol->object)); if (ol->next) { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; ol = ol->next; goto restart; } return first; } static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol) { AddrPatch *addrPatch; NameSpaceObjectList *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(nsol))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(nsol, first); do { CPrec_AppendData(nsol, sizeof(NameSpaceObjectList)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjBasePatch(nsol->object)); if (!nsol->next) break; if ((addrPatch = CPrec_FindAddrPatch(nsol->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; nsol = nsol->next; CPrec_NewAddrPatch(nsol, next); } } while (1); return first; } static NameSpaceName *CPrec_GetNameSpaceNamePatch(NameSpaceName *nsn, Boolean flag) { AddrPatch *addrPatch; NameSpaceName *first, *current, *next; if ((addrPatch = CPrec_FindAddrPatch(nsn))) return addrPatch->value; first = current = CPrec_AppendAlign(); CPrec_NewAddrPatch(nsn, first); do { CPrec_AppendData(nsn, sizeof(NameSpaceName)); CPrec_NamePatch(¤t->name, nsn->name); CPrec_NewPointerPatch(¤t->first.object, CPrec_GetObjBasePatch(nsn->first.object)); if (nsn->first.next) CPrec_NewPointerPatch(¤t->first.next, CPrec_GetNameSpaceObjectListPatch(nsn->first.next)); if (!nsn->next) break; if ((addrPatch = CPrec_FindAddrPatch(nsn->next))) { CPrec_NewPointerPatch(¤t->next, addrPatch->value); break; } else { next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; nsn = nsn->next; CPrec_NewAddrPatch(nsn, next); } } while (!flag || !cprec_dowrite || CPrec_FlushBufferCheck() == noErr); return first; } static NameSpaceList *CPrec_GetNameSpaceListPatch(NameSpaceList *nsl) { NameSpaceList *first, *current, *next; first = current = CPrec_AppendAlign(); do { CPrec_AppendData(nsl, sizeof(NameSpaceList)); CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(nsl->nspace)); if (!nsl->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; nsl = nsl->next; } while (1); return first; } static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace) { NameSpace *p; AddrPatch *addrPatch; if ((addrPatch = CPrec_FindAddrPatch(nspace))) return addrPatch->value; p = CPrec_AppendAlign(); CPrec_NewAddrPatch(nspace, p); CPrec_AppendData(nspace, sizeof(NameSpace)); if (nspace->parent) CPrec_NewPointerPatch(&p->parent, CPrec_GetNameSpacePatch(nspace->parent)); if (nspace->name) CPrec_NamePatch(&p->name, nspace->name); if (nspace->usings) CPrec_NewPointerPatch(&p->usings, CPrec_GetNameSpaceListPatch(nspace->usings)); if (nspace->theclass) CPrec_NewPointerPatch(&p->theclass, CPrec_GetTypePatch((Type *) nspace->theclass)); if (nspace->is_hash) { char *hash; int i; hash = CPrec_AppendAlign(); CPrec_NewPointerPatch(&p->data.hash, hash); CPrec_AppendData(nspace->data.hash, sizeof(NameSpaceName *) * 1024); for (i = 0; i < 1024; i++) { if (nspace->data.hash[i]) CPrec_NewPointerPatch(hash + (i * sizeof(NameSpaceName *)), CPrec_GetNameSpaceNamePatch(nspace->data.hash[i], 0)); } } else if (nspace->data.list) { CPrec_NewPointerPatch(&p->data.list, CPrec_GetNameSpaceNamePatch(nspace->data.list, 0)); } return p; } static void CPrec_DumpRootNameSpace(void) { NameSpaceList *nslist; NameSpaceName *nsname; int i; CError_ASSERT(3905, cscope_root->is_hash); if (cscope_root->usings) { nslist = CPrec_GetNameSpaceListPatch(cscope_root->usings); if (cprec_dowrite) cprec_header->usings = nslist; } if (cprec_dowrite) cprec_header->root_names = cscope_root->names; i = 0; do { if (cscope_root->data.hash[i]) { nsname = CPrec_GetNameSpaceNamePatch(cscope_root->data.hash[i], 1); if (cprec_dowrite) { if (cprec_ioerror != noErr) break; cprec_header->root_nametable[i] = nsname; } } } while (++i < 0x400); } static CSOMStub *CPrec_GetSOMPatch(CSOMStub *stub) { CSOMStub *first, *current, *next; first = current = CPrec_AppendAlign(); while (1) { CPrec_AppendData(stub, sizeof(CSOMStub)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(stub->object)); CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(stub->tclass))); if (!stub->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; stub = stub->next; } return first; } static OLinkList *CPrec_GetOLinkPatch(OLinkList *olink) { OLinkList *first, *current, *next; first = current = CPrec_AppendAlign(); while (1) { CPrec_AppendData(olink, sizeof(OLinkList)); CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(olink->obj)); if (!olink->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; olink = olink->next; } return first; } static StaticData *CPrec_GetStaticDataPatch(StaticData *sd) { StaticData *current, *first, *next; first = current = CPrec_AppendAlign(); while (1) { CPrec_AppendData(sd, sizeof(StaticData)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(sd->object)); if (sd->buffer) CPrec_RawMemPatch(¤t->buffer, sd->buffer, sd->object->type->size); if (sd->links) CPrec_NewPointerPatch(¤t->links, CPrec_GetOLinkPatch(sd->links)); if (!sd->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; sd = sd->next; } return first; } static CallbackAction *CPrec_GetCallbackPatch(CallbackAction *ca) { CallbackAction *first, *current, *next; first = current = CPrec_AppendAlign(); while (1) { CPrec_AppendData(ca, sizeof(CallbackAction)); CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(ca->obj)); CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(ca->tclass))); if (!ca->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; ca = ca->next; } return first; } static ObjCSelector **CPrec_GetSelHashTablePatch(ObjCSelector **table) { ObjCSelector **first, **current; int i; first = current = CPrec_AppendAlign(); CPrec_AppendData(table, sizeof(ObjCSelector *) * 0x400); for (i = 0; i < 0x400; i++) { if (*table) CPrec_NewPointerPatch(current, CPrec_GetObjCSelectorPatch(*table)); table++; current++; } return first; } static InitExpr *CPrec_GetIExpressionPatch(InitExpr *initexpr) { InitExpr *first, *current, *next; first = current = CPrec_AppendAlign(); while (1) { CPrec_AppendData(initexpr, sizeof(InitExpr)); CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(initexpr->object)); CPrec_NewPointerPatch(¤t->expr, CPrec_GetExpressionPatch(initexpr->expr)); if (!initexpr->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; initexpr = initexpr->next; } return first; } static CI_Action *CPrec_GetInlineActionPatch(CI_Action *act) { CI_Action *current, *first, *next; first = current = CPrec_AppendAlign(); while (1) { if (act->actiontype == CI_ActionInlineFunc) memclrw(&act->u.inlinefunc.fileoffset, sizeof(FileOffsetInfo)); CPrec_AppendData(act, sizeof(CI_Action)); CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(act->obj)); switch (act->actiontype) { case CI_ActionInlineFunc: if (act->u.inlinefunc.stream.firsttoken) CPrec_NewPointerPatch( ¤t->u.inlinefunc.stream.firsttoken, CPrec_GetTStreamPatch(act->u.inlinefunc.stream.firsttoken, act->u.inlinefunc.stream.tokens)); if (act->u.inlinefunc.tclass) CPrec_NewPointerPatch(¤t->u.inlinefunc.tclass, CPrec_GetTypePatch(TYPE(act->u.inlinefunc.tclass))); break; case CI_ActionMemberFunc: CPrec_NewPointerPatch(¤t->u.memberfunc.templ, CPrec_GetTypePatch(TYPE(act->u.memberfunc.templ))); CPrec_NewPointerPatch(¤t->u.memberfunc.inst, CPrec_GetTypePatch(TYPE(act->u.memberfunc.inst))); CPrec_NewPointerPatch(¤t->u.memberfunc.tmemb, CPrec_GetTemplateMemberPatch(act->u.memberfunc.tmemb)); break; case CI_ActionTemplateFunc: CPrec_NewPointerPatch(¤t->u.templatefunc.func, CPrec_GetTemplateFunctionPatch(act->u.templatefunc.func)); CPrec_NewPointerPatch(¤t->u.templatefunc.inst, CPrec_GetTemplFuncInstancePatch(act->u.templatefunc.inst)); break; case CI_ActionDefaultFunc: break; default: CError_FATAL(4177); } if (!act->next) break; next = CPrec_AppendAlign(); CPrec_NewPointerPatch(¤t->next, next); current = next; act = act->next; } return first; } static void CPrec_GenerateBuiltinPatches(void) { int x; int y; Patch *scan; for (x = 0; x < cprec_builtins; x++) { y = 0; for (scan = cprec_builtin[x].patches; scan; scan = scan->next) ++y; if (y) { CPrec_AppendWord32(y); CPrec_AppendWord32(x); for (scan = cprec_builtin[x].patches; scan; scan = scan->next) CPrec_AppendWord32(scan->offset); } } CPrec_AppendWord32(0); } static void CPrec_GenerateTokenStreamPatches(void) { TokenPatch *scan; for (scan = cprec_tokenpatches; scan; scan = scan->next) { CPrec_AppendWord32((UInt32) scan->tokens); CPrec_AppendWord32((UInt32) scan->count); } CPrec_AppendWord32(0); } static OSErr CPrec_CompressWrite(const char *data, SInt32 size) { char buf[2048 + 256]; OSErr err; int bufpos = 0; int blockstart; int c; const char *p = data; const char *end = data + size; for (;;) { if (p < end) { if (!*p) { c = 224; while (!*p && p < end && c < 256) { c++; p++; } buf[bufpos++] = c - 1; } else { blockstart = bufpos++; c = 0; while (p < end && c < 224) { if (!p[0] && !p[1]) { break; } else { buf[bufpos++] = *(p++); c++; } } buf[blockstart] = c - 1; } } if (p >= end || bufpos > 2048) { if ((err = COS_FileWrite(cprec_refnum, buf, bufpos))) return err; if (p >= end) break; else bufpos = 0; } } return noErr; } static OSErr CPrec_FlushRawBuffer(void) { OSErr err; if (cprec_dowrite) { CPrec_AppendAlign(); cprec_zero_offset += cprec_glist.size; COS_LockHandle(cprec_glist.data); err = CPrec_CompressWrite(*cprec_glist.data, cprec_glist.size); COS_UnlockHandle(cprec_glist.data); cprec_glist.size = 0; return err; } else { return noErr; } } static OSErr CPrec_FlushBufferCheck(void) { static SInt32 flushmax; OSErr err; if (cprec_glist.size > flushmax) flushmax = cprec_glist.size; if (cprec_glist.size > 10000) { err = CPrec_FlushRawBuffer(); if (err) { cprec_ioerror = err; return err; } } return noErr; } static int CPrec_CompressPatches(void) { Patch *scan; int count; SInt32 last; cprec_glist.size = 0; scan = cprec_patch_list; last = 0; count = 0; while (scan) { CError_ASSERT(4339, (scan->offset & 0x80000001) == 0); if ((scan->offset - last) >= -128 && (scan->offset - last) <= 126) CPrec_AppendByte(((scan->offset - last) >> 1) | 0x80); else CPrec_AppendWord32(scan->offset); last = scan->offset; scan = scan->next; count++; } return count; } static OSErr CPrec_DumpColorSymbolTable(Boolean doWrite) { OSErr err; freelheap(); CPrec_InitAddressHashTable(); CPrec_InitPointerHashTable(); cprec_patch_list = NULL; cprec_tokenpatches = NULL; cprec_offset = 0; cprec_zero_offset = 0; cprec_dowrite = doWrite; cprec_ioerror = noErr; CPrec_SetupBuiltIn(); CPrec_AppendWord32(0); CPrec_DumpNameTable(); if ((err = CPrec_FlushRawBuffer()) != noErr) return err; CPrec_DumpMacroTable(); if ((err = CPrec_FlushRawBuffer()) != noErr) return err; CPrec_DumpRootNameSpace(); if (doWrite) { if (cprec_ioerror != noErr) return cprec_ioerror; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (ctempl_templates) { TemplClass *p = TEMPL_CLASS(CPrec_GetTypePatch(TYPE(ctempl_templates))); if (doWrite) cprec_header->ctempl_templates = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (ctempl_templatefuncs) { TemplateFunction *p = CPrec_GetTemplateFunctionPatch(ctempl_templatefuncs); if (doWrite) cprec_header->ctempl_templatefuncs = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (csom_stubs) { CSOMStub *p = CPrec_GetSOMPatch(csom_stubs); if (doWrite) cprec_header->csom_stubs = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cprec_staticdata) { StaticData *p = CPrec_GetStaticDataPatch(cprec_staticdata); if (doWrite) cprec_header->cprec_staticdata = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (callbackactions) { CallbackAction *p = CPrec_GetCallbackPatch(callbackactions); if (doWrite) cprec_header->callbackactions = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_type_class) { Type *p = CPrec_GetTypePatch(cobjc_type_class); if (doWrite) cprec_header->cobjc_type_class = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_type_id) { Type *p = CPrec_GetTypePatch(cobjc_type_id); if (doWrite) cprec_header->cobjc_type_id = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_type_sel) { Type *p = CPrec_GetTypePatch(cobjc_type_sel); if (doWrite) cprec_header->cobjc_type_sel = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_selhashtable) { ObjCSelector **p = CPrec_GetSelHashTablePatch(cobjc_selhashtable); if (doWrite) cprec_header->cobjc_selhashtable = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_classdefs) { BClassList *p = CPrec_GetBClassListPatch(cobjc_classdefs); if (doWrite) cprec_header->cobjc_classdefs = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cobjc_protocols) { ObjCProtocol *p = CPrec_GetObjCProtocolPatch(cobjc_protocols); if (doWrite) cprec_header->cobjc_protocols = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (init_expressions) { InitExpr *p = CPrec_GetIExpressionPatch(init_expressions); if (doWrite) cprec_header->init_expressions = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } if (cinline_tactionlist) { CI_Action *p = CPrec_GetInlineActionPatch(cinline_tactionlist); if (doWrite) cprec_header->cinline_tactionlist = p; if ((err = CPrec_FlushRawBuffer()) != noErr) return err; } return noErr; } static OSErr CPrec_FileAlign(short refnum, SInt32 *len) { OSErr err; SInt32 n; char buf[8]; n = *len; if ((n & 7) == 0) return noErr; memclrw(buf, 8); err = COS_FileWrite(refnum, buf, n = 8 - (n & 7)); *len += n; return err; } static OSErr CPrec_WriteFile(void) { char str[128]; int i; HashNameNode *name; OSErr err; SInt32 offset; if (InitGList(&cprec_glist, 0x40000)) CError_NoMem(); CompilerGetCString(10, str); CWShowStatus(cparams.context, str, ""); CPrep_RemoveSpecialMacros(); for (i = 0; i < 0x800; i++) { for (name = name_hash_nodes[i]; name; name = name->next) name->id = 0; } if ((err = CPrec_DumpColorSymbolTable(0)) != noErr) return err; CompilerGetCString(11, str); CWShowStatus(cparams.context, str, ""); cprec_header = galloc(sizeof(Header)); memclrw(cprec_header, sizeof(Header)); cprec_header->magic = 0xBEEFFACE; cprec_header->version = 1047; cprec_header->target = 2; cprec_header->check_header_flags = copts.checkprecompflags; cprec_header->cplusplus = copts.cplusplus; cprec_header->uniqueID = CParser_GetUniqueID(); cprec_header->cobjc_selrefcount = cobjc_selrefcount; cprec_header->cobjc_classrefcount = cobjc_classrefcount; cprec_header->cobjc_stringcount = cobjc_stringcount; if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) return err; offset = sizeof(Header); if ((err = CPrec_DumpColorSymbolTable(1)) != noErr) return err; cprec_header->x28 = cprec_offset; cprec_header->x30 = offset; if ((err = COS_FileGetPos(cprec_refnum, &offset)) != noErr) return err; cprec_header->x2C = offset - cprec_header->x30; cprec_header->compressedPatchCount = CPrec_CompressPatches(); cprec_header->compressedPatchSize = cprec_glist.size; cprec_header->compressedPatchOffset = offset; if (cprec_header->compressedPatchCount) { if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) return err; offset += cprec_glist.size; } if ((err = CPrec_FileAlign(cprec_refnum, &offset)) != noErr) return err; cprec_glist.size = 0; CPrec_GenerateBuiltinPatches(); cprec_header->builtinPatchSize = cprec_glist.size; cprec_header->builtinPatchOffset = offset; if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) return err; offset += cprec_glist.size; if (cprec_tokenpatches) { cprec_glist.size = 0; CPrec_GenerateTokenStreamPatches(); cprec_header->tokenStreamPatchSize = cprec_glist.size; cprec_header->tokenStreamPatchOffset = offset; if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) return err; offset += cprec_glist.size; } if ((err = COS_FileSetPos(cprec_refnum, 0)) != noErr) return err; if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) return err; return noErr; } void PrecompilerWrite(void) { OSErr err; short strindex; char str[128]; FSSpec spec; spec = cparamblkptr->sourcefile; if (CWGetPrecompiledHeaderSpec(cparamblkptr->context, &spec, precomp_target_str) == cwNoErr) { strindex = 3; err = COS_FileNew(&spec, &cprec_refnum, copts.appltype, copts.headtype); if (err == noErr) { strindex = 4; err = CPrec_WriteFile(); } CleanupPrecompiler(); if (err != noErr) { CompilerGetCString(strindex, str); sprintf(string, str, err); CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); } else { CWFileTime time = 0; CWSetModDate(cparamblkptr->context, &spec, &time, 1); } } } static void CPrec_ReadData(SInt32 offset, void *buffer, SInt32 size) { if ( COS_FileSetPos(cprec_refnum, offset) != noErr || COS_FileRead(cprec_refnum, buffer, size) != noErr ) CError_ErrorTerm(CErrorStr181); } static void CPrec_ReadRawBuffer(void) { UInt8 *buffer; UInt8 *work; UInt8 *end; UInt32 size; int ch; if (!cprec_buffer) { size = cprec_header->x28 + (cprec_header->x28 >> 7) + 64; buffer = galloc(size); cprec_rawbuffer = buffer; work = buffer + size - cprec_header->x2C; CPrec_ReadData(cprec_header->x30, work, cprec_header->x2C); } else { buffer = galloc(cprec_header->x28); cprec_rawbuffer = buffer; work = (UInt8 *) cprec_buffer + cprec_header->x30; } end = work + cprec_header->x2C; while (work < end) { if ((ch = *(work++)) >= 0xE0) { ch -= 0xE0; do { *(buffer++) = 0; } while (--ch >= 0); } else { do { *(buffer++) = *(work++); } while (--ch >= 0); } } if (work != end || buffer != RESOLVE_RAW_BUFFER(cprec_header->x28)) CError_ErrorTerm(CErrorStr181); } static void CPrec_RelocateRawBuffer(void) { UInt8 *patches; UInt32 offset; UInt8 *dest; SInt32 count; UInt8 *patch; UInt32 var; if ((count = cprec_header->compressedPatchCount)) { if (!cprec_buffer) { patches = lalloc(cprec_header->compressedPatchSize); CPrec_ReadData(cprec_header->compressedPatchOffset, patches, cprec_header->compressedPatchSize); } else { patches = RESOLVE_BUFFER(cprec_header->compressedPatchOffset); } offset = 0; patch = patches; dest = cprec_rawbuffer; do { if (!(*patch & 0x80)) { ((UInt8 *) &var)[0] = *(patch++); ((UInt8 *) &var)[1] = *(patch++); ((UInt8 *) &var)[2] = *(patch++); ((UInt8 *) &var)[3] = *(patch++); offset = var; } else { offset += (char) (*(patch++) * 2); } *((uintptr_t *) (dest + offset)) += (uintptr_t) dest; } while (--count > 0); freelheap(); if (patch != (patches + cprec_header->compressedPatchSize)) CError_ErrorTerm(CErrorStr181); } } static void CPrec_RelocateBuiltins(void) { UInt32 *patches; void *builtin; UInt32 count; UInt8 *buffer; if (cprec_header->builtinPatchSize) { CPrec_SetupBuiltInArray(); if (!cprec_buffer) { patches = lalloc(cprec_header->builtinPatchSize); CPrec_ReadData(cprec_header->builtinPatchOffset, patches, cprec_header->builtinPatchSize); } else { patches = RESOLVE_BUFFER(cprec_header->builtinPatchOffset); } buffer = cprec_rawbuffer; while (1) { if (!(count = *(patches++))) break; builtin = cprec_builtin_array[*(patches++)]; do { *((void **) (buffer + *(patches++))) = builtin; } while (--count); } } } static void CPrec_RelocateTokenStreams(void) { UInt32 *patches; UInt32 count; TStreamElement *tokens; UInt8 *buffer; CPrepFileInfo *file; SInt32 pos; if (cprec_header->tokenStreamPatchSize) { CPrep_GetPrepPos(&file, &pos); if (!cprec_buffer) { patches = lalloc(cprec_header->tokenStreamPatchSize); CPrec_ReadData(cprec_header->tokenStreamPatchOffset, patches, cprec_header->tokenStreamPatchSize); } else { patches = RESOLVE_BUFFER(cprec_header->tokenStreamPatchOffset); } buffer = cprec_rawbuffer; while (1) { if (!*patches) break; tokens = (TStreamElement *) (buffer + *(patches++)); count = *(patches++); while (count--) { tokens->tokenfile = file; tokens->tokenoffset = pos; tokens++; } } } } static void CPrec_RelocateMacroTable(void) { int i; int j; int count; UInt8 *buffer; Macro **prec_table; Macro **table; Macro *macro; uintptr_t offset; buffer = cprec_rawbuffer; prec_table = cprec_header->macrotable; table = macrohashtable; i = 0; do { for (macro = *table; macro; macro = macro->next) { macro->name = GetHashNameNodeExport(macro->name->name); count = macro->xC & 0x7FFF; for (j = 1; j < count; j++) macro->names[j - 1] = GetHashNameNodeExport(macro->names[j - 1]->name); } if ((offset = (uintptr_t) *prec_table)) { if (*table) { macro = (Macro *) (buffer + offset); while (macro->next) macro = macro->next; macro->next = *table; } *table = (Macro *) (buffer + offset); } prec_table++; table++; } while (++i < 0x800); } static void CPrec_RelocateTable(void **table, int size, void **dest) { int i; void *buffer = cprec_rawbuffer; for (i = 0; i < size; i++) { if (*table) *dest = (char *) buffer + (uintptr_t) *table; else *dest = NULL; table++; dest++; } } static void CPrec_RelocateRootNameSpace(void) { CError_ASSERT(4981, cscope_root->is_hash); cscope_root->names = cprec_header->root_names; CPrec_RelocateTable( (void **) cprec_header->root_nametable, 0x400, (void **) cscope_root->data.hash); } static void CPrec_FixNameIds(void) { int i; HashNameNode *node; for (i = 0; i < 2048; i++) { for (node = name_hash_nodes[i]; node; node = node->next) node->id = -1; } } static void CPrec_DefineStaticData(void) { StaticData *sd = cprec_staticdata; cprec_staticdata = NULL; while (sd) { CInit_DeclareData(sd->object, sd->buffer, sd->links, sd->size); sd = sd->next; } } void PrecompilerRead(short refnum, void *buffer) { cprec_refnum = refnum; cprec_buffer = buffer; CPrep_RemoveSpecialMacros(); if (!CScope_IsEmptySymTable()) CError_ErrorTerm(CErrorStr180); if (!cprec_buffer) { cprec_header = galloc(sizeof(Header)); CPrec_ReadData(0, cprec_header, sizeof(Header)); } else { cprec_header = cprec_buffer; } if (cprec_header->magic != 0xBEEFFACE) CError_ErrorTerm(CErrorStr181); if (cprec_header->version != 1047) CError_ErrorTerm(CErrorStr222); if (cprec_header->target != 2) CError_ErrorTerm(CErrorStr223); copts.checkprecompflags = cprec_header->check_header_flags; CPrec_ReadRawBuffer(); CPrec_RelocateRawBuffer(); CPrec_RelocateBuiltins(); CPrec_RelocateTable((void **) cprec_header->nametable, 0x800, (void **) name_hash_nodes); CPrec_FixNameIds(); CPrec_RelocateMacroTable(); CPrec_RelocateTokenStreams(); CPrec_RelocateRootNameSpace(); if (!cprec_header->usings) cscope_root->usings = NULL; else cscope_root->usings = RESOLVE_RAW_BUFFER(cprec_header->usings); ctempl_templates = RESOLVE_SAFE(cprec_header->ctempl_templates); ctempl_templatefuncs = RESOLVE_SAFE(cprec_header->ctempl_templatefuncs); csom_stubs = RESOLVE_SAFE(cprec_header->csom_stubs); cprec_staticdata = RESOLVE_SAFE(cprec_header->cprec_staticdata); callbackactions = RESOLVE_SAFE(cprec_header->callbackactions); cobjc_type_class = RESOLVE_SAFE(cprec_header->cobjc_type_class); cobjc_type_id = RESOLVE_SAFE(cprec_header->cobjc_type_id); cobjc_type_sel = RESOLVE_SAFE(cprec_header->cobjc_type_sel); cobjc_selhashtable = RESOLVE_SAFE(cprec_header->cobjc_selhashtable); cobjc_classdefs = RESOLVE_SAFE(cprec_header->cobjc_classdefs); cobjc_protocols = RESOLVE_SAFE(cprec_header->cobjc_protocols); init_expressions = RESOLVE_SAFE(cprec_header->init_expressions); cinline_tactionlist = RESOLVE_SAFE(cprec_header->cinline_tactionlist); CParser_SetUniqueID(cprec_header->uniqueID); cobjc_selrefcount = cprec_header->cobjc_selrefcount; cobjc_classrefcount = cprec_header->cobjc_classrefcount; cobjc_stringcount = cprec_header->cobjc_stringcount; cprec_refnum = 0; CleanupPrecompiler(); cscope_current = cscope_root; if (!CParser_ReInitRuntimeObjects(1)) CError_ErrorTerm(CErrorStr181); CPrep_InsertSpecialMacros(); if (cparamblkptr->precompile != 1) CPrec_DefineStaticData(); }