/* * GTools C compiler * ================= * source file : * C * * Copyright 2001-2004 Paul Froissart. * Credits to Christoph van Wuellen and Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. */ #ifndef C_H #define C_H #ifdef PC #ifdef SHORT_INT #undef int #endif #include //#include #include #ifdef SHORT_INT #define int short #endif #else #include "define.h" #endif //#warning hey hey! #include "error.h" #ifdef CPU_DEFINED #undef CPU_DEFINED #endif #ifdef MC68000 #define MC680X0 #ifdef CPU_DEFINED error, define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "gtclist.txt" #define ICODE_NAME "gtcicode.txt" #endif #ifdef MC68010 #define MC680X0 #ifdef CPU_DEFINED error, define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "gtclist.txt" #define ICODE_NAME "gtcicode.txt" #endif #ifdef MC68020 #define MC680X0 #ifdef CPU_DEFINED error, define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "gtclist.txt" #define ICODE_NAME "gtcicode.txt" #endif #ifdef MC68030 #define MC680X0 #ifdef CPU_DEFINED error, define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "gtclist.txt" #define ICODE_NAME "gtcicode.txt" #endif #ifdef MC68040 #define MC680X0 #ifdef CPU_DEFINED error, define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "gtclist.txt" #define ICODE_NAME "gtcicode.txt" #endif #ifdef INTEL_486 #ifndef INTEL_386 #define INTEL_386 #endif #endif #ifdef INTEL_386 #ifdef CPU_DEFINED #error define only one target CPU! #endif #define CPU_DEFINED #define LIST_NAME "c386.list" #define ICODE_NAME "c386.icode" /* * if FUNCS_USE_387 is defined, extra library calls are generated if the * nofpu option is in effect that allows to use code generated by * this compiler to be linked with functions that return values * on the 387 stack */ #define FUNCS_USE_387 #endif #ifndef CPU_DEFINED #error target CPU type must be defined #endif /* the tokens returned from lexical analysis */ /* assumptions about the order : * none currently (beware of is_lang_ext though) */ enum e_sym { // 0x00 cconst, iconst, lconst, uconst, ulconst, sconst, rconst, plus, minus, // 0x09 divide, lshift, rshift, modop, eq, neq, lt, leq, gt, // 0x12 geq, assign, asplus, asminus, astimes, asdivide, asmodop, asuparrow, // 0x1A aslshift, asrshift, asand, asor, autoinc, autodec, hook, compl, // 0x22 comma, colon, semicolon, uparrow, openbr, closebr, begin, end, // 0x2A closepa, pointsto, dot, lor, land, not, or, and, // 0x32 star, openpa, id, kw_int, kw_char, kw_short, kw_long, kw_void, kw_float, kw_double, kw_struct, kw_union, kw_enum, kw_unsigned, kw_signed, kw_auto, kw_extern, kw_const, kw_volatile, // 0x45 kw_register, kw_typedef, kw_static, kw_goto, kw_return, kw_sizeof, kw_break, kw_continue, kw_if, kw_else, kw_for, kw_do, kw_while, kw_switch, kw_case, kw_default, // 0x55 eof, // ANSI extensions kw_typeof, dots, kw_alloca, // GTC extensions kw_loop, kw_until, kw_count, kw_eval, // (lang extensions) kw_defined, kw_incbin, kw_softcast, kw_c, // GNU C extensions kw_asm, kwb_constant_p, kw_attr, // ASM keywords kw_dreg, kw_areg, sharp, #ifdef OLD_AMODE_INPUT kw_offs_end, #endif kw_instr, }; #define is_lang_ext(__st) (__st>=kw_loop && __st<=kw_eval) /* storage classes */ enum e_sc { sc_static, sc_auto, sc_global, sc_external, sc_type, sc_const, sc_member, sc_label, sc_ulabel, sc_typedef, sc_parms, sc_parms2, sc_define, sc_vamac }; /* basic data types */ #ifndef BCDFLT #define bt_size(__x) ((__x)=bt_struct) #else #define bt_aggregate(__x) ((__x)>=bt_struct) #endif #define bt_uncastable(__x) ((__x)>=bt_struct) #define iscomparable(tp) bt_comparable((tp)->type) #define isscalar(tp) bt_scalar((tp)->type) #define integral(tp) bt_integral((tp)->type) #define isaggregate(tp) bt_aggregate((tp)->type) enum e_bt { bt_char, bt_uchar, bt_short, bt_ushort, bt_long, bt_ulong, bt_float, #ifdef DOUBLE bt_double, #endif bt_pointer, bt_func, bt_void, bt_bitfield, bt_struct, bt_union, }; /* these form the string literal pool */ struct slit { struct slit *next; char *str; short label; short len; }; /* a symbol table */ struct stab { int hash; struct sym *head; struct sym *tail; }; /* important points for reconsidering N_HASH value : - a HTABLE is about 8*N_HASH -byte long - each imbricated 'compound()' call takes the space of 2 HTABLEs on the stack (512 bytes with N_HASH=32, thus allowing only 20 imbricated compound stmts) - there are 6 static HTABLEs, 7 if AS is defined (but could be improved with malloc() / BSS) - N_HASH = 1 << HASH_LOG */ #define N_HASH 32 #define N_HASH_AND "31" #define HASH_LOG 5 typedef struct hstab { int hash; struct htab { struct sym *head; struct sym *tail; } h[N_HASH]; } HTABLE; /* structure defining a data type */ struct typ { struct stab lst; struct typ *btp; #ifdef LISTING char *sname; #endif long size; enum(e_bt) type; /* * The following six chars may be unsigned -- no harm. * They could be ints without restriction -- this is to save memory */ /* * val_flag is normally 0, except for: * - type==bt_pointer: set to 1 if it's an array, to 0 if it's a pointer * - type==bt_func: always set to 1 * (passing a function is like passing an array, we should actually be passing a pointer; * and like an array, we do not want cond_deref() to build an en_ref node) * - type==bt_integral: set to 1 to indicate an enum (this feature is currently unused) */ char val_flag; char st_flag; // is the type already stored globally? char const_flag; // is it a 'const' type? char vol_flag; // is it a 'volatile' type? char bit_width; char bit_offset; }; #ifdef REGPARM #define rp_dn bit_width #define rp_an bit_offset #endif /* a symbol table entry */ struct sym { char *name; struct sym *prev; struct sym *next; struct typ *tp; union { long i; unsigned long u; int splab; char *s; } value; enum(e_sc) storage_class; int used; // note: // - for 'normal' symbols (C variables), this belongs to {-1,0,1} // - for preprocessor symbols, the lower 8 bits is the number of arguments to the macro // and the higher 8 bits are described in enum(e_ppsymflags) below }; enum e_ppsymflags { PPSYM_UNDER_EXPANSION = 0x8000, // set if we are currently expanding this symbol (avoid recursive expansion) #ifdef ASM PPSYM_ASM_KEYWORD = 0x4000, // set if this an ASM reserved keyword ('move', 'b', 'w', 'l', 'd7', 'sp') PPSYM_DEFINED_IN_ASM = 0x2000, // set if this symbol was defined inside an asm{} statement #endif }; #define SYM struct sym #define TYP struct typ #define TABLE struct stab #ifdef PC #define MAX_ERROR_COUNT 1 #else #define MAX_ERROR_COUNT 1 #endif #define MAX_STRLEN 1500 #define MAX_ID_LEN 50 #ifdef OLD_MACRO #define MAX_MAC_LEN 800 #define LINE_LENGTH (1800+MAX_MAC_LEN+1) #else #define LINE_LENGTH (1800+1) #endif #define MAX_PARAMS 20 #define REG_LIST 20 #define AUTO_LIST 100 #define ERR_SYNTAX 0 /* general error */ #define ERR_ILLCHAR 1 /* illegal character */ #define ERR_FPCON 2 /* illegal floating-point constant */ #define ERR_ILLTYPE 3 /* illegal type */ #define ERR_UNDEFINED 4 /* undefined identifier */ #define ERR_FIELD 5 /* no field allowed here */ #define ERR_PUNCT 6 /* expected symbol not found */ #define ERR_IDEXPECT 7 /* identifier expected */ #define ERR_NOINIT 8 /* initialization invalid */ #define ERR_INCOMPLETE 9 /* incomplete struct/union/enum declaration */ #define ERR_ILLINIT 10 /* illegal initialization */ #define ERR_INITSIZE 11 /* too many initializers */ #define ERR_ILLCLASS 12 /* illegal storage class */ #define ERR_BLOCK 13 /* function body expected */ #define ERR_NOPOINTER 14 /* pointer type expected */ #define ERR_NOFUNC 15 /* function type expected */ #define ERR_NOMEMBER 16 /* struct/union member expected */ #define ERR_LVALUE 17 /* l-value required */ #define ERR_DEREF 18 /* error dereferencing a pointer */ #define ERR_MISMATCH 19 /* type mismatch error */ #define ERR_EXPREXPECT 20 /* expression expected */ #define ERR_WHILEXPECT 21 /* 'while' expected in do-loop */ #define ERR_ENUMVAL 22 /* enum value out of range */ #define ERR_DUPCASE 23 /* duplicate case label */ #define ERR_LABEL 24 /* undefined label */ //#define ERR_PREPROC 25 /* preprocessing error */ #define ERR_ARG 26 /* declared Argument missing */ #define ERR_WIDTH 27 /* illegal field width */ #define ERR_INTEXPR 28 /* illegal constant integer expression */ #define ERR_CAST 29 /* error doing a cast */ #define ERR_INTEGER 30 /* integer-valued type expected */ #define ERR_CASTCON 31 /* error casting a constant */ #define ERR_REDECL 32 /* illegal redeclaration */ //#define ERR_PARMS 33 /* error while scanning a parameter list */ #define ERR_FTYPE 34 /* bad host type for bit fields */ #define ERR_INCLFILE 35 /* #include: no include file specified */ #define ERR_CANTOPEN 36 /* can't open include file */ #define ERR_DEFINE 37 /* wrong #define */ #define ERR_CUSTOM 38 /* #error */ #define ERR_DUPSYM 39 /* duplicate symbol */ #define ERR_CONSTEXPECT 40 /* constant expression expected */ #define ERR_OUTRANGE 41 /* value out of range */ #define ERR_TOOMPARAMS 42 /* too many parameters to function */ #define ERR_TOOFPARAMS 43 /* too few parameters to function */ #define ERR_CASERANGE 44 /* invalid case range */ #define ERR_UNEXPECTEOF 45 /* unexpected end of file */ #define ERR_OTH 46 /* (custom error) */ #define ERR_SYS 47 /* (system limitation) */ #define ERRA_INVALIDREL 48 /* invalid relocation in expression */ /* alignment sizes */ #ifdef MC68000 /* * MC68000 is a 16-bit processor. Word alignment is OK in all cases */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 2 #define AL_POINTER 2 #define AL_FLOAT 2 #define AL_DOUBLE 2 #define AL_STRUCT 2 #define AL_FUNC 2 #define AL_DEFAULT 2 /* alignment suitable for all types */ #endif /* MC68000 */ #ifdef MC68010 /* * MC68010 is a 16-bit processor. Word alignment is OK in all cases */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 2 #define AL_POINTER 2 #define AL_FLOAT 2 #define AL_DOUBLE 2 #define AL_STRUCT 2 #define AL_FUNC 2 #define AL_DEFAULT 2 /* alignment suitable for all types */ #endif /* MC68010 */ #ifdef MC68020 /* * perhaps not necessary, but useful: 32-bit alignment for 32-bit types */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 4 #define AL_POINTER 4 #define AL_FLOAT 4 #define AL_DOUBLE 4 #define AL_STRUCT 4 #define AL_FUNC 4 #define AL_DEFAULT 4 /* alignment suitable for all types */ #endif /* MC68020 */ #ifdef MC68030 /* * perhaps not necessary, but useful: 32-bit alignment for 32-bit types */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 4 #define AL_POINTER 4 #define AL_FLOAT 4 #define AL_DOUBLE 4 #define AL_STRUCT 4 #define AL_FUNC 4 #define AL_DEFAULT 4 /* alignment suitable for all types */ #endif /* MC68030 */ #ifdef MC68040 /* * perhaps not necessary, but useful: 32-bit alignment for 32-bit types */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 4 #define AL_POINTER 4 #define AL_FLOAT 4 #define AL_DOUBLE 4 #define AL_STRUCT 4 #define AL_FUNC 4 #define AL_DEFAULT 4 /* alignment suitable for all types */ #endif /* MC68040 */ #ifdef INTEL_386 /* * perhaps not necessary, but useful: 32-bit alignment for 32-bit types */ #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 4 #define AL_POINTER 4 #define AL_FLOAT 4 #define AL_DOUBLE 4 #define AL_STRUCT 4 #define AL_FUNC 4 #define AL_DEFAULT 4 /* alignment suitable for all types */ #endif /* INTEL_386 */ #ifdef SPARC #define AL_CHAR 1 #define AL_SHORT 2 #define AL_LONG 4 #define AL_POINTER 4 #define AL_FLOAT 4 #define AL_DOUBLE 8 #define AL_STRUCT 8 #define AL_FUNC 4 #define AL_DEFAULT 8 /* alignment suitable for all types */ #endif /* SPARC */ int *_xalloc(int); struct sym *search(); struct sym *gsearch(); char *strsave(); TYP *expression(); TYP *exprnc(); TYP *cast_op(); TYP *mk_type(); long intexpr(); int getch(); //void error(); void getsym(); void needpunc(); void initsym(); void append(); long strip_icon(); long push_param(); void do_warning(char *,...); struct sym *symremove(); void getidstr(); void skipspace(); void msg(char *s); void rel_local(); void rel_global(); void clean_up(); void out_init(); void out_close(); void do_compile(); void initpch(); void closepch(); void insert(SYM *sp,HTABLE *table); #ifdef DUAL_STACK extern void *dualstack; extern void *ds_currentlo,*ds_currenthi; void ds_allocatleast(unsigned int size); void ds_free(void); #define ds_remaining (unsigned int)((char *)ds_currenthi-(char *)dualstack) #define ds_ensure(size) ((ds_remaining>=(size) ? 0 : ds_allocatleast(size),0), dualstack) #define ds_pop(target) (void)((target)!=ds_currentlo ? (dualstack = (target)) : ds_free(),0) #ifdef PC #define ds_update(ptr) (void)(dualstack=(ptr),dualstack+=(-(size_t)dualstack)&3,0) #else #define ds_update(ptr) (void)(dualstack=(ptr),1&(short)(long)dualstack ? ++dualstack,0 : 0,0) #endif #define ds_var(type) (type)dualstack #define DS_BSIZE 6000 // we set aside 6 kb for each stack block #endif #endif // vim:ts=4:sw=4