mirror of https://git.wuffs.org/MWCC
4365 lines
128 KiB
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 = ¯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;
|
|
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 = ¯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.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, ¯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;
|
|
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;
|
|
}
|