#include "compiler/CPrep.h" #include "compiler/CBrowse.h" #include "compiler/CCompiler.h" #include "compiler/CError.h" #include "compiler/CException.h" #include "compiler/CInt64.h" #include "compiler/CMachine.h" #include "compiler/CParser.h" #include "compiler/CPrec.h" #include "compiler/CPreprocess.h" #include "compiler/CPrepTokenizer.h" #include "compiler/CScope.h" #include "compiler/CSOM.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/FuncLevelAsmPPC.h" #include "../Optimizer/IroPointerAnalysis.h" #include "compiler/ObjGenMachO.h" #include "compiler/objects.h" #include "compiler/scopes.h" #include "compiler/tokens.h" #include "cos.h" #ifdef __MWERKS__ #pragma options align=mac68k #endif typedef struct PrepValue { CInt64 val; char is_unsigned; } PrepValue; typedef struct IfStack { CPrepFileInfo *file; SInt32 pos; short state; } IfStack; enum { IfState_0 = 0, IfState_1 = 1, IfState_2 = 2, IfState_3 = 3, IfState_4 = 4 }; // forward declarations static PrepValue CPrep_ParseCond(void); static PrepValue CPrep_ParseBinary(PrepValue *rhs, short precLimit); static char *XpandMacro(Macro *macro); static void prepmacro(Macro *macro); static void prepifskip(void); static void gotonexttoken(void); #ifdef CW_CLT extern SInt16 *CLT_filesp; extern CPrepFileInfo **CLT_filestack; #endif struct CompilerOption { char *name; short bits; } compileroptions[138] = { "little_endian", OPT_FLAG_4000 | OPT_OFFSET(littleendian), "longlong", OPT_OFFSET(longlong), "traceback", OPT_OFFSET(traceback), "disable_registers", OPT_OFFSET(disable_registers), "fp_contract", OPT_OFFSET(fp_contract), "no_common", OPT_OFFSET(no_common), "no_implicit_templates", OPT_OFFSET(no_implicit_templates), "absolutepath", OPT_OFFSET(absolutepath), "debug_listing", OPT_OFFSET(debuglisting), "profile", OPT_OFFSET(profile), "optimizewithasm", OPT_OFFSET(optimizewithasm), "use_lmw_stmw", OPT_OFFSET(use_lmw_stmw), "no_register_save_helpers", OPT_OFFSET(no_register_save_helpers), "ppc_opt_bclt_bctr", OPT_OFFSET(opt_bcc_lr_ctr), "misaligned_mem_access", OPT_OFFSET(misaligned_mem_access), "switch_tables", OPT_OFFSET(switch_tables), "prepare_compress", OPT_OFFSET(prepare_compress), "asmsemicolcomment", OPT_OFFSET(asmsemicolcomment), "asmpoundcomment", OPT_OFFSET(asmpoundcomment), "cplusplus", OPT_OFFSET(cplusplus), "ecplusplus", OPT_OFFSET(ecplusplus), "objective_c", OPT_OFFSET(objective_c), "objc_strict", OPT_OFFSET(objc_strict), "ARM_conform", OPT_OFFSET(ARMconform), "ARM_scoping", OPT_OFFSET(ARMscoping), "require_prototypes", OPT_OFFSET(checkprotos), "trigraphs", OPT_OFFSET(trigraphs), "only_std_keywords", OPT_OFFSET(onlystdkeywords), "enumsalwaysint", OPT_OFFSET(enumsalwaysint), "ANSI_strict", OPT_OFFSET(ANSIstrict), "mpwc_relax", OPT_OFFSET(mpwc_relax), "mpwc_newline", OPT_OFFSET(mpwc_newline), "ignore_oldstyle", OPT_OFFSET(ignore_oldstyle), "cpp_extensions", OPT_OFFSET(cpp_extensions), "pointercast_lvalue", OPT_OFFSET(pointercast_lvalue), "RTTI", OPT_OFFSET(RTTI), "delete_exception", OPT_OFFSET(delete_exception), "oldalignment", OPT_OFFSET(oldalignment), "multibyteaware", OPT_OFFSET(multibyteaware), "unsigned_char", OPT_OFFSET(unsigned_char), "auto_inline", OPT_OFFSET(auto_inline), "inline_bottom_up", OPT_OFFSET(inline_bottom_up), "defer_codegen", OPT_OFFSET(defer_codegen), "direct_to_som", OPT_OFFSET(direct_to_som), "SOMCheckEnvironment", OPT_OFFSET(som_env_check), "SOMCallOptimization", OPT_OFFSET(som_call_optimize), "bool", OPT_OFFSET(booltruefalse), "old_enum_mangler", OPT_OFFSET(old_enum_mangler), "longlong_enums", OPT_OFFSET(longlong_enums), "no_tfuncinline", OPT_OFFSET(no_tfuncinline), "flat_include", OPT_OFFSET(flat_include), "syspath_once", OPT_OFFSET(syspath_once), "always_import", OPT_OFFSET(always_import), "simple_class_byval", OPT_OFFSET(simple_class_byval), "wchar_type", OPT_OFFSET(wchar_type), "vbase_ctor_offset", OPT_OFFSET(vbase_ctor_offset), "vbase_abi_v2", OPT_OFFSET(vbase_abi_v2), "def_inherited", OPT_OFFSET(def_inherited), "template_patch", OPT_OFFSET(template_patch), "template_friends", OPT_OFFSET(template_friends), "faster_pch_gen", OPT_OFFSET(faster_pch_gen), "array_new_delete", OPT_OFFSET(array_new_delete), "dollar_identifiers", OPT_OFFSET(dollar_identifiers), "def_inline_tfuncs", OPT_OFFSET(def_inline_tfuncs), "arg_dep_lookup", OPT_OFFSET(arg_dep_lookup), "simple_prepdump", OPT_OFFSET(simple_prepdump), "line_prepdump", OPT_OFFSET(line_prepdump), "fullpath_prepdump", OPT_OFFSET(fullpath_prepdump), "old_mtemplparser", OPT_OFFSET(old_mtemplparser), "suppress_init_code", OPT_OFFSET(suppress_init_code), "reverse_bitfields", OPT_OFFSET(reverse_bitfields), "c9x", OPT_OFFSET(c9x), "float_constants", OPT_OFFSET(float_constants), "no_static_dtors", OPT_OFFSET(no_static_dtors), "longlong_prepeval", OPT_OFFSET(longlong_prepeval), "const_strings", OPT_OFFSET(const_strings), "dumpir", OPT_OFFSET(dumpir), "experimental", OPT_OFFSET(experimental), "gcc_extensions", OPT_OFFSET(gcc_extensions), "stdc_fp_contract", OPT_OFFSET(stdc_fp_contract), "stdc_fenv_access", OPT_OFFSET(stdc_fenv_access), "stdc_cx_limitedr", OPT_OFFSET(stdc_cx_limitedr), "old_argmatch", OPT_OFFSET(old_argmatch), "optEH", OPT_OFFSET(optEH), "optEH2", OPT_OFFSET(optEH2), "new_mangler", OPT_OFFSET(new_mangler), "microsoft_exceptions", OPT_OFFSET(microsoft_EH), "microsoft_RTTI", OPT_OFFSET(microsoft_EH), "warning_errors", OPT_OFFSET(warningerrors), "extended_errorcheck", OPT_OFFSET(pedantic), "check_header_flags", OPT_OFFSET(checkprecompflags), "supress_warnings", OPT_OFFSET(supress_warnings), "warn_illpragma", OPT_OFFSET(warn_illpragma), "warn_emptydecl", OPT_OFFSET(warn_emptydecl), "warn_possunwant", OPT_OFFSET(warn_possunwant), "warn_unusedvar", OPT_OFFSET(warn_unusedvar), "warn_unusedarg", OPT_OFFSET(warn_unusedarg), "warn_extracomma", OPT_OFFSET(warn_extracomma), "warn_hidevirtual", OPT_OFFSET(warn_hidevirtual), "warn_largeargs", OPT_OFFSET(warn_largeargs), "warn_implicitconv", OPT_OFFSET(warn_implicitconv), "warn_notinlined", OPT_OFFSET(warn_notinlined), "warn_structclass", OPT_OFFSET(warn_structclass), "warn_padding", OPT_OFFSET(warn_padding), "warn_no_side_effect", OPT_OFFSET(warn_no_side_effect), "warn_resultnotused", OPT_OFFSET(warn_resultnotused), "warn_ptr_int_conv", OPT_OFFSET(warn_ptr_int_conv), "align_array_members", OPT_OFFSET(alignarraymembers), "dont_reuse_strings", OPT_OFFSET(dont_reuse_strings), "pool_strings", OPT_OFFSET(poolstrings), "explicit_zero_data", OPT_OFFSET(explicit_zero_data), "readonly_strings", OPT_OFFSET(readonly_strings), "opt_common_subs", OPT_OFFSET(commonsubs), "opt_loop_invariants", OPT_OFFSET(loopinvariants), "opt_propagation", OPT_OFFSET(propagation), "opt_unroll_loops", OPT_OFFSET(unrolling), "opt_lifetimes", OPT_OFFSET(lifetimes), "opt_strength_reduction", OPT_OFFSET(strengthreduction), "opt_strength_reduction_strict", OPT_OFFSET(strengthreductionstrict), "opt_dead_code", OPT_OFFSET(deadcode), "opt_dead_assignments", OPT_OFFSET(deadstore), "opt_vectorize_loops", OPT_OFFSET(vectorizeloops), "opt_pointer_analysis", OPT_OFFSET(opt_pointer_analysis), "exceptions", OPT_OFFSET(exceptions), "dont_inline", OPT_OFFSET(dontinline), "always_inline", OPT_OFFSET(alwaysinline), "optimize_for_size", OPT_OFFSET(optimizesize), "peephole", OPT_OFFSET(peephole), "global_optimizer", OPT_OFFSET(globaloptimizer), "side_effects", OPT_OFFSET(sideeffects), "internal", OPT_FLAG_2000 | OPT_OFFSET(cfm_internal), "import", OPT_FLAG_2000 | OPT_OFFSET(cfm_import), "export", OPT_FLAG_2000 | OPT_OFFSET(cfm_export), "lib_export", OPT_FLAG_2000 | OPT_OFFSET(cfm_lib_export), "nosyminline", OPT_OFFSET(nosyminline), "force_active", OPT_OFFSET(force_active), "sym", OPT_OFFSET(filesyminfo), NULL, 0 }; CompilerLinkerParamBlk *cparamblkptr; short tk; CInt64 tkintconst; Float tkfloatconst; char *tkstring; HashNameNode *tkidentifier; SInt32 tksize; short ispascalstring; short nlflag; SInt32 lines; Boolean spaceskip; Macro **macrohashtable; Boolean cprep_nomem_exit; Boolean cprep_nostring; Boolean cprep_eoltokens; static IfStack ifstack[64]; static short iflevel; TokenStack tokenstack[128]; short tokenstacklevel; CPrepFileInfo *cprep_cursymfile; char *pos; char *macropos; char *nextcharpos; unsigned char CPrep_SkipNewCommentChar; Boolean preprocessing_only; Handle stringmem; SInt32 maxstringsize; char cprep_idarray[256]; Boolean was_escchar; Boolean macrocheck; Boolean widestring; Boolean at_linestart; char *prep_file_start; char *prep_file_end; char *macrostart; Boolean cprep_strconcat; CPrepFileInfo *prep_file; short filesp; SInt32 linenumber; static CPrepFileInfo *filestack[32]; typedef struct CPrepFileInfoList { struct CPrepFileInfoList *next; CPrepFileInfo *fileinfo; } CPrepFileInfoList; static CPrepFileInfoList *cprep_files; static UInt32 linetick; static Boolean waslockedmacro; static Boolean include_once; static time_t now_time; static SInt32 lineoffset; static Boolean was_prep_error; static Boolean cprep_hasprepline; static Boolean cprep_incondexpr; struct PackStack { HashNameNode *identifier; short align_mode; }; static struct PackStack cprep_packstack[128]; static short cprep_packstackp; static Macro lineM; static Macro fileM; static Macro dateM; static Macro timeM; static Macro stdcM; static Macro stcvM; static Macro stchM; static Macro casmM; static Macro cpplM; static Macro MWRSM; static Macro dtsomM; static Macro ecppM; static Macro optiM; static Macro trgtM; GList pplist; struct COptsPush { struct COptsPush *next; CompilerLinkerOptions opts; }; struct COptPush { struct COptPush *next; SInt32 id; Boolean x8; UInt8 value; }; static struct COptsPush *coptpushs; static struct COptPush *coptpush; static CompilerLinkerOptions *coptssave; static Boolean dofreeaheap; static GList mlist; static Handle ts_buffer; static TStreamElement *ts_first; TStreamElement *ts_last; TStreamElement *ts_current; static SInt32 ts_elements; SInt32 ts_preread_elements; static SInt32 gDirectiveStart; static SInt32 high_mem_mark; static short exprtk; #ifdef __MWERKS__ #pragma options align=reset #endif static void cannotopenerror(StringPtr filename, Boolean err) { static char fname[64]; short len = filename[0]; if (len > 63) len = 63; memcpy(fname, filename + 1, len); fname[len] = 0; CError_ResetErrorSkip(); if (prep_file) { was_prep_error = 1; CError_Error(CErrorStr151, fname); if (err) longjmp(errorreturn, 1); } else { CError_CannotOpen(); } } static void insertmacro(Macro *macro) { macro->next = macrohashtable[macro->name->hashval]; macrohashtable[macro->name->hashval] = macro; macro->xF = 0; } void CPrep_InsertSpecialMacro(Macro *macro, char *name) { macro->name = GetHashNameNodeExport(name); macro->is_special = 1; insertmacro(macro); } void CPrep_InsertSpecialMacros(void) { CPrep_InsertSpecialMacro(&lineM, "__LINE__"); CPrep_InsertSpecialMacro(&fileM, "__FILE__"); CPrep_InsertSpecialMacro(&dateM, "__DATE__"); CPrep_InsertSpecialMacro(&timeM, "__TIME__"); CPrep_InsertSpecialMacro(&stdcM, "__STDC__"); CPrep_InsertSpecialMacro(&stcvM, "__STDC_VERSION__"); CPrep_InsertSpecialMacro(&stchM, "__STDC_HOSTED__"); CPrep_InsertSpecialMacro(&casmM, "__CASM__"); CPrep_InsertSpecialMacro(&cpplM, "__cplusplus"); CPrep_InsertSpecialMacro(&MWRSM, "__MWERKS__"); CPrep_InsertSpecialMacro(&dtsomM, "__SOM_ENABLED__"); CPrep_InsertSpecialMacro(&ecppM, "__embedded_cplusplus"); CPrep_InsertSpecialMacro(&optiM, "__option"); CPrep_InsertSpecialMacro(&trgtM, "__ide_target"); CodeGen_InsertSpecialMacros(); } void CPrep_RemoveSpecialMacros(void) { Macro **scan; int x; for (x = 0; x < 2048; x++) { scan = ¯ohashtable[x]; while (*scan) { if ((*scan)->is_special) { *scan = (*scan)->next; } else { scan = &(*scan)->next; } } } } static void CPrep_Reconfig(void) { cprep_idarray['$'] = copts.dollar_identifiers != 0; } Boolean setupprep(void) { int x; now_time = time(NULL); lineoffset = 0; include_once = 0; cprep_eoltokens = 0; cprep_nostring = 0; cprep_incondexpr = 0; filesp = -1; linetick = 0; lines = 0; dofreeaheap = 1; macrocheck = 1; maxstringsize = 256; iflevel = 0; tokenstacklevel = 0; cprep_cursymfile = 0; cprep_files = 0; #ifdef CW_CLT CLT_filesp = &filesp; CLT_filestack = filestack; #endif anyerrors = 0; fatalerrors = 0; was_prep_error = 0; cprep_strconcat = 0; GListErrorProc = CError_NoMem; mlist.data = NULL; pplist.data = NULL; if (InitGList(&mlist, 10000)) CError_NoMem(); if (!(stringmem = COS_NewHandle(256))) CError_NoMem(); if (!(ts_buffer = COS_NewHandle(1024 * sizeof(TStreamElement)))) CError_NoMem(); COS_LockHandleHi(ts_buffer); ts_first = (TStreamElement *) *ts_buffer; ts_last = ts_first + 1023; ts_current = ts_first; ts_elements = 1024; ts_preread_elements = 0; macrohashtable = galloc(sizeof(Macro *) * 2048); memclrw(macrohashtable, sizeof(Macro *) * 2048); CPrep_InsertSpecialMacros(); for (x = 0; x < 256; x++) cprep_idarray[x] = 0; for (x = 'a'; ; x++) { cprep_idarray[x] = 1; if (x == 'z') break; } for (x = 'A'; ; x++) { cprep_idarray[x] = 1; if (x == 'Z') break; } for (x = '0'; ; x++) { cprep_idarray[x] = 2; if (x == '9') break; } cprep_idarray['_'] = 1; CPrep_Reconfig(); return 0; } void cleanupprep(void) { while (filesp >= 0) popfile(); high_mem_mark = CTool_TotalHeapSize(); releaseheaps(); GListErrorProc = NULL; FreeGList(&mlist); FreeGList(&pplist); if (stringmem) { COS_FreeHandle(stringmem); stringmem = NULL; } if (ts_buffer) { COS_FreeHandle(ts_buffer); ts_buffer = NULL; } ts_current = NULL; ts_first = ts_last = NULL; } static char *getfiledata(FSSpec *spec) { const char *text; SInt32 textlength; short filedatatype; if (CWGetFileText(cparamblkptr->context, spec, &text, &textlength, &filedatatype) != cwNoErr) { Str255 filename; COS_FileGetFSSpecInfo(spec, NULL, NULL, filename); cannotopenerror(filename, 1); return NULL; } else { return (char *) text; } } static Boolean setupfile(StringPtr filename, Boolean flag1, Boolean flag2) { CPrepFileInfo prepinfo; CWFileInfo fileinfo; Str255 file_filename; char myfilename[256]; OSType file_type; SInt32 file_size; SInt32 file_dirid; void *cache; CWMemHandle cache_hnd; SInt16 refnum; SInt16 file_vrefnum; char *extpos; char *src; char *append; char *dst; int len; if (filesp >= 31) { was_prep_error = 1; CError_ErrorTerm(CErrorStr243); return 0; } memclrw(&prepinfo, sizeof(CPrepFileInfo)); prepinfo.unkfield126 = !flag1; if (filename) { memclrw(&fileinfo, sizeof(CWFileInfo)); fileinfo.fullsearch = flag1; fileinfo.dependencyType = cwNormalDependency; fileinfo.isdependentoffile = -1; memcpy(myfilename, &filename[1], filename[0]); myfilename[filename[0]] = 0; if (CWFindAndLoadFile(cparamblkptr->context, myfilename, &fileinfo) != cwNoErr) { if (filename[0] + strlen(".framework/Headers") < 255) { if ((extpos = strchr(myfilename, '/'))) { src = (char *) filename + 1; append = ".framework/Headers"; dst = myfilename; len = filename[0]; while (dst < extpos) { *(dst++) = *(src++); len--; } while (*append) { *(dst++) = *(append++); } while (len) { *(dst++) = *(src++); len--; } *dst = 0; if (CWFindAndLoadFile(cparamblkptr->context, myfilename, &fileinfo) != cwNoErr) { cannotopenerror(filename, 0); return 0; } } else { cannotopenerror(filename, 0); return 0; } } else { cannotopenerror(filename, 0); return 0; } } if ((flag2 || include_once) && fileinfo.alreadyincluded) return 1; prepinfo.textfile = fileinfo.filespec; prepinfo.nameNode = CTool_GetPathName(&fileinfo.filespec, &prepinfo.fileModDate); if (fileinfo.filedata) { if (fileinfo.filedatatype == cwFileTypeText) { prepinfo.textbuffer = (char *) fileinfo.filedata; prepinfo.textlength = fileinfo.filedatalength; prepinfo.fileID = fileinfo.fileID; prepinfo.recordbrowseinfo = fileinfo.recordbrowseinfo; } else if (fileinfo.filedatatype == cwFileTypePrecompiledHeader) { PrecompilerRead(0, (void *) fileinfo.filedata); return 1; } else { cannotopenerror(filename, 0); return 0; } } else { COS_FileGetFSSpecInfo(&prepinfo.textfile, &file_vrefnum, &file_dirid, file_filename); if (COS_FileOpen(&prepinfo.textfile, &refnum)) { cannotopenerror(filename, 0); return 0; } if (COS_FileGetType(&prepinfo.textfile, &file_type) || COS_FileGetSize(refnum, &file_size)) { COS_FileClose(refnum); cannotopenerror(filename, 0); return 0; } if (file_type == copts.headtype) { if (cparamblkptr->caching_includes) { if (CWAllocMemHandle(cparamblkptr->context, file_size, 1, &cache_hnd) != cwNoErr) { if (CWAllocMemHandle(cparamblkptr->context, file_size, 0, &cache_hnd) != cwNoErr) { COS_FileClose(refnum); CError_NoMem(); } } CWLockMemHandle(cparamblkptr->context, cache_hnd, 0, &cache); if (COS_FileRead(refnum, cache, file_size)) { COS_FileClose(refnum); CWFreeMemHandle(cparamblkptr->context, cache_hnd); cannotopenerror(filename, 0); return 0; } COS_FileClose(refnum); CWCachePrecompiledHeader(cparamblkptr->context, &prepinfo.textfile, cache_hnd); PrecompilerRead(0, cache); CWUnlockMemHandle(cparamblkptr->context, cache_hnd); return 1; } else { PrecompilerRead(refnum, 0); COS_FileClose(refnum); return 1; } } else { COS_FileClose(refnum); cannotopenerror(filename, 0); return 0; } } } else { if (!cparamblkptr->sourcetext) { COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, &file_vrefnum, &file_dirid, file_filename); cannotopenerror(file_filename, 1); return 0; } prepinfo.textfile = cparamblkptr->sourcefile; prepinfo.textbuffer = (char *) cparamblkptr->sourcetext; prepinfo.textlength = cparamblkptr->sourcetextsize; prepinfo.fileID = cparamblkptr->browserfileID; prepinfo.recordbrowseinfo = cparamblkptr->recordbrowseinfo; } if (filesp >= 0) { filestack[filesp]->linenumber = linenumber; filestack[filesp]->hasprepline = cprep_hasprepline; filestack[filesp]->pos = pos - filestack[filesp]->textbuffer; } pos = prepinfo.textbuffer; linenumber = 1; at_linestart = 1; filestack[++filesp] = galloc(sizeof(CPrepFileInfo)); *filestack[filesp] = prepinfo; prep_file = filestack[filesp]; prep_file_start = prep_file->textbuffer; prep_file_end = prep_file->textbuffer + prep_file->textlength; if (preprocessing_only && !copts.simple_prepdump) CPrep_PreprocessDumpFileInfo(1); return 1; } void CPrep_TSBufferGrow(int amount) { int current_offset = ts_current - ts_first; COS_UnlockHandle(ts_buffer); if (!COS_ResizeHandle(ts_buffer, sizeof(TStreamElement) * (ts_elements + amount))) CError_NoMem(); COS_LockHandleHi(ts_buffer); ts_elements += amount; ts_first = (TStreamElement *) *ts_buffer; ts_last = ts_first + (ts_elements - 1); ts_current = ts_first + current_offset; } void CPrep_TokenStreamGetState(SInt32 *state) { *state = ts_current - ts_first; } void CPrep_TokenStreamSetState(SInt32 *state) { ts_preread_elements += ts_current - ts_first - *state; ts_current = ts_first + *state; } void CPrep_UnLex(void) { ++ts_preread_elements; --ts_current; CError_ASSERT(900, ts_current >= ts_first); } void CPrep_TokenStreamSetCurState(SInt32 *state) { ts_preread_elements += ts_current - ts_first - (*state - 1); ts_current = ts_first + (*state - 1); tk = lex(); } static SInt32 CPrep_StreamSkipToBrace(CPrepStreamFuncPtr func, SInt32 val) { TStreamElement ts; SInt32 v = val + 1; do { switch (lex()) { case '{': return v; case 0: case ';': return 0; case TK_IDENTIFIER: if (func) { ts = ts_current[-1]; func(&ts); ts_current[-1] = ts; tk = ts.tokentype; } break; } v++; } while (1); } static SInt32 CPrep_StreamSkipBlock(CPrepStreamFuncPtr func, SInt32 val) { TStreamElement ts; SInt32 brace_level; char save_asmpoundcomment; char save_cplusplus; char starttoken; char endtoken; SInt32 level; SInt32 v; SInt16 t; save_asmpoundcomment = copts.asmpoundcomment; save_cplusplus = copts.cplusplus; level = 0; brace_level = 1; v = val + 1; loop: v++; switch ((t = lex())) { case 0: return 0; case TK_ASM: cprep_nostring = 1; v++; t = lex(); if ((t == TK_VOLATILE) || ((t == TK_IDENTIFIER) && !strcmp(tkidentifier->name, "__volatile__"))) { v++; t = lex(); } if (!t) return 0; if (t == TK_EOL) { t = lex(); v++; } if (t == '(') { starttoken = '('; endtoken = ')'; } else if (t == '{') { starttoken = '{'; endtoken = '}'; brace_level++; } level = 1; in_assembler = 1; v++; t = lex(); if (t == '"') { copts.cplusplus = 0; copts.asmpoundcomment = 1; goto loop; } if (t) goto loop; return 0; case '(': if (starttoken == t) level++; goto loop; case ')': if (level && endtoken == t && !--level) { cprep_nostring = 0; in_assembler = 0; copts.cplusplus = save_cplusplus; copts.asmpoundcomment = save_asmpoundcomment; } goto loop; case TK_IDENTIFIER: if (func) { ts = ts_current[-1]; func(&ts); ts_current[-1] = ts; tk = ts.tokentype; } goto loop; case '{': brace_level++; if (starttoken == t) level++; goto loop; case '}': if (level && endtoken == t && !--level) { cprep_nostring = 0; in_assembler = 0; copts.cplusplus = save_cplusplus; copts.asmpoundcomment = save_asmpoundcomment; } if (--brace_level > 0) goto loop; break; default: goto loop; } return v; } void CPrep_StreamGetBlock(TokenStream *stream, CPrepStreamFuncPtr func, int arg) { Boolean save_eoltokens; Boolean tryflag; SInt32 start_offset; SInt32 count; start_offset = ts_current - ts_first - 1; tryflag = 0; stream->tokens = 0; stream->firsttoken = NULL; count = 0; save_eoltokens = cprep_eoltokens; cprep_eoltokens = 1; switch (tk) { case TK_TRY: tryflag = 1; case ':': if (!(count = CPrep_StreamSkipToBrace(func, 0))) { CError_Error(CErrorStr121); cprep_eoltokens = save_eoltokens; return; } case '{': break; default: CError_Error(CErrorStr121); cprep_eoltokens = save_eoltokens; return; } if (!(count = CPrep_StreamSkipBlock(func, count))) { CError_Error(CErrorStr121); cprep_eoltokens = save_eoltokens; return; } if (tryflag) { tryloop: switch (lex()) { case TK_EOL: count++; goto tryloop; case TK_CATCH: if (!(count = CPrep_StreamSkipToBrace(func, count)) || !(count = CPrep_StreamSkipBlock(func, count))) { CError_Error(CErrorStr242); cprep_eoltokens = save_eoltokens; return; } if (lookahead_noeol() == TK_CATCH) goto tryloop; break; default: CError_Error(CErrorStr242); cprep_eoltokens = save_eoltokens; return; } } cprep_eoltokens = save_eoltokens; stream->tokens = count; stream->firsttoken = galloc(count * sizeof(TStreamElement)); memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement)); } void CPrep_StreamGetSemicolon(TokenStream *stream, CPrepStreamFuncPtr func) { SInt32 count; SInt32 start_offset; Boolean save_eoltokens; start_offset = ts_current - ts_first - 1; save_eoltokens = cprep_eoltokens; cprep_eoltokens = 1; stream->tokens = 0; stream->firsttoken = NULL; count = 1; while (tk && tk != ';') { tk = lex(); if ((tk == TK_IDENTIFIER) && func) { func(&ts_current[-1]); tk = ts_current[-1].tokentype; } count++; } stream->tokens = count; stream->firsttoken = galloc(count * sizeof(TStreamElement)); memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement)); cprep_eoltokens = save_eoltokens; } void CPrep_StreamGetTemplate(TokenStream *stream, CPrepStreamFuncPtr func) { SInt32 count; SInt32 start_offset; Boolean save_eoltokens; SInt16 level; start_offset = ts_current - ts_first - 1; save_eoltokens = cprep_eoltokens; cprep_eoltokens = 1; stream->tokens = 0; stream->firsttoken = NULL; count = 0; loop: switch (tk) { case 0: CError_ErrorTerm(CErrorStr102); case '}': CError_Error(CErrorStr229); return; case ';': count++; break; case TK_IDENTIFIER: if (func) { func(&ts_current[-1]); tk = ts_current[-1].tokentype; } default: count++; tk = lex(); goto loop; case '{': level = 0; do { count++; switch (tk) { case TK_IDENTIFIER: if (func) { func(&ts_current[-1]); tk = ts_current[-1].tokentype; } break; case '{': level++; break; case '}': level--; break; } if (level <= 0) break; if (!(tk = lex())) CError_ErrorTerm(CErrorStr102); } while (1); if (lookahead() == ';') { tk = lex(); count++; } } stream->tokens = count; stream->firsttoken = galloc(count * sizeof(TStreamElement)); memcpy(stream->firsttoken, ts_first + start_offset, count * sizeof(TStreamElement)); cprep_eoltokens = save_eoltokens; } void CPrep_StreamInsert(TokenStream *stream, SInt32 *state) { if (ts_preread_elements + (ts_current - ts_first) + stream->tokens >= ts_elements) CPrep_TSBufferGrow(stream->tokens); if (ts_preread_elements) memmove(ts_current + stream->tokens, ts_current, sizeof(TStreamElement) * ts_preread_elements); memcpy(ts_current, stream->firsttoken, sizeof(TStreamElement) * stream->tokens); ts_preread_elements += stream->tokens; CPrep_TokenStreamGetState(state); } void CPrep_StreamRemove(TokenStream *stream, SInt32 *state) { TStreamElement *end; SInt32 amount; end = ts_first + *state; amount = ts_preread_elements + ((ts_current - ts_first) - *state - stream->tokens); if (amount >= 0) { if (amount) memmove(end, end + stream->tokens, sizeof(TStreamElement) * amount); ts_current = end; ts_preread_elements = amount; } } void CPrep_RemoveTokens(SInt32 amount) { CError_ASSERT(1296, ts_preread_elements >= amount); ts_preread_elements -= amount; memmove(ts_current, ts_current + amount, sizeof(TStreamElement) * ts_preread_elements); } void CPrep_TokenStreamFlush(void) { if (!ts_preread_elements) ts_current = ts_first; } static short CPrep_TokenSize(char *str) { short len; int c; if ((str[0] >= 'a' && str[0] <= 'z') || (str[0] >= 'A' && str[0] <= 'Z') || (str[0] == '_')) { len = 1; str++; do { c = *(str++); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_')) len++; else break; } while (1); return len; } switch (str[0]) { case '*': if (str[1] == '=') return 2; break; case '/': if (str[1] == '=' || str[1] == '*' || str[1] == '/') return 2; break; case '%': if (str[1] == '=') return 2; break; case '+': if (str[1] == '=' || str[1] == '+') return 2; break; case '-': if (str[1] == '>') { if (str[2] == '*') return 3; else return 2; } if (str[1] == '=' || str[1] == '-') return 2; break; case '<': if (str[1] == '=') return 2; if (str[1] == '<') { if (str[2] == '=') return 3; else return 2; } break; case '>': if (str[1] == '=') return 2; if (str[1] == '>') { if (str[2] == '=') return 3; else return 2; } break; case '&': if (str[1] == '=' || str[1] == '&') return 2; break; case '^': if (str[1] == '=') return 2; break; case '|': if (str[1] == '=' || str[1] == '|') return 2; break; case '=': if (str[1] == '=') return 2; break; case '!': if (str[1] == '=') return 2; break; case '.': if (str[1] == '.' && str[2] == '.') return 3; if (str[1] == '*') return 2; break; case ':': if (str[1] == ':') return 2; break; } return 1; } TStreamElement *CPrep_CurStreamElement(void) { static TStreamElement dummyelement; if (ts_first < ts_current) return ts_current - 1; else return &dummyelement; } void CPrep_GetTokenContext(TStreamElement *token, CPrepFileInfo **tokenfile, SInt32 *selectionoffset, short *tokensize, SInt32 *plinenumber, char *buf1, short *tokenoffset, short *tokenlength, char *buf2, short *lastarg) { // misassigned registers SInt32 p; TStreamElement *prevtoken; char *filedata; char *tokendata; Boolean hasowndata; SInt32 line; SInt32 i; char *r4; int r5; int r6; char *r7; const char *r5x; SInt16 c; if (token && !token->tokenfile) token = NULL; prevtoken = token; if (!token && ts_first < ts_current) prevtoken = ts_current - 1; if (prevtoken && !prevtoken->tokenfile) CError_FATAL(1454); if (was_prep_error || !prevtoken) { if (!prep_file) CError_CannotOpen(); *tokenfile = prep_file; if (!tokenstacklevel) { p = pos - prep_file_start; if (was_prep_error && p > 0) p--; } else { p = tokenstack[0].pos - prep_file_start; } *selectionoffset = p; } else { *tokenfile = prevtoken->tokenfile; p = prevtoken->tokenoffset; *selectionoffset = p; } filedata = (*tokenfile)->textbuffer; if (!filedata) { filedata = getfiledata(&(*tokenfile)->textfile); hasowndata = 1; } else { hasowndata = 0; } if (!cprep_hasprepline) { line = 1; for (i = 0; i < p; i++) { if (filedata[i] == 13) line++; } *plinenumber = line; } else { *plinenumber = linenumber; } tokendata = filedata + p; *tokensize = CPrep_TokenSize(tokendata); if (!token && tokenstacklevel == 1) { r4 = macrostart; r7 = macropos; } else { r4 = filedata; r7 = tokendata; } *tokenoffset = 0; r5 = 1; while (r5 < 80 && (r7 - r5) >= r4 && r7[-r5] != 13) r5++; r5--; while ((c = r7[-r5]) && (c == ' ' || c == '\t' || c == TK_4)) r5--; r6 = 0; while ((c = r7[-r5]) != 13 && c && r6 < 126) { if (!r5) *tokenoffset = r6; if (c != TK_4) { if (c == '\t') c = ' '; buf1[r6++] = c; } r5--; } if (!r5) { buf1[r6] = ' '; *tokenoffset = r6; buf1[r6 + 1] = 0; *tokenlength = 1; } else { buf1[r6] = 0; *tokenlength = CPrep_TokenSize(buf1 + *tokenoffset); } if (p > 16) { r5x = tokendata - 16; *lastarg = 16; } else { r5x = filedata; *lastarg = p; } for (i = 0; i < 31 && r5x[i]; i++) { buf2[i] = r5x[i]; } buf2[i] = 0; if (hasowndata) CWReleaseFileText(cparamblkptr->context, filedata); was_prep_error = 0; } void CPrep_Error(short code) { Boolean save = in_assembler; in_assembler = 0; if (code == 102 && (tokenstacklevel > 0 || pos < prep_file_end)) code = 105; was_prep_error = 1; CError_Error(code); in_assembler = save; } void CPrep_ErrorName(short code, const char *name) { Boolean save = in_assembler; in_assembler = 0; was_prep_error = 1; if (code == 102 && (tokenstacklevel > 0 || pos < prep_file_end)) CError_Error(CErrorStr105, name); else CError_Error(code, name); in_assembler = save; } void CPrep_Warning(short code) { Boolean save = in_assembler; in_assembler = 0; was_prep_error = 1; CError_Warning(code); in_assembler = save; } void CPrep_WarningName(short code, const char *name) { Boolean save = in_assembler; in_assembler = 0; was_prep_error = 1; CError_Warning(code, name); in_assembler = save; } void CPrep_ErrorMessage(int errTable, char *str, Boolean flag1, Boolean flag2) { Boolean save = in_assembler; in_assembler = 0; was_prep_error = 1; CError_ErrorMessage(errTable, str, flag1, flag2); in_assembler = save; } void CPrep_ErrorMessageVA(int code, const char *format, va_list list, Boolean flag1, Boolean flag2) { Boolean save = in_assembler; in_assembler = 0; was_prep_error = 1; CError_ErrorMessageVA(code, format, list, flag1, flag2); in_assembler = save; } void popfile(void) { CPrepFileInfo *file; if (filesp >= 0) { CWReleaseFileText(cparamblkptr->context, prep_file->textbuffer); prep_file->textbuffer = NULL; if (--filesp >= 0) { file = filestack[filesp]; prep_file = file; prep_file_start = file->textbuffer; prep_file_end = file->textbuffer + file->textlength; pos = prep_file_start + file->pos; linenumber = file->linenumber; cprep_hasprepline = file->hasprepline; at_linestart = 1; } if (preprocessing_only && !copts.simple_prepdump) CPrep_PreprocessDumpFileInfo(1); } } static SInt32 prepoffset(void) { if (filesp > 0) return filestack[0]->pos; else if (tokenstacklevel) return tokenstack[0].pos - filestack[filesp]->textbuffer; else return pos - filestack[0]->textbuffer; } static SInt32 prepoffset2(void) { return lineoffset; } void CPrep_SetSourceFile(FileOffsetInfo *foi) { CPrepFileInfoList *list; if (foi->file) { if (foi->file == filestack[0]) { if (cprep_cursymfile) { if (cparamblkptr->precompile != 1) ObjGen_SrcBreakName(NULL, 0, 0); cprep_cursymfile = NULL; } } else { if (cprep_cursymfile != foi->file) { for (list = cprep_files; list; list = list->next) { if (foi->file == list->fileinfo) { if (cparamblkptr->precompile != 1) ObjGen_SrcBreakName(list->fileinfo->nameNode, list->fileinfo->fileModDate, 0); cprep_cursymfile = foi->file; return; } } list = galloc(sizeof(CPrepFileInfoList)); list->next = cprep_files; cprep_files = list; list->fileinfo = foi->file; if (cparamblkptr->precompile != 1) ObjGen_SrcBreakName(list->fileinfo->nameNode, list->fileinfo->fileModDate, 1); cprep_cursymfile = foi->file; } } } } HashNameNode *CPrep_GetSourceFilePath(CPrepFileInfo *fileinfo) { HashNameNode *node; if ((node = fileinfo->nameNode) == NULL) node = CTool_GetPathName(&fileinfo->textfile, NULL); return node; } void CPrep_NewFileOffsetInfo(FileOffsetInfo *foi, TStreamElement *ts) { if (!ts || !ts->tokenfile) { if (ts_first < ts_current) { foi->file = ts_current[-1].tokenfile; foi->tokenline = ts_current[-1].tokenline; foi->tokenoffset = ts_current[-1].tokenoffset; } else { foi->file = filestack[filesp]; foi->tokenline = linenumber; if (tokenstacklevel) foi->tokenoffset = tokenstack[0].pos - filestack[filesp]->textbuffer; else foi->tokenoffset = pos - filestack[filesp]->textbuffer; } } else { foi->file = ts->tokenfile; foi->tokenline = ts->tokenline; foi->tokenoffset = ts->tokenoffset; } foi->is_inline = 0; } SInt32 CPrep_GetFileOffsetInfo(FileOffsetInfo *foi) { SInt32 p; SInt32 i; if (ts_first < ts_current && ts_current[-1].tokenfile == foi->file) { if (ts_current[-1].tokenline > foi->tokenline) foi->tokenline = ts_current[-1].tokenline; if (ts_current[-1].tokenoffset > foi->tokenoffset) foi->tokenoffset = ts_current[-1].tokenoffset; } else if (foi->file == filestack[filesp]) { if (linenumber > foi->tokenline) foi->tokenline = linenumber; if (tokenstacklevel) p = tokenstack[0].pos - filestack[filesp]->textbuffer; else p = pos - filestack[filesp]->textbuffer; if (p > foi->tokenoffset) foi->tokenoffset = p; } else { for (i = filesp - 1; i >= 0; i--) { if (foi->file == filestack[i]) { if (filestack[i]->linenumber > foi->tokenline) foi->tokenline = filestack[i]->linenumber; if (filestack[i]->pos > foi->tokenoffset) foi->tokenoffset = filestack[i]->pos; break; } } } return foi->tokenline; } void CPrep_GetFileOffsetInfo2(FileOffsetInfo *foi, SInt32 *pLine, HashNameNode **pName) { SInt32 p; SInt32 i; if (ts_first < ts_current && ts_current[-1].tokenfile == foi->file) { if (ts_current[-1].tokenline > foi->tokenline) foi->tokenline = ts_current[-1].tokenline; if (ts_current[-1].tokenoffset > foi->tokenoffset) foi->tokenoffset = ts_current[-1].tokenoffset; } else if (foi->file == filestack[filesp]) { if (linenumber > foi->tokenline) foi->tokenline = linenumber; if (tokenstacklevel) p = tokenstack[0].pos - filestack[filesp]->textbuffer; else p = pos - filestack[filesp]->textbuffer; if (p > foi->tokenoffset) foi->tokenoffset = p; } else { for (i = filesp - 1; i >= 0; i--) { if (foi->file == filestack[i]) { if (filestack[i]->linenumber > foi->tokenline) foi->tokenline = filestack[i]->linenumber; if (filestack[i]->pos > foi->tokenoffset) foi->tokenoffset = filestack[i]->pos; break; } } } *pLine = foi->tokenline; CError_ASSERT(2010, *pLine >= 0); *pName = foi->file ? foi->file->nameNode : NULL; } void CPrep_ResetFileInfo(FileOffsetInfo *foi) { // this function is empty so i can only assume... } void CPrep_GetPrepPos(CPrepFileInfo **file, SInt32 *ppos) { *file = prep_file; if (tokenstacklevel > 0) *ppos = tokenstack->pos - prep_file_start; else *ppos = pos - prep_file_start; } UInt8 C_Compiler(CompilerLinkerParamBlk *param) { TStreamElement ts; UInt8 code; CInt64_Init(); cprep_packstackp = 128; widestring = 0; cprep_nomem_exit = 0; cparamblkptr = param; prep_file = NULL; lines = 0; linenumber = 0; cprep_hasprepline = 0; if (CWDisplayLines(param->context, 0) != cwNoErr) return 0; linetick = COS_GetTicks() + 5; code = 0; copts.delete_exception = 1; copts.som_call_optimize = 1; copts.template_patch = 1; copts.template_friends = 1; copts.simple_class_byval = 1; copts.array_new_delete = 1; copts.syspath_once = 1; copts.arg_dep_lookup = 1; copts.longlong = 1; copts.longlong_prepeval = copts.longlong; copts.vbase_ctor_offset = 1; copts.vbase_abi_v2 = 1; copts.optEH = 1; copts.optEH2 = 0; if (copts.cplusplus) copts.const_strings = 1; copts.inline_bottom_up = 1; if (initheaps(&CError_NoMem)) { releaseheaps(); cprep_nomem_exit = 1; code = 255; } else { if (setjmp(errorreturn) == 0) { InitNameHash(); setupprep(); CParser_Setup(); SetupPrecompiler(cparamblkptr->precompile); SetupAssembler(); ObjGen_Setup(); PointerAnalysis_Setup(); CBrowse_Setup(param); setupfile(NULL, 1, 0); if (copts.oldprefixname[0]) setupfile(copts.oldprefixname, 1, 0); coptssave = galloc(sizeof(CompilerLinkerOptions)); *coptssave = copts; coptpushs = NULL; coptpush = NULL; preprocessing_only = param->preprocess; if (param->preprocess) CPrep_Preprocess(); else cparser(); if (CWDisplayLines(param->context, lines) != cwNoErr) anyerrors = 1; if (tokenstacklevel) { was_prep_error = 1; CError_ErrorTerm(CErrorStr119); } else if (iflevel) { was_prep_error = 0; ts.tokenfile = ifstack[iflevel - 1].file; ts.tokenoffset = ifstack[iflevel - 1].pos; if (iflevel) CError_SetErrorToken(&ts); CError_ErrorTerm(CErrorStr119); } if (!anyerrors) { if (param->precompile == 1) { CBrowse_Finish(param); PrecompilerWrite(); } else if (!param->preprocess) { ObjGen_Finish(); CBrowse_Finish(param); } code = 1; } if (param->preprocess) { cparamblkptr->objectdata = pplist.data; pplist.data = NULL; cparamblkptr->browsedata = NULL; } } else { CWDisplayLines(param->context, lines); } CParser_Cleanup(); CleanupPrecompiler(); CleanupAssembler(); ObjGen_Cleanup(); ObjGen_CodeCleanup(); PointerAnalysis_Cleanup(); cleanupprep(); CBrowse_Cleanup(param); } param->object.compiledlines = lines; if (cprep_nomem_exit) { CompilerGetCString(7, string); CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); } return code; } static void pushtokenseq(Macro *macro) { if (tokenstacklevel >= 128) { was_prep_error = 1; CError_ErrorTerm(CErrorStr111); } else { tokenstack[tokenstacklevel].pos = pos; tokenstack[tokenstacklevel].macrostart = macrostart; tokenstack[tokenstacklevel].macro = macro; if (macro) macro->xF = 1; tokenstack[tokenstacklevel].macrocheck = macrocheck; tokenstacklevel++; } } void poptokenseq(void) { if (!--tokenstacklevel && dofreeaheap) freeaheap(); pos = tokenstack[tokenstacklevel].pos; macrostart = tokenstack[tokenstacklevel].macrostart; if (tokenstack[tokenstacklevel].macro) tokenstack[tokenstacklevel].macro->xF = 0; macrocheck = tokenstack[tokenstacklevel].macrocheck; spaceskip = 1; } static Boolean is_nextchar(short t) { char *p = pos; short level = tokenstacklevel; int c; do { switch ((c = *p)) { case 0: if (level <= 0) return 0; p = tokenstack[--level].pos; continue; case 13: p++; continue; } if (c == t) return 1; if (c != ' ' && (c < 9 || c > 12)) break; p++; } while (1); return 0; } static Macro *ismacroname(void) { Macro *scan; Boolean save_macrocheck; HashNameNode *name = tkidentifier; for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) { if (scan->name == name) { if (scan->is_special) { if (scan == &vecM && !copts.altivec_model) return NULL; if (scan == &stdcM && copts.cplusplus) return NULL; if (scan == &cpplM && !copts.cplusplus) return NULL; if (scan == &ecppM && (!copts.cplusplus || !copts.ecplusplus)) return NULL; } if (scan->xF) { waslockedmacro = 1; return NULL; } if (scan->xC) { save_macrocheck = macrocheck; macrocheck = 0; gotonexttoken(); macrocheck = save_macrocheck; if (*pos != '(') return NULL; } return scan; } } return NULL; } static Macro *ismacroname2(char *str) { Macro *scan; HashNameNode *name = tkidentifier; for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) { if (scan->name == name) { if (scan->xF) { waslockedmacro = 1; return NULL; } if (scan->xC) { while (*str == ' ' || (*str >= 9 && *str <= 12)) str++; if (*str != '(' && !is_nextchar('(')) return NULL; } return scan; } } return NULL; } static Macro *ismacroname5(char *str) { Macro *scan; HashNameNode *name = tkidentifier; for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) { if (scan->name == name) { if (scan->xF) { waslockedmacro = 1; return NULL; } if (scan->xC) { while (*str == ' ' || (*str >= 9 && *str <= 12)) str++; if (*str != '(') return NULL; } return scan; } } return NULL; } static Macro *ismacroname3(void) { Macro *scan; HashNameNode *name = tkidentifier; for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) { if (scan->name == name) { if (scan->is_special) { if (scan == &vecM && !copts.altivec_model) return NULL; if (scan == &stdcM && copts.cplusplus) return NULL; if (scan == &cpplM && !copts.cplusplus) return NULL; } break; } } return scan; } static Macro *ismacroname4(HashNameNode *name) { Macro *scan; for (scan = macrohashtable[name->hashval]; scan; scan = scan->next) { if (scan->name == name) { if (scan->is_special) { if (scan == &vecM && !copts.altivec_model) return NULL; if (scan == &stdcM && copts.cplusplus) return NULL; if (scan == &cpplM && !copts.cplusplus) return NULL; } break; } } return scan; } void foundnl(void) { if (!tokenstacklevel) { if (preprocessing_only) CPrep_PreprocessDumpNewLine(); linenumber++; lines++; if (filesp <= 0) lineoffset = pos - filestack[0]->textbuffer; } } void newline(void) { foundnl(); nlflag = 1; at_linestart = 1; spaceskip = 1; if (COS_GetTicks() > linetick) { if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) CError_UserBreak(); linetick = COS_GetTicks() + 5; } } static void gotonexttoken(void) { char *save_pos; Macro *macro; char c; loop: switch ((c = prepskipnextchar())) { case 0: if (tokenstacklevel) { poptokenseq(); goto loop; } if (tokenstacklevel > 0 || pos >= prep_file_end) { if (filesp > 0) { popfile(); goto loop; } return; } pos = nextcharpos; goto loop; case 13: newline(); pos = nextcharpos; goto loop; } if (macrocheck && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'))) { pos = ReadIdentifier(save_pos = pos); if ((macro = ismacroname())) { prepmacro(macro); goto loop; } else { pos = save_pos; } } } short notendofline(void) { char *save_pos; Macro *macro; char c; loop: switch ((c = prepskipnextchar())) { case 0: if (tokenstacklevel) { poptokenseq(); goto loop; } case 13: return 0; } if (macrocheck && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'))) { pos = ReadIdentifier(save_pos = pos); if ((macro = ismacroname())) { prepmacro(macro); goto loop; } else { pos = save_pos; } } return 1; } static void CPrep_MacroRedefError(char *name, Boolean *flag) { if (!*flag) { if (copts.gcc_extensions) { CPrep_WarningName(CErrorStr108, name); } else if (copts.cpp_extensions) { if (copts.pedantic) CPrep_WarningName(CErrorStr108, name); } else { CPrep_ErrorName(CErrorStr108, name); } *flag = 1; } } static void goendofline(void) { if (notendofline()) { CPrep_Error(CErrorStr113); skipendofline(); } } static void CPrep_Define(void) { Macro *existing_macro; // r31 Macro *macro; // r20 HashNameNode *name; // r29 HashNameNode **names; // r20 short t; // r17 short i; short argCount; // r28 char *ptr19; char *ptr17; Boolean hasVarArgs; // r27 Boolean isPrecedingTokenAnArg; Boolean tokenPasteFlag; Boolean error_flag; HashNameNode *myNameList[128]; macrocheck = 0; nlflag = 0; t = lexidentifier(); if (nlflag) { CPrep_Error(CErrorStr112); skipendofline(); } if (t != TK_IDENTIFIER) { CPrep_Error(CErrorStr107); skipendofline(); return; } existing_macro = ismacroname3(); name = tkidentifier; error_flag = 0; hasVarArgs = 0; if (prepcurchar() == '(') { argCount = 1; pos = nextcharpos; if (existing_macro) names = existing_macro->names; else names = NULL; do { t = lexidentifier(); if (t != TK_IDENTIFIER) break; if (nlflag) { CPrep_Error(CErrorStr112); return; } if (!strcmp(tkidentifier->name, "__VA_ARGS__")) { CPrep_ErrorName(CErrorStr365, tkidentifier->name); return; } for (i = 1; i < argCount; i++) { if (!strcmp(tkidentifier->name, myNameList[i - 1]->name)) { CPrep_ErrorName(CErrorStr365, tkidentifier->name); return; } } myNameList[argCount - 1] = tkidentifier; if (existing_macro) { if ((existing_macro->xC & 0x7FFF) < argCount) CPrep_MacroRedefError(name->name, &error_flag); if (names[argCount - 1] != tkidentifier && !copts.cpp_extensions) CPrep_MacroRedefError(name->name, &error_flag); } if (argCount >= 128) CError_Error(CErrorStr110); else argCount++; t = plex(); if (nlflag) { CPrep_Error(CErrorStr112); return; } } while (t == ','); if (nlflag) { CPrep_Error(CErrorStr112); return; } if (t == TK_ELLIPSIS) { hasVarArgs = 1; myNameList[argCount - 1] = GetHashNameNode("__VA_ARGS__"); if (argCount >= 128) CError_Error(CErrorStr110); else argCount++; t = plex(); if (nlflag) { CPrep_Error(CErrorStr112); return; } } if (t != ')') { CPrep_Error(CErrorStr109); skipendofline(); return; } macro = galloc(sizeof(Macro) + sizeof(HashNameNode *) + sizeof(HashNameNode *) * (argCount - 2)); } else { macro = galloc(sizeof(Macro)); argCount = 0; } if (existing_macro && (existing_macro->xC & 0x7FFF) != argCount) CPrep_MacroRedefError(name->name, &error_flag); macro->name = name; macro->xC = hasVarArgs ? (argCount | 0x8000) : argCount; macro->is_special = 0; macro->xF = 0; for (i = 1; i < argCount; i++) macro->names[i - 1] = myNameList[i - 1]; mlist.size = 0; if (notendofline()) { while (1) { tokenPasteFlag = 0; innerLoop: isPrecedingTokenAnArg = 0; ptr19 = pos; spaceskip = 0; t = prepnextchar(); switch (t) { case 0: CPrep_Error(CErrorStr102); break; case '"': case '\'': CPrep_MatchChar(t, 1); AppendGListData(&mlist, ptr19, pos - ptr19); break; case '#': ptr17 = pos; if (prepnextchar() == '#') CPrep_Error(CErrorStr117); pos = ptr17; if (notendofline()) { t = prepnextchar(); if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || t == '_') { pos = ReadIdentifier(pos - 1); for (i = 1; i < argCount; i++) { if (tkidentifier == macro->names[i - 1]) break; } if (i < argCount) { AppendGListByte(&mlist, TK_MACRO_ARG_HASH); AppendGListByte(&mlist, i); break; } } } if (copts.ANSIstrict) CPrep_Error(CErrorStr117); AppendGListByte(&mlist, '#'); pos = ptr17; break; default: if ((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z') || t == '_') { pos = ReadIdentifier(pos - 1); for (i = 1; i < argCount; i++) { if (tkidentifier == macro->names[i - 1]) break; } if (i < argCount) { AppendGListByte(&mlist, tokenPasteFlag ? TK_MACRO_ARG_2 : TK_MACRO_ARG_1); AppendGListByte(&mlist, i); isPrecedingTokenAnArg = 1; } else { AppendGListName(&mlist, tkidentifier->name); } } else { AppendGListByte(&mlist, t); } } if (!notendofline()) break; ptr17 = pos; if (prepnextchar() == '#' && prepnextchar() == '#') { if (!notendofline()) CPrep_Error(CErrorStr117); if (isPrecedingTokenAnArg) (*mlist.data)[mlist.size - 2] = TK_MACRO_ARG_2; tokenPasteFlag = 1; goto innerLoop; } pos = ptr17; if (spaceskip) AppendGListByte(&mlist, ' '); } } macrocheck = 1; if (mlist.size > 0) { AppendGListByte(&mlist, 0); if (mlist.size > 0x20000) { CPrep_Error(CErrorStr111); return; } if (existing_macro) { if (!existing_macro->c || memcmp(*mlist.data, existing_macro->c, mlist.size)) CPrep_MacroRedefError(name->name, &error_flag); } macro->c = galloc(mlist.size); memcpy(macro->c, *mlist.data, mlist.size); } else { macro->c = NULL; if (existing_macro && existing_macro->c) CPrep_MacroRedefError(name->name, &error_flag); } if (existing_macro && error_flag) return; macro->next = macrohashtable[macro->name->hashval]; macrohashtable[macro->name->hashval] = macro; if (cparamblkptr->browseoptions.recordMacros && prep_file->recordbrowseinfo) { CBrowse_NewMacro(macro, prep_file, gDirectiveStart, pos - prep_file_start + 1); } if (error_flag) { macro = macrohashtable[macro->name->hashval]; while (1) { if (macro->next == existing_macro) { macro->next = macro->next->next; break; } macro = macro->next; CError_ASSERT(2847, macro); } } } static void prepundefine(void) { short t; Macro *macro; Macro **scan; HashNameNode *name; nlflag = 0; t = lexidentifier(); if (nlflag) { CPrep_Error(CErrorStr112); skipendofline(); } else if (t != TK_IDENTIFIER) { CPrep_Error(CErrorStr107); skipendofline(); } else { name = tkidentifier; for (scan = ¯ohashtable[name->hashval], macro = *scan; macro; scan = ¯o->next, macro = *scan) { if (macro->name == name) { *scan = macro->next; macrocheck = 1; return; } } goendofline(); } } static Boolean CPrep_CheckTarget(void) { Boolean result; if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (plex() != '(') { CError_Error(CErrorStr114); return 0; } if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (plex() != TK_STRING) { CError_Error(CErrorStr120); return 0; } result = !strcmp(cparams.idetargetname, tkstring); if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (plex() != ')') { CError_Error(CErrorStr115); return 0; } return result; } static Boolean CPrep_CheckOption(void) { UInt32 offset; UInt8 *ptr; struct CompilerOption *option; Boolean result; if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (plex() != '(') { CError_Error(CErrorStr114); return 0; } if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (lexidentifier() != TK_IDENTIFIER) { CError_Error(CErrorStr107); return 0; } if (!strcmp(tkidentifier->name, "scheduling")) { result = copts.schedule_factor != 0; } else if (!strcmp(tkidentifier->name, "precompile")) { result = cparamblkptr->precompile == 1; } else if (!strcmp(tkidentifier->name, "preprocess")) { result = cparamblkptr->preprocess; } else { for (option = compileroptions; option->name; option++) { if (!strcmp(tkidentifier->name, option->name)) { offset = option->bits & OPT_OFFSET_MASK; ptr = (UInt8 *) (offset + (intptr_t) &copts); result = *ptr; if (offset == OPT_OFFSET(booltruefalse) && !copts.cplusplus) result = 0; goto gotResult; } } result = 0; } gotResult: if (!notendofline()) { CError_Error(CErrorStr112); return 0; } if (plex() != ')') { CError_Error(CErrorStr115); return 0; } return result; } static char *CPrep_XpandDefinedCheck(char *str) { while (*str == ' ' || (*str >= 9 && *str <= 12)) str++; if (*str == '(') { str++; while (*str == ' ' || (*str >= 9 && *str <= 12)) str++; } if ((*str >= 'a' && *str <= 'z') || (*str >= 'A' && *str <= 'Z') || *str == '_') return ReadIdentifier(str); return NULL; } static char *XpandString(Macro *macro, char *somepos) { short start_level; char *curpos; char *tmp; SInt32 tmplen; SInt32 i; char *macro_output; Macro *macro2; int c; pushtokenseq(macro); macropos = somepos; macrostart = somepos; start_level = tokenstacklevel; pos = somepos; mlist.size = 0; while (tokenstacklevel >= start_level) { loop: switch (*(curpos = pos)) { case 4: AppendGListByte(&mlist, 4); pos = ReadIdentifier(somepos = ++pos); if (cprep_incondexpr && !strcmp(tkidentifier->name, "defined") && (tmp = CPrep_XpandDefinedCheck(pos))) pos = tmp; AppendGListData(&mlist, somepos, pos - somepos); goto loop; case '"': case '\'': somepos = pos++; CPrep_MatchChar(*somepos, 0); AppendGListData(&mlist, somepos, pos - somepos); goto loop; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '_': pos = ReadIdentifier(curpos); waslockedmacro = 0; if (cprep_incondexpr && !strcmp(tkidentifier->name, "defined") && (tmp = CPrep_XpandDefinedCheck(pos))) { pos = tmp; AppendGListData(&mlist, curpos, pos - curpos); goto loop; } else { if (macro) macro2 = ismacroname2(pos); else macro2 = ismacroname5(pos); if (macro2) { AppendGListByte(&mlist, 5); tmplen = mlist.size; if (tmplen > 0x20000) { macropos = pos; CPrep_Error(CErrorStr111); return ""; } curpos = aalloc(tmplen); memcpy(curpos, *mlist.data, tmplen); macro_output = XpandMacro(macro2); if (tokenstacklevel == start_level) { for (i = strlen(macro_output) - 1; i > 0; i--) { switch (macro_output[i]) { case ' ': case '"': case '\'': case ';': goto exit_innermost_loop; } } exit_innermost_loop: if (i > 0) { mlist.size = 0; AppendGListName(&mlist, ¯o_output[i + 1]); AppendGListID(&mlist, pos); pos = aalloc(mlist.size); memcpy(pos, *mlist.data, mlist.size); mlist.size = 0; AppendGListData(&mlist, curpos, tmplen); AppendGListData(&mlist, macro_output, i + 1); } else { mlist.size = 0; AppendGListName(&mlist, macro_output); AppendGListID(&mlist, pos); macro_output = aalloc(mlist.size); memcpy(macro_output, *mlist.data, mlist.size); mlist.size = 0; pos = macro_output; AppendGListData(&mlist, curpos, tmplen); } } else { mlist.size = 0; AppendGListData(&mlist, curpos, tmplen); AppendGListID(&mlist, macro_output); if (tokenstacklevel < start_level) goto skip_null_term; mlist.size--; goto loop; } } else { if (waslockedmacro) AppendGListByte(&mlist, 4); AppendGListData(&mlist, curpos, pos - curpos); goto loop; } } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': AppendGListByte(&mlist, *(pos++)); do { c = *pos; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c >= '0' && c <= '9')) { AppendGListByte(&mlist, c); pos++; } else { break; } } while (1); goto loop; default: AppendGListByte(&mlist, *(pos++)); goto loop; case 0: if (tokenstacklevel >= start_level) poptokenseq(); } } AppendGListByte(&mlist, 0); skip_null_term: if ((tmplen = mlist.size) > 0x20000) { CPrep_Error(CErrorStr111); return ""; } tmp = aalloc(tmplen); memcpy(tmp, *mlist.data, tmplen); return tmp; } char *CPrep_GetFileName(char *buffer, Boolean flag1, Boolean flag2) { FSSpec spec; Str255 filename; int size; StringPtr src; char *dst; COS_FileGetFSSpecInfo(&filestack[flag1 ? 0 : filesp]->textfile, NULL, NULL, filename); size = filename[0]; if (!buffer) buffer = galloc(size + 3); dst = buffer; if (flag2) *(dst++) = '"'; src = filename; while (size-- > 0) *(dst++) = *(++src); if (flag2) *(dst++) = '"'; *(dst++) = 0; return buffer; } static char *XpandSpecialMacro(Macro *macro) { char buf[512]; char smallbuf[32]; char *strptr; struct tm *tm; if (macro == &optiM) { return CPrep_CheckOption() ? "1" : "0"; } else if (macro == &trgtM) { return CPrep_CheckTarget() ? "1" : "0"; } else if (macro == &lineM) { sprintf(buf, "%" PRId32, linenumber); do_string: strptr = aalloc(strlen(buf) + 1); strcpy(strptr, buf); return strptr; } else if (macro == &fileM) { CPrep_GetFileName(buf, 0, 1); goto do_string; } else if (macro == &dateM) { tm = localtime(&now_time); strftime(buf, 64, "\"%b ", tm); strftime(smallbuf, 32, "%d", tm); if (smallbuf[0] == '0') smallbuf[0] = ' '; strcat(buf, smallbuf); strftime(smallbuf, 32, " %Y\"", tm); strcat(buf, smallbuf); goto do_string; } else if (macro == &timeM) { strftime(buf, 64, "\"%H:%M:%S\"", localtime(&now_time)); goto do_string; } else if (macro == &stdcM) { return "1"; } else if (macro == &casmM || macro == &MWRSM) { return "0x2405"; } else if (macro == &cpplM) { return "199711L"; } else if (macro == &dtsomM) { return copts.direct_to_som ? "1" : "0"; } else if (macro == &ecppM) { return copts.ecplusplus ? "1" : "0"; } else if (macro == &stcvM) { return copts.c9x ? "199901L" : "199409L"; } else if (macro == &stchM) { return "0"; } else { return CodeGen_ExpandSpecialMacro(macro); } } static char *XpandMacro(Macro *macro) { void **buf1; void **buf2; Boolean hasVarArgs; int argCount; int maxArgs; char *p; char *p2; char *input; short ch; short t; short i; short depth; short spaceFlag; Boolean inVarArgs; SInt32 tmplen; if (macro->is_special) return XpandSpecialMacro(macro); argCount = macro->xC & 0x7FFF; hasVarArgs = (macro->xC & 0x8000) != 0; if (argCount) { gotonexttoken(); CError_ASSERT(3293, prepnextchar() == '('); if (argCount > 1) { inVarArgs = hasVarArgs && argCount == 2; maxArgs = argCount - 1; buf1 = aalloc(sizeof(void *) * maxArgs); buf2 = aalloc(sizeof(void *) * maxArgs); i = 1; while (i < argCount) { spaceFlag = 1; depth = 0; mlist.size = 0; restart1: spaceskip = 0; restart2: t = prepnextchar(); switch (t) { case '\r': foundnl(); spaceskip = 1; goto restart2; case '\t': case '\n': case '\v': case '\f': case ' ': spaceskip = 1; goto restart2; case 0: if (tokenstacklevel != 0) { poptokenseq(); goto restart2; } CPrep_Error(CErrorStr102); break; case '"': case '\'': p = pos - 1; CPrep_MatchChar(t, 0); AppendGListData(&mlist, p, pos - p); goto restart1; case ')': if (--depth < 0) { if (++i >= argCount) break; macropos = pos; CPrep_Error(CErrorStr116); return ""; } goto do_default; case ',': if (depth <= 0 && !inVarArgs) { i++; if (hasVarArgs && i == maxArgs) { inVarArgs = 1; } else if (i >= argCount) { macropos = pos; CPrep_Error(CErrorStr115); return ""; } break; } goto do_default; case '(': depth++; default: do_default: if (spaceskip && !spaceFlag) AppendGListByte(&mlist, ' '); AppendGListByte(&mlist, t); spaceFlag = 0; goto restart1; } buf2[i - 2] = buf1[i - 2] = NULL; if (mlist.size > 0) { AppendGListByte(&mlist, 0); tmplen = mlist.size; if (tmplen <= 0x20000) { buf1[i - 2] = aalloc(tmplen); memcpy(buf1[i - 2], *mlist.data, tmplen); } else { CPrep_Error(CErrorStr111); } } } } else { gotonexttoken(); if (prepnextchar() != ')') { macropos = pos; CPrep_Error(CErrorStr115); } } } if (!macro->c) return ""; if (argCount <= 1 && hasVarArgs == 0) return XpandString(macro, macro->c); input = macro->c; mlist.size = 0; while ((ch = *(input++))) { switch (ch) { case '"': case '\'': p = input - 1; input = CPrep_MatchChar2(input, ch, 0); AppendGListData(&mlist, p, input - p); break; case TK_MACRO_ARG_2: p = buf1[*(input++) - 1]; if (p) { while (1) { switch (*p) { case 0: break; case TK_4: case TK_5: p++; continue; default: AppendGListByte(&mlist, *(p++)); continue; } break; } } break; case TK_MACRO_ARG_HASH: AppendGListByte(&mlist, '"'); p = buf1[*(input++) - 1]; if (p) { while ((ch = *(p++))) { switch (ch) { case TK_4: case TK_5: break; case '"': AppendGListByte(&mlist, '\\'); case '\'': AppendGListByte(&mlist, ch); while (*p && *p != ch) { if (*p == '"' || *p == '\\') AppendGListByte(&mlist, '\\'); AppendGListByte(&mlist, *(p++)); } if (*p == '"') AppendGListByte(&mlist, '\\'); if (*p) AppendGListByte(&mlist, *(p++)); break; default: AppendGListByte(&mlist, ch); break; } } } AppendGListByte(&mlist, '"'); break; case TK_MACRO_ARG_1: i = *(input++) - 1; p = buf2[i]; if (!p) { if (!buf1[i]) break; tmplen = mlist.size; p2 = aalloc(tmplen); memcpy(p2, *mlist.data, tmplen); p = buf2[i] = XpandString(NULL, buf1[i]); mlist.size = 0; AppendGListData(&mlist, p2, tmplen); } while (*p) AppendGListByte(&mlist, *(p++)); if (p[-1] == '>' && *input == '>') AppendGListByte(&mlist, ' '); break; default: AppendGListByte(&mlist, ch); } } AppendGListByte(&mlist, 0); if (mlist.size > 0x20000) { CPrep_Error(CErrorStr111); return ""; } else { p = aalloc(mlist.size); memcpy(p, *mlist.data, mlist.size); return XpandString(macro, p); } } static void prepmacro(Macro *macro) { Boolean save_spaceskip; char *result; macrocheck = 0; dofreeaheap = 0; save_spaceskip = spaceskip; result = XpandMacro(macro); macrocheck = 1; pushtokenseq(NULL); macropos = result; pos = result; macrostart = result; dofreeaheap = 1; macrocheck = 0; spaceskip = save_spaceskip; } Boolean macrotest(void) { Macro *macro; if ((macro = ismacroname())) { prepmacro(macro); return 1; } else { return 0; } } short CPrep_PragmaLex(Boolean no_err) { if (notendofline()) return plex(); if (!no_err) CPrep_Error(CErrorStr113); return 0; } void CPrep_PushOption(SInt32 id, char value) { struct COptPush *opt; struct COptPush *newopt; opt = coptpush; do { if (!opt || (opt->x8 && opt->id == id)) { newopt = galloc(sizeof(struct COptPush)); newopt->next = coptpush; coptpush = opt = newopt; break; } if (!opt->x8) break; opt = opt->next; } while (1); opt->value = ((UInt8 *) &copts)[id]; opt->id = id; opt->x8 = 1; ((UInt8 *) &copts)[id] = value; } void CPrep_PopOption(SInt32 id) { struct COptPush *opt; for (opt = coptpush; opt; opt = opt->next) { if (opt->x8 && opt->id == id) { ((UInt8 *) &copts)[id] = opt->value; opt->x8 = 0; return; } } ((UInt8 *) &copts)[id] = ((UInt8 *) coptssave)[id]; } static void CPrep_PragmaImExport(int flags) { NameSpaceObjectList *list; do { if ( !notendofline() || plex() != TK_IDENTIFIER || !(list = CScope_GetLocalObject(cscope_root, tkidentifier)) ) break; while (list) { if (list->object->otype == OT_OBJECT) { switch (OBJECT(list->object)->datatype) { case DDATA: case DFUNC: OBJECT(list->object)->flags |= flags; break; default: CPrep_Warning(CErrorStr186); return; } } list = list->next; } if (!notendofline()) return; } while (plex() == ',' && notendofline()); if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } static void pragma_on_off_reset(UInt32 bits) { Boolean flag = (bits & OPT_FLAG_2000) != 0; int imex_flags; if (notendofline() && plex() == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "on")) { CPrep_PushOption(bits & OPT_OFFSET_MASK, 1); return; } if (!strcmp(tkidentifier->name, "off")) { CPrep_PushOption(bits & OPT_OFFSET_MASK, 0); return; } if (!strcmp(tkidentifier->name, "reset")) { CPrep_PopOption(bits & OPT_OFFSET_MASK); return; } if (flag && !strcmp(tkidentifier->name, "list")) { if (cparamblkptr->preprocess) { skipendofline(); return; } macrocheck = 1; if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(cfm_internal)) imex_flags = OBJECT_INTERNAL; else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(cfm_import)) imex_flags = OBJECT_IMPORT; else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(cfm_export)) imex_flags = OBJECT_EXPORT; else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(cfm_lib_export)) imex_flags = OBJECT_LIB_EXPORT; else CError_FATAL(3610); CPrep_PragmaImExport(imex_flags); return; } } if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } static HashNameNode *CPrep_PragmaOnceName(StringPtr name, Boolean flag) { char buf[256]; char *myname; char *src; char *dst; short len; len = name[0]; if (len > 250) len = 250; myname = &buf[1]; dst = myname; src = (char *) &name[1]; while (len-- > 0) { *(dst++) = tolower(*(src++)); } *dst = 0; *(--myname) = (copts.syspath_once && flag) ? '$' : -'\\'; return GetHashNameNodeExport(myname); } static void pragma_precompile_target(void) { if (!notendofline()) { CPrep_Error(CErrorStr112); return; } if (plex() != TK_STRING) { CPrep_Error(CErrorStr117); skipendofline(); return; } if (ispascalstring) { CPrep_Error(CErrorStr101); skipendofline(); return; } precomp_target_str = tkstring; goendofline(); } static void CPrep_DefinePragmaOnceMacro(StringPtr name, Boolean flag) { HashNameNode *namenode; Macro *macro; namenode = CPrep_PragmaOnceName(name, flag); if (!ismacroname4(namenode)) { macro = galloc(sizeof(Macro) + sizeof(HashNameNode *)); memclrw(macro, sizeof(Macro) + sizeof(HashNameNode *)); macro->name = namenode; macro->next = macrohashtable[namenode->hashval]; macrohashtable[namenode->hashval] = macro; } } static void CPrep_PragmaOnce(void) { if (notendofline()) { if (plex() == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "on")) { include_once = 1; return; } else if (!strcmp(tkidentifier->name, "off")) { include_once = 0; return; } } if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } else { Str255 filename; COS_FileGetFSSpecInfo(&prep_file->textfile, NULL, NULL, filename); CPrep_DefinePragmaOnceMacro(filename, prep_file->unkfield126); } } static void CPrep_PragmaUnused(void) { NameSpace *nspace; NameSpaceObjectList *list; short t; if (cparamblkptr->preprocess) { skipendofline(); return; } if (cscope_currentfunc && notendofline() && plex() == '(' && notendofline()) { restart: if (plex() == TK_IDENTIFIER) { for (nspace = cscope_current; nspace; nspace = nspace->parent) { if (nspace->is_global) break; list = CScope_GetLocalObject(nspace, tkidentifier); if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) { OBJECT(list->object)->flags = OBJECT(list->object)->flags | OBJECT_USED; if (notendofline()) { t = plex(); if (t == ')') return; if (t == ',' && notendofline()) goto restart; } break; } } } } if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } static void CPrep_PragmaInlineDepth(void) { int lv; if (notendofline() && plex() == '(' && notendofline()) { switch (plex()) { case TK_IDENTIFIER: if (strcmp(tkidentifier->name, "smart")) CPrep_Warning(CErrorStr186); else copts.inlinelevel = 0; break; case TK_INTCONST: lv = CInt64_GetULong(&tkintconst); if (lv >= 0 && lv <= 1024) { if (!lv) lv = -1; copts.inlinelevel = lv; } else { CPrep_Warning(CErrorStr186); } break; default: CPrep_Warning(CErrorStr186); skipendofline(); return; } if (!notendofline() || plex() != ')') { CPrep_Warning(CErrorStr115); } if (notendofline()) { CPrep_Warning(CErrorStr113); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } static void CPrep_PragmaInlineMaxSize(void) { if (notendofline() && plex() == '(' && notendofline()) { switch (plex()) { case TK_INTCONST: copts.inlinemaxsize = CInt64_GetULong(&tkintconst); break; default: CPrep_Warning(CErrorStr186); skipendofline(); return; } if (!notendofline() || plex() != ')') { CPrep_Warning(CErrorStr115); } if (notendofline()) { CPrep_Warning(CErrorStr113); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } static void CPrep_PragmaInlineMaxTotalSize(void) { if (notendofline() && plex() == '(' && notendofline()) { switch (plex()) { case TK_INTCONST: copts.inlinemaxtotalsize = CInt64_GetULong(&tkintconst); break; default: CPrep_Warning(CErrorStr186); skipendofline(); return; } if (!notendofline() || plex() != ')') { CPrep_Warning(CErrorStr115); } if (notendofline()) { CPrep_Warning(CErrorStr113); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } static void pragma_segment(void) { short i; short t; char name[256]; if (notendofline()) { for (i = 0; i < 255; i++) { spaceskip = 0; t = prepskipnextchar(); if (spaceskip) break; if (t <= ' ') break; name[i] = t; pos = nextcharpos; } name[i] = 0; if (!i || i >= 255) CPrep_Warning(CErrorStr186); copts.cursegmentname = GetHashNameNodeExport(name); ObjGen_SegmentName(); } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } static void pragma_options(void) { if (notendofline() && plex() == TK_IDENTIFIER && !strcmp(tkidentifier->name, "align") && notendofline() && plex() == '=' && notendofline() && plex() == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "reset")) { CPrep_PopOption(OPT_OFFSET(structalignment)); goto done; } else if (!strcmp(tkidentifier->name, "native")) { CPrep_PushOption(OPT_OFFSET(structalignment), AlignMode2_PPC); goto done; } else if (!strcmp(tkidentifier->name, "mac68k")) { CPrep_PushOption(OPT_OFFSET(structalignment), AlignMode0_Mac68k); goto done; } else if (!strcmp(tkidentifier->name, "mac68k4byte")) { CPrep_PushOption(OPT_OFFSET(structalignment), AlignMode1_Mac68k4byte); goto done; } else if (!strcmp(tkidentifier->name, "power")) { CPrep_PushOption(OPT_OFFSET(structalignment), AlignMode2_PPC); goto done; } else if (!strcmp(tkidentifier->name, "packed")) { CPrep_PushOption(OPT_OFFSET(structalignment), AlignMode8_Packed); goto done; } } if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; done: if (notendofline()) { CPrep_Error(CErrorStr113); skipendofline(); } } static void pragma_push(void) { struct COptsPush *push; push = galloc(sizeof(struct COptsPush)); push->next = coptpushs; coptpushs = push; push->opts = copts; } static void pragma_pop(void) { if (coptpushs) { copts = coptpushs->opts; coptpushs = coptpushs->next; CMach_Configure(); } else { CPrep_Error(CErrorStr237); } } static void pragma_overload(void) { Object *obj; if (cparamblkptr->preprocess) { skipendofline(); return; } nlflag = 0; tk = lex(); if ((obj = CParser_ParseObject())) { if (obj->sclass && obj->sclass != 0x103) CPrep_Error(CErrorStr177); obj->qual |= Q_WEAK; } else { CPrep_Error(CErrorStr186); } if (nlflag) CPrep_Error(CErrorStr112); if (tk != ';') CPrep_Error(CErrorStr123); } static void pragma_optimization_level(void) { short t; int lv; if (notendofline()) { t = plex(); if (t == TK_INTCONST) { lv = CInt64_GetULong(&tkintconst); if (lv >= 0 && lv <= 4) { if (copts.crippled && lv > 1) { CPrep_Warning(CErrorStr385); lv = 1; } CPrep_PushOption(OPT_OFFSET(optimizationlevel), lv); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr154); skipendofline(); } } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) { CPrep_PopOption(OPT_OFFSET(optimizationlevel)); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr105); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } static void pragma_opt_unroll_count(void) { short t; int lv; if (notendofline()) { t = plex(); if (t == TK_INTCONST) { lv = CInt64_GetULong(&tkintconst); if (lv >= 0 && lv <= 127) { CPrep_PushOption(OPT_OFFSET(unrollfactor), lv); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr154); skipendofline(); } } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) { CPrep_PopOption(OPT_OFFSET(unrollfactor)); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr105); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } static void pragma_opt_unroll_instr_count(void) { short t; int lv; if (notendofline()) { t = plex(); if (t == TK_INTCONST) { lv = CInt64_GetULong(&tkintconst); if (lv >= 0 && lv <= 127) { CPrep_PushOption(OPT_OFFSET(unrollinstrfactor), lv); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr154); skipendofline(); } } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) { CPrep_PopOption(OPT_OFFSET(unrollinstrfactor)); CodeGen_UpdateOptimizerOptions(); CodeGen_UpdateBackEndOptions(); } else { CPrep_Error(CErrorStr105); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } static void pragma_pack(void) { int t; int i; Boolean did_push; Boolean did_pop; if (notendofline() && plex() == '(') { macrocheck = 1; if (notendofline() && ((t = plex()) == ')')) { copts.structalignment = coptssave->structalignment; } else { did_push = did_pop = 0; do { if (t == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "push")) { if (cprep_packstackp) { cprep_packstackp--; cprep_packstack[cprep_packstackp].identifier = NULL; cprep_packstack[cprep_packstackp].align_mode = copts.structalignment; did_push = 1; } else { CPrep_Warning(CErrorStr186); } } else if (!strcmp(tkidentifier->name, "pop")) { if (cprep_packstackp < 128) { copts.structalignment = cprep_packstack[cprep_packstackp].align_mode; cprep_packstackp++; did_pop = 1; } else { CPrep_Warning(CErrorStr186); } } else { if (did_push) { cprep_packstack[cprep_packstackp].identifier = tkidentifier; } else if (did_pop) { for (i = cprep_packstackp - 1; i < 128; i++) { if (cprep_packstack[i].identifier == tkidentifier) break; } if (i < 128) { copts.structalignment = cprep_packstack[i].align_mode; cprep_packstackp = i + 1; } else { CPrep_Warning(CErrorStr186); } } else { CPrep_Warning(CErrorStr186); } did_pop = 0; did_push = 0; } } else { if (t == TK_INTCONST) { switch (CInt64_GetULong(&tkintconst)) { case 0: copts.structalignment = coptssave->structalignment; break; case 1: copts.structalignment = AlignMode3_1Byte; break; case 2: copts.structalignment = AlignMode4_2Byte; break; case 4: copts.structalignment = AlignMode5_4Byte; break; case 8: copts.structalignment = AlignMode6_8Byte; break; case 16: copts.structalignment = AlignMode7_16Byte; break; default: if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } did_pop = 0; did_push = 0; } if (notendofline()) t = plex(); if (t != ',') break; t = plex(); } while (1); } if (t != ')' && copts.warn_illpragma) CPrep_Warning(CErrorStr186); macrocheck = 0; } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); } } static void pragma_comment(void) { int t; short start_tokenstacklevel = tokenstacklevel; if (notendofline() && plex() == '(') { if (notendofline()) { t = plex(); if (t == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "compiler")) { t = plex(); } else if (!strcmp(tkidentifier->name, "exestr") || !strcmp(tkidentifier->name, "linker") || !strcmp(tkidentifier->name, "user")) { if (plex() == ',') { macrocheck = 1; t = plex(); macrocheck = 0; if (t == TK_STRING) { while (t == TK_STRING) { macrocheck = 1; if (tokenstacklevel == start_tokenstacklevel && !notendofline()) break; macrocheck = 1; t = plex(); macrocheck = 0; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } else if (!strcmp(tkidentifier->name, "lib")) { if (plex() == ',') { macrocheck = 1; t = plex(); macrocheck = 0; if (t == TK_STRING) { while (t == TK_STRING) { macrocheck = 1; if (tokenstacklevel == start_tokenstacklevel && !notendofline()) break; macrocheck = 1; t = plex(); macrocheck = 0; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); return; } } if (t != ')') { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } static void pragma_message(void) { int t; short start_tokenstacklevel; char str[128]; char *ptr; if (notendofline() && plex() == '(') { if (notendofline()) { start_tokenstacklevel = tokenstacklevel; ptr = str; str[0] = 0; macrocheck = 1; t = plex(); macrocheck = 0; if (t == TK_STRING) { while (t == TK_STRING) { strncpy(ptr, tkstring, sizeof(str) - (ptr - str)); str[sizeof(str) - 1] = 0; ptr = str + strlen(str); macrocheck = 1; if (tokenstacklevel == start_tokenstacklevel && !notendofline()) break; macrocheck = 1; t = plex(); macrocheck = 0; } CWReportMessage(cparamblkptr->context, NULL, str, NULL, messagetypeInfo, 337); skipendofline(); } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } else if (plex() != ')') { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); } } static void preppragma(void) { struct CompilerOption *opt; Boolean save_eoltokens; if (notendofline()) { macrocheck = 0; if (lexidentifier() == TK_IDENTIFIER) { if (!strcmp(tkidentifier->name, "pack")) { pragma_pack(); } else if (!strcmp(tkidentifier->name, "optimization_level")) { pragma_optimization_level(); } else if (!strcmp(tkidentifier->name, "once")) { CPrep_PragmaOnce(); } else if (!strcmp(tkidentifier->name, "unused")) { CPrep_PragmaUnused(); } else if (!strcmp(tkidentifier->name, "inline_depth")) { CPrep_PragmaInlineDepth(); } else if (!strcmp(tkidentifier->name, "inline_max_size")) { CPrep_PragmaInlineMaxSize(); } else if (!strcmp(tkidentifier->name, "inline_max_total_size")) { CPrep_PragmaInlineMaxTotalSize(); } else if (!strcmp(tkidentifier->name, "opt_pointer_analysis_mode")) { PointerAnalysis_PragmaMode(); } else if (!strcmp(tkidentifier->name, "options")) { pragma_options(); macrocheck = 1; return; } else if (!strcmp(tkidentifier->name, "segment")) { pragma_segment(); } else if (!strcmp(tkidentifier->name, "push")) { pragma_push(); } else if (!strcmp(tkidentifier->name, "pop")) { pragma_pop(); } else if (!strcmp(tkidentifier->name, "parameter")) { macrocheck = 1; CMach_PragmaParams(); } else if (!strcmp(tkidentifier->name, "overload")) { macrocheck = 1; pragma_overload(); } else if (!strcmp(tkidentifier->name, "mark")) { skipendofline(); macrocheck = 1; return; } else if (!strcmp(tkidentifier->name, "precompile_target")) { pragma_precompile_target(); } else if (!strcmp(tkidentifier->name, "message")) { pragma_message(); } else if (!strcmp(tkidentifier->name, "opt_unroll_count")) { pragma_opt_unroll_count(); } else if (!strcmp(tkidentifier->name, "opt_unroll_instr_count")) { pragma_opt_unroll_instr_count(); } else if (!strcmp(tkidentifier->name, "exception_terminate")) { if (!preprocessing_only) CExcept_Terminate(); } else if (!strcmp(tkidentifier->name, "exception_arrayinit")) { if (!preprocessing_only) CExcept_ArrayInit(); } else if (!strcmp(tkidentifier->name, "exception_magic")) { if (!preprocessing_only) CExcept_Magic(); } else if (!strcmp(tkidentifier->name, "SOMReleaseOrder")) { macrocheck = 1; CSOM_PragmaReleaseOrder(); } else if (!strcmp(tkidentifier->name, "SOMClassVersion")) { macrocheck = 1; CSOM_PragmaClassVersion(); } else if (!strcmp(tkidentifier->name, "SOMMetaClass")) { macrocheck = 1; CSOM_PragmaMetaClass(); } else if (!strcmp(tkidentifier->name, "SOMCallStyle")) { CSOM_PragmaCallStyle(); } else { for (opt = compileroptions; opt->name; opt++) { if (!strcmp(tkidentifier->name, opt->name) && !(opt->bits & OPT_FLAG_4000)) { pragma_on_off_reset(opt->bits); if (opt->bits & OPT_FLAG_8000) CMach_Configure(); goto foundOption; } } save_eoltokens = cprep_eoltokens; cprep_eoltokens = 1; CodeGen_ParsePragma(tkidentifier); cprep_eoltokens = save_eoltokens; macrocheck = 1; return; } } else { if (copts.warn_illpragma) CPrep_Warning(CErrorStr186); skipendofline(); macrocheck = 1; return; } foundOption: if (notendofline()) { CPrep_Error(CErrorStr113); skipendofline(); } CPrep_Reconfig(); macrocheck = 1; } } static void prepinclude(Boolean flag) { // mostly ok but registers need to be rearranged short t; Boolean r29; short len; short i; char *save_pos; char buf[256]; short start_tokenstacklevel; StringPtr ptr; if (!notendofline()) { CPrep_Error(CErrorStr112); return; } t = prepcurchar(); if (t != '"' && t != '<') { CPrep_Error(CErrorStr117); skipendofline(); return; } r29 = 1; save_pos = pos; if (t == '<') { prepnextchar(); if (!copts.flat_include) r29 = 0; len = 0; while ((t = prepnextstringchar((StringPtr) save_pos, 1)) != '>') { if (t != TK_5) { if (len > 254) { CPrep_Error(CErrorStr106); skipendofline(); return; } buf[++len] = t; } } buf[0] = len; ptr = (StringPtr) buf; } else { start_tokenstacklevel = tokenstacklevel; macrocheck = 1; t = plex(); macrocheck = 0; buf[1] = 0; if (t != TK_STRING) { CPrep_Error(CErrorStr117); skipendofline(); return; } while (t == TK_STRING) { strncat(&buf[1], tkstring, 254 - strlen(&buf[1])); buf[255] = 0; if (tokenstacklevel == start_tokenstacklevel && !notendofline()) break; macrocheck = 1; t = plex(); macrocheck = 0; } buf[0] = strlen(&buf[1]); ptr = (StringPtr) buf; } goendofline(); if (ismacroname4(CPrep_PragmaOnceName((StringPtr) buf, !r29))) return; if (flag || copts.always_import) CPrep_DefinePragmaOnceMacro((StringPtr) buf, !r29); if (copts.flat_include) { for (i = len; i > 0; i--) { switch (buf[i]) { case ':': case '/': case '\\': ptr = (StringPtr) buf; ptr += i; buf[i] = len - i; goto all_done; } } } all_done: setupfile(ptr, r29, flag); } static void prepline(void) { short t; short len; char buf[256]; cprep_hasprepline = 1; if (!notendofline()) { CPrep_Error(CErrorStr112); return; } if (plex() != TK_INTCONST) { CPrep_Error(CErrorStr117); skipendofline(); return; } linenumber = CInt64_GetULong(&tkintconst) - 1; if (notendofline()) { if (prepnextchar() != '"') { CPrep_Error(CErrorStr117); skipendofline(); return; } len = 0; while ((t = prepnextchar()) != '"') { if (!t) break; if (len > 252) { CPrep_Error(CErrorStr106); skipendofline(); return; } buf[len] = t; len++; } buf[len] = 0; CTool_CtoPstr(buf); filestack[filesp]->nameNode = CPrep_GetSourceFilePath(filestack[filesp]); COS_FileSetFSSpec(&filestack[filesp]->textfile, (StringPtr) buf); goendofline(); if (preprocessing_only && !copts.simple_prepdump) CPrep_PreprocessDumpFileInfo(0); } } static Type *CPrep_GetPrepType(PrepValue *pv) { if (copts.longlong_prepeval || copts.c9x) { if (pv->is_unsigned) return TYPE(&stunsignedlonglong); else return TYPE(&stsignedlonglong); } else { if (pv->is_unsigned) return TYPE(&stunsignedlong); else return TYPE(&stsignedlong); } } static PrepValue CPrep_ParseUnary(void) { PrepValue val; if (!notendofline()) { CPrep_Error(CErrorStr112); val.val = cint64_zero; val.is_unsigned = 0; } else { switch (plex()) { case '-': val = CPrep_ParseUnary(); val.val = CMach_CalcIntMonadic(CPrep_GetPrepType(&val), '-', val.val); return val; case '+': val = CPrep_ParseUnary(); return val; case '!': val = CPrep_ParseUnary(); CInt64_SetLong(&val.val, CInt64_IsZero(&val.val)); return val; case '~': val = CPrep_ParseUnary(); val.val = CMach_CalcIntMonadic(CPrep_GetPrepType(&val), '~', val.val); return val; case '(': val = CPrep_ParseCond(); if (exprtk != ')') { CPrep_Error(CErrorStr115); return val; } break; case TK_TRUE: val.val = cint64_one; val.is_unsigned = 1; break; default: CPrep_Error(CErrorStr141); case TK_FALSE: val.val = cint64_zero; val.is_unsigned = 1; break; case TK_INTCONST: val.val = tkintconst; val.is_unsigned = (tksize == IT_ULONGLONG || tksize == IT_ULONG || tksize == IT_UINT || tksize == IT_UCHAR); break; case TK_IDENTIFIER: val.val = cint64_zero; val.is_unsigned = 0; if (!strcmp("defined", tkidentifier->name)) { macrocheck = 0; if (!notendofline()) { CPrep_Error(CErrorStr112); break; } if ((exprtk = plex()) == '(') { if (!notendofline()) { CPrep_Error(CErrorStr112); macrocheck = 1; break; } if (lexidentifier() != TK_IDENTIFIER) { CPrep_Error(CErrorStr107); macrocheck = 1; break; } if (ismacroname3()) val.val = cint64_one; if (!notendofline()) { CPrep_Error(CErrorStr112); macrocheck = 1; break; } if (plex() != ')') CPrep_Error(CErrorStr115); } else if (exprtk == TK_IDENTIFIER) { if (ismacroname3()) val.val = cint64_one; } else { CPrep_Error(CErrorStr107); } macrocheck = 1; } break; } } exprtk = notendofline() ? plex() : (short) 0; return val; } static PrepValue CPrep_ParseBinary(PrepValue *rhs, short precLimit) { PrepValue a; PrepValue b; short op; short prec; short newprec; if (!rhs) a = CPrep_ParseUnary(); else a = *rhs; while (1) { if (!(prec = GetPrec(op = exprtk))) return a; if (!notendofline()) { CPrep_Error(CErrorStr112); return a; } b = CPrep_ParseUnary(); while (1) { if (exprtk == ')' || !notendofline()) { if (b.is_unsigned) a.is_unsigned = 1; a.val = CMach_CalcIntDiadic(CPrep_GetPrepType(&a), a.val, op, b.val); return a; } if (!(newprec = GetPrec(exprtk))) { CPrep_Error(CErrorStr141); return a; } if (prec >= newprec) { if (b.is_unsigned) a.is_unsigned = 1; a.val = CMach_CalcIntDiadic(CPrep_GetPrepType(&a), a.val, op, b.val); if (GetPrec(newprec) <= precLimit) return a; break; } else { b = CPrep_ParseBinary(&b, prec); } } } } static PrepValue CPrep_ParseCond(void) { PrepValue a; PrepValue b; PrepValue c; a = CPrep_ParseBinary(NULL, -1); if (exprtk == '?') { b = CPrep_ParseCond(); if (!notendofline()) { CPrep_Error(CErrorStr112); return a; } if (exprtk != ':') { CPrep_Error(CErrorStr170); return a; } if (!notendofline()) { CPrep_Error(CErrorStr112); return a; } c = CPrep_ParseCond(); a = !CInt64_IsZero(&a.val) ? b : c; } return a; } static void doevalconstexpr(void) { PrepValue v; macrocheck = 1; nlflag = 0; cprep_incondexpr = 1; v = CPrep_ParseCond(); if (exprtk) CPrep_Error(CErrorStr141); cprep_incondexpr = 0; if (nlflag) CPrep_Error(CErrorStr112); else goendofline(); tkintconst = v.val; } static void pushifstate(SInt16 state) { if (iflevel >= 64) { CPrep_Error(CErrorStr215); } else { ifstack[iflevel].state = state; ifstack[iflevel].file = prep_file; ifstack[iflevel].pos = pos - prep_file_start; iflevel++; } } static void popifstate(void) { if (iflevel <= 0) { CPrep_Error(CErrorStr117); } else { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: iflevel--; return; } iflevel--; if (iflevel > 0) { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: prepifskip(); } } } } static void positiveif(void) { pushifstate(IfState_0); } static void negativeif(Boolean flag) { if (flag) { pushifstate(IfState_1); prepifskip(); } else { pushifstate(IfState_3); } } static void prepif(void) { if (iflevel > 0) { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: skipendofline(); negativeif(0); return; } } doevalconstexpr(); if (CInt64_IsZero(&tkintconst)) negativeif(1); else positiveif(); } static void prepifdef(void) { if (iflevel > 0) { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: skipendofline(); negativeif(0); return; } } macrocheck = 0; if (!notendofline()) { CPrep_Error(CErrorStr112); negativeif(1); return; } if (lexidentifier() != TK_IDENTIFIER) { CPrep_Error(CErrorStr107); negativeif(1); return; } macrocheck = 1; goendofline(); if (ismacroname3()) positiveif(); else negativeif(1); } static void prepifndef(void) { if (iflevel > 0) { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: skipendofline(); negativeif(0); return; } } macrocheck = 0; if (!notendofline()) { CPrep_Error(CErrorStr112); negativeif(1); return; } if (lexidentifier() != TK_IDENTIFIER) { CPrep_Error(CErrorStr107); negativeif(1); return; } macrocheck = 1; goendofline(); if (!ismacroname3()) positiveif(); else negativeif(1); } static void prepelif(void) { if (iflevel <= 0 || ifstack[iflevel - 1].state == IfState_2 || ifstack[iflevel - 1].state == IfState_4) { CPrep_Error(CErrorStr118); skipendofline(); return; } switch (ifstack[iflevel - 1].state) { case IfState_1: doevalconstexpr(); if (!CInt64_IsZero(&tkintconst)) ifstack[iflevel - 1].state = IfState_0; break; case IfState_3: skipendofline(); break; case IfState_0: ifstack[iflevel - 1].state = IfState_3; skipendofline(); prepifskip(); break; default: CError_FATAL(5700); } } static void prepelse(void) { if (iflevel <= 0 || ifstack[iflevel - 1].state == IfState_2 || ifstack[iflevel - 1].state == IfState_4) { CPrep_Error(CErrorStr118); skipendofline(); return; } if (!copts.ANSIstrict) skipendofline(); else goendofline(); switch (ifstack[iflevel - 1].state) { case IfState_1: ifstack[iflevel - 1].state = IfState_2; break; case IfState_0: ifstack[iflevel - 1].state = IfState_4; prepifskip(); break; case IfState_3: ifstack[iflevel - 1].state = IfState_4; break; default: CError_FATAL(5738); } } static void prependif(void) { if (iflevel <= 0) { CPrep_Error(CErrorStr118); skipendofline(); return; } macrocheck = 0; if (!copts.ANSIstrict) skipendofline(); else goendofline(); macrocheck = 1; popifstate(); } static void prepifskip(void) { TStreamElement ts; short t; while (iflevel > 0) { switch (ifstack[iflevel - 1].state) { case IfState_1: case IfState_3: case IfState_4: restart: t = prepskipnextchar(); pos = nextcharpos; switch (t) { case 0: if (tokenstacklevel > 0) { poptokenseq(); } else if (tokenstacklevel > 0 || pos >= prep_file_end) { if (filesp > 0) { popfile(); } else { was_prep_error = 0; ts.tokenfile = ifstack[iflevel - 1].file; ts.tokenoffset = ifstack[iflevel - 1].pos; CError_SetErrorToken(&ts); CError_ErrorTerm(CErrorStr119); iflevel = 0; return; } } else { CPrep_Error(CErrorStr105); } goto restart; case 13: newline(); goto restart; case '"': skipendoflinematch((StringPtr) pos, '"'); goto restart; case '\'': skipendoflinematch((StringPtr) pos, '"'); goto restart; case '#': t = prepskipnextchar(); pos = nextcharpos; switch (t) { case 13: goto restart; case 0: CPrep_Error(CErrorStr102); default: pos = ReadIdentifier(pos - 1); if (!strcmp("if", tkidentifier->name)) { prepif(); } else if (!strcmp("ifdef", tkidentifier->name)) { prepifdef(); } else if (!strcmp("ifndef", tkidentifier->name)) { prepifndef(); } else if (!strcmp("elif", tkidentifier->name)) { prepelif(); } else if (!strcmp("else", tkidentifier->name)) { prepelse(); } else if (!strcmp("endif", tkidentifier->name)) { prependif(); } else { skipendofline(); goto restart; } } break; default: skipendofline(); goto restart; } break; case IfState_2: default: return; } } } void preprocessor(void) { short t; gDirectiveStart = pos - prep_file_start; t = prepskipnextchar(); pos = nextcharpos; switch (t) { case 0: CPrep_Error(CErrorStr102); case 13: return; } pos = ReadIdentifier(pos - 1); if (!strcmp("define", tkidentifier->name)) { CPrep_Define(); macrocheck = 1; return; } if (!strcmp("undef", tkidentifier->name)) { prepundefine(); macrocheck = 1; return; } if (!strcmp("include", tkidentifier->name)) { prepinclude(0); macrocheck = 1; return; } if (!strcmp("line", tkidentifier->name)) { prepline(); macrocheck = 1; return; } if (!strcmp("error", tkidentifier->name)) { CPrep_Error(CErrorStr318); CError_ResetErrorSkip(); skipendofline(); macrocheck = 1; return; } if (!strcmp("pragma", tkidentifier->name)) { preppragma(); macrocheck = 1; return; } if (!copts.ANSIstrict) { if (!strcmp("warning", tkidentifier->name)) { CPrep_Warning(CErrorStr337); skipendofline(); macrocheck = 1; return; } if (!strcmp(tkidentifier->name, "ident")) { skipendofline(); macrocheck = 1; return; } } if (!strcmp("if", tkidentifier->name)) { macrocheck = 1; prepif(); return; } if (!strcmp("ifdef", tkidentifier->name)) { macrocheck = 1; prepifdef(); return; } if (!strcmp("ifndef", tkidentifier->name)) { macrocheck = 1; prepifndef(); return; } if (!strcmp("elif", tkidentifier->name)) { macrocheck = 1; prepelif(); return; } if (!strcmp("else", tkidentifier->name)) { macrocheck = 1; prepelse(); return; } if (!strcmp("endif", tkidentifier->name)) { macrocheck = 1; prependif(); return; } if (copts.objective_c || !copts.ANSIstrict) { if (!strcmp("import", tkidentifier->name)) { prepinclude(1); macrocheck = 1; return; } } CPrep_Error(CErrorStr104); skipendofline(); macrocheck = 1; } SInt32 CPrep_BrowserTokenOffset(FileOffsetInfo *foi) { return foi->tokenoffset; } SInt32 CPrep_BrowserFileOffset(void) { if (ts_first < ts_current) return ts_current[-1].tokenoffset + 1; else if (tokenstacklevel) return tokenstack[0].pos - filestack[filesp]->textbuffer; else return pos - filestack[filesp]->textbuffer; } void CPrep_BrowserFilePosition(CPrepFileInfo **fileinfo, SInt32 *offset) { CPrepFileInfo *file; if (ts_first < ts_current) { file = ts_current[-1].tokenfile; *offset = ts_current[-1].tokenoffset + 1; } else { file = filestack[filesp]; if (tokenstacklevel) { *offset = tokenstack[0].pos - filestack[filesp]->textbuffer; } else { *offset = pos - filestack[filesp]->textbuffer; } } if (file && file->fileID > 0 && (file->recordbrowseinfo || gForceSourceLoc)) { *fileinfo = file; } else { *fileinfo = NULL; *offset = 0; } } CPrepFileInfo *CPrep_BrowserCurrentFile(void) { return prep_file; }