MWCC/compiler_and_linker/FrontEnd/C/CPrep.c

4365 lines
128 KiB
C

#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 "compiler/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);
extern SInt16 *CLT_filesp;
extern CPrepFileInfo **CLT_filestack;
struct CompilerOption {
char *name;
short bits;
} compileroptions[138] = {
"little_endian", OPT_FLAG_4000 | OPT_OFFSET(little_endian),
"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_bclr_bcctr", OPT_OFFSET(ppc_opt_bclr_bcctr),
"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(ARM_conform),
"ARM_scoping", OPT_OFFSET(ARM_scoping),
"require_prototypes", OPT_OFFSET(require_prototypes),
"trigraphs", OPT_OFFSET(trigraphs),
"only_std_keywords", OPT_OFFSET(only_std_keywords),
"enumsalwaysint", OPT_OFFSET(enumsalwaysint),
"ANSI_strict", OPT_OFFSET(ANSI_strict),
"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(useRTTI),
"delete_exception", OPT_OFFSET(delete_exception),
"oldalignment", OPT_OFFSET(oldalignment),
"multibyteaware", OPT_OFFSET(multibyteaware),
"unsigned_char", OPT_OFFSET(unsignedchars),
"auto_inline", OPT_OFFSET(autoinline),
"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_opt),
"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),
"microsoft_RTTI", OPT_OFFSET(microsoft),
"warning_errors", OPT_OFFSET(warningerrors),
"extended_errorcheck", OPT_OFFSET(pedantic),
"check_header_flags", OPT_OFFSET(check_header_flags),
"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(align_array_members),
"dont_reuse_strings", OPT_OFFSET(dont_reuse_strings),
"pool_strings", OPT_OFFSET(pool_strings),
"explicit_zero_data", OPT_OFFSET(explicit_zero_data),
"readonly_strings", OPT_OFFSET(readonly_strings),
"opt_common_subs", OPT_OFFSET(opt_common_subs),
"opt_loop_invariants", OPT_OFFSET(opt_loop_invariants),
"opt_propagation", OPT_OFFSET(opt_propagation),
"opt_unroll_loops", OPT_OFFSET(opt_unroll_loops),
"opt_lifetimes", OPT_OFFSET(opt_lifetimes),
"opt_strength_reduction", OPT_OFFSET(opt_strength_reduction),
"opt_strength_reduction_strict", OPT_OFFSET(opt_strength_reduction_strict),
"opt_dead_code", OPT_OFFSET(opt_dead_code),
"opt_dead_assignments", OPT_OFFSET(opt_dead_assignments),
"opt_vectorize_loops", OPT_OFFSET(opt_vectorize_loops),
"opt_pointer_analysis", OPT_OFFSET(opt_pointer_analysis),
"exceptions", OPT_OFFSET(exceptions),
"dont_inline", OPT_OFFSET(dont_inline),
"always_inline", OPT_OFFSET(always_inline),
"optimize_for_size", OPT_OFFSET(optimize_for_size),
"peephole", OPT_OFFSET(peephole),
"global_optimizer", OPT_OFFSET(global_optimizer),
"side_effects", OPT_OFFSET(side_effects),
"internal", OPT_FLAG_2000 | OPT_OFFSET(internal),
"import", OPT_FLAG_2000 | OPT_OFFSET(import),
"export", OPT_FLAG_2000 | OPT_OFFSET(export),
"lib_export", OPT_FLAG_2000 | OPT_OFFSET(lib_export),
"nosyminline", OPT_OFFSET(nosyminline),
"force_active", OPT_OFFSET(force_active),
"sym", OPT_OFFSET(isGeneratingDebugInfo),
NULL, 0
};
CParams *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;
COpts opts;
};
struct COptPush {
struct COptPush *next;
SInt32 id;
Boolean x8;
UInt8 value;
};
static struct COptsPush *coptpushs;
static struct COptPush *coptpush;
static COpts *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 = &macrohashtable[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;
CLT_filesp = &filesp;
CLT_filestack = filestack;
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();
stringmem = COS_NewHandle(256);
if (!stringmem)
CError_NoMem();
ts_buffer = COS_NewHandle(1024 * sizeof(TStreamElement));
if (!ts_buffer)
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;
unsigned 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 = 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.pchType) {
if (cparamblkptr->isCachingPrecompiledHeaders) {
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->mainFileText) {
COS_FileGetFSSpecInfo(&cparamblkptr->mainFileSpec, &file_vrefnum, &file_dirid, file_filename);
cannotopenerror(file_filename, 1);
return 0;
}
prepinfo.textfile = cparamblkptr->mainFileSpec;
prepinfo.textbuffer = (char *) cparamblkptr->mainFileText;
prepinfo.textlength = cparamblkptr->mainFileTextLength;
prepinfo.fileID = cparamblkptr->mainFileID;
prepinfo.recordbrowseinfo = cparamblkptr->field276;
}
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;
SInt32 start_offset;
Boolean tryflag;
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 int CPrep_TokenSize(char *str) {
int 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] == '>') return (str[2] == '*') ? 3 : 2;
if (str[1] == '=' || str[1] == '-') return 2;
break;
case '<':
if (str[1] == '=') return 2;
if (str[1] == '<') return (str[2] == '=') ? 3 : 2;
break;
case '>':
if (str[1] == '=') return 2;
if (str[1] == '>') return (str[2] == '=') ? 3 : 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;
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] == '\r')
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] != '\r')
r5++;
r5--;
while ((c = r7[-r5]) && (c == ' ' || c == '\t' || c == TK_4))
r5--;
r6 = 0;
while ((c = r7[-r5]) != '\r' && c && r6 < 126) {
if (!r5)
*tokenoffset = r6;
if (c != TK_4) {
buf1[r6++] = (c != '\t') ? 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++) {
buf2[i] = *(r5x++);
}
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->isPrecompiling != 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->isPrecompiling != 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->isPrecompiling != 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(CParams *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_opt = 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->isPrecompiling);
SetupAssembler();
ObjGen_Setup();
PointerAnalysis_Setup();
CBrowse_Setup(param);
setupfile(NULL, 1, 0);
if (copts.oldprefixname[0])
setupfile(copts.oldprefixname, 1, 0);
coptssave = galloc(sizeof(COpts));
*coptssave = copts;
coptpushs = NULL;
coptpush = NULL;
preprocessing_only = param->isPreprocessing;
if (param->isPreprocessing)
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->isPrecompiling == 1) {
CBrowse_Finish(param);
PrecompilerWrite();
} else if (!param->isPreprocessing) {
ObjGen_Finish();
CBrowse_Finish(param);
}
code = 1;
}
if (param->isPreprocessing) {
cparamblkptr->objectDataHandle = pplist.data;
pplist.data = NULL;
cparamblkptr->browseDataHandle = NULL;
}
} else {
CWDisplayLines(param->context, lines);
}
CParser_Cleanup();
CleanupPrecompiler();
CleanupAssembler();
ObjGen_Cleanup();
ObjGen_CodeCleanup();
PointerAnalysis_Cleanup();
cleanupprep();
CBrowse_Cleanup(param);
}
param->objectdata.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 '\r':
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 '\r':
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 '\r':
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.ANSI_strict)
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 = &macrohashtable[name->hashval], macro = *scan; macro; scan = &macro->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.targetName, tkstring);
if (!notendofline()) {
CError_Error(CErrorStr112);
return 0;
}
if (plex() != ')') {
CError_Error(CErrorStr115);
return 0;
}
return result;
}
static Boolean CPrep_CheckOption(void) {
UInt16 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_mode != 0;
} else if (!strcmp(tkidentifier->name, "precompile")) {
result = cparamblkptr->isPrecompiling == 1;
} else if (!strcmp(tkidentifier->name, "preprocess")) {
result = cparamblkptr->isPreprocessing;
} 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, &macro_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;
char *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 = (char *) 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, "%ld", 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) {
// does not match - weirdness with the branching inside the loop
NameSpaceObjectList *list;
do {
if (!notendofline())
break;
if (plex() != TK_IDENTIFIER)
break;
if (!(list = CScope_GetLocalObject(cscope_root, tkidentifier))) {
break;
} else {
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->isPreprocessing) {
skipendofline();
return;
}
macrocheck = 1;
if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(internal))
imex_flags = OBJECT_FLAGS_10;
else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(import))
imex_flags = OBJECT_FLAGS_20;
else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(export))
imex_flags = OBJECT_FLAGS_40;
else if ((bits & OPT_OFFSET_MASK) == OPT_OFFSET(lib_export))
imex_flags = OBJECT_FLAGS_60;
else
CError_FATAL(3610);
CPrep_PragmaImExport(imex_flags);
return;
}
}
if (copts.warn_illpragma)
CPrep_Warning(CErrorStr186);
}
static HashNameNode *CPrep_PragmaOnceName(StringPtr name, Boolean flag) {
// does not match, can't be bothered to fix it atm
short len;
char myname[256];
unsigned char *src;
char *dst;
len = name[0];
if (len > 250)
len = 250;
dst = &myname[1];
src = &name[1];
while (len-- > 0) {
*(dst++) = tolower(*(src++));
}
*dst = 0;
myname[0] = (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->isPreprocessing) {
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_FLAGS_1;
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)
copts.inlinelevel = lv ? lv : -1;
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.inline_max_size = 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.inline_max_total_size = 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.forcedSegment = 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(align_mode));
goto done;
} else if (!strcmp(tkidentifier->name, "native")) {
CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode2_PPC);
goto done;
} else if (!strcmp(tkidentifier->name, "mac68k")) {
CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode0_Mac68k);
goto done;
} else if (!strcmp(tkidentifier->name, "mac68k4byte")) {
CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode1_Mac68k4byte);
goto done;
} else if (!strcmp(tkidentifier->name, "power")) {
CPrep_PushOption(OPT_OFFSET(align_mode), AlignMode2_PPC);
goto done;
} else if (!strcmp(tkidentifier->name, "packed")) {
CPrep_PushOption(OPT_OFFSET(align_mode), 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->isPreprocessing) {
skipendofline();
return;
}
nlflag = 0;
tk = lex();
if ((obj = CParser_ParseObject())) {
if (obj->sclass && obj->sclass != 0x103)
CPrep_Error(CErrorStr177);
obj->qual |= Q_OVERLOAD;
} 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(loop_unroll_count), lv);
CodeGen_UpdateOptimizerOptions();
CodeGen_UpdateBackEndOptions();
} else {
CPrep_Error(CErrorStr154);
skipendofline();
}
} else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
CPrep_PopOption(OPT_OFFSET(loop_unroll_count));
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(loop_unroll_size_threshold), lv);
CodeGen_UpdateOptimizerOptions();
CodeGen_UpdateBackEndOptions();
} else {
CPrep_Error(CErrorStr154);
skipendofline();
}
} else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
CPrep_PopOption(OPT_OFFSET(loop_unroll_size_threshold));
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.align_mode = coptssave->align_mode;
} 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.align_mode;
did_push = 1;
} else {
CPrep_Warning(CErrorStr186);
}
} else if (!strcmp(tkidentifier->name, "pop")) {
if (cprep_packstackp < 128) {
copts.align_mode = 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.align_mode = 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.align_mode = coptssave->align_mode;
break;
case 1:
copts.align_mode = AlignMode3_1Byte;
break;
case 2:
copts.align_mode = AlignMode4_2Byte;
break;
case 4:
copts.align_mode = AlignMode5_4Byte;
break;
case 8:
copts.align_mode = AlignMode6_8Byte;
break;
case 16:
copts.align_mode = 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.ANSI_strict)
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.ANSI_strict)
skipendofline();
else
goendofline();
macrocheck = 1;
popifstate();
}
static void prepifskip(void) {
// this function does something very weird with its code generation that i can't match
TStreamElement ts;
short t;
while (iflevel > 0) {
switch (ifstack[iflevel - 1].state) {
case IfState_1:
case IfState_3:
case IfState_4:
while (1) {
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);
}
continue;
case '\r':
newline();
continue;
case '"':
skipendoflinematch((StringPtr) pos, '"');
continue;
case '\'':
skipendoflinematch((StringPtr) pos, '"');
continue;
case '#':
t = prepskipnextchar();
pos = nextcharpos;
switch (t) {
case '\r':
continue;
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();
continue;
}
}
break;
default:
skipendofline();
continue;
}
break;
}
break;
case IfState_2:
default:
return;
}
return;
}
}
void preprocessor(void) {
short t;
gDirectiveStart = pos - prep_file_start;
t = prepskipnextchar();
pos = nextcharpos;
switch (t) {
case 0:
CPrep_Error(CErrorStr102);
case '\r':
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.ANSI_strict) {
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.ANSI_strict) {
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;
}