X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=gmqcc.h;h=0031227457eded092b0b4d25d7e5793b5d45d464;hp=949559442021428f8555b8ce672dbb38c9d02330;hb=b8e536d409a98bcd80d266e85dcc6b9a7c2a3c2c;hpb=c3964cf29d0928b7c1decbd5a4d8dd38c3aff78a diff --git a/gmqcc.h b/gmqcc.h index 9495594..0031227 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012, 2013 * Dale Weiler * Wolfgang Bumiller * @@ -36,18 +36,42 @@ */ #ifdef _MSC_VER # pragma warning(disable : 4244 ) /* conversion from 'int' to 'float', possible loss of data */ -# pragma warning(disable : 4018 ) /* signed/unsigned mismatch */ -#endif +#endif /*! _MSC_VER */ #define GMQCC_VERSION_MAJOR 0 -#define GMQCC_VERSION_MINOR 2 +#define GMQCC_VERSION_MINOR 3 #define GMQCC_VERSION_PATCH 0 #define GMQCC_VERSION_BUILD(J,N,P) (((J)<<16)|((N)<<8)|(P)) #define GMQCC_VERSION \ GMQCC_VERSION_BUILD(GMQCC_VERSION_MAJOR, GMQCC_VERSION_MINOR, GMQCC_VERSION_PATCH) +/* Undefine the following on a release-tag: */ +#define GMQCC_VERSION_TYPE_DEVEL + +/* Full version string in case we need it */ +#ifdef GMQCC_VERSION_TYPE_DEVEL +# ifdef GMQCC_GITINFO +# define GMQCC_DEV_VERSION_STRING "git build: " GMQCC_GITINFO "\n" +# elif defined(GMQCC_VERSION_TYPE_DEVEL) +# define GMQCC_DEV_VERSION_STRING "development build\n" +# else +# define GMQCC_DEV_VERSION_STRING +# endif /*! GMQCC_GITINGO */ +#else +# define GMQCC_DEV_VERSION_STRING +#endif + +#define GMQCC_STRINGIFY(x) #x +#define GMQCC_IND_STRING(x) GMQCC_STRINGIFY(x) +#define GMQCC_FULL_VERSION_STRING \ +"GMQCC " \ +GMQCC_IND_STRING(GMQCC_VERSION_MAJOR) "." \ +GMQCC_IND_STRING(GMQCC_VERSION_MINOR) "." \ +GMQCC_IND_STRING(GMQCC_VERSION_PATCH) \ +" Built " __DATE__ " " __TIME__ \ +"\n" GMQCC_DEV_VERSION_STRING /* - * We cannoy rely on C99 at all, since compilers like MSVC + * We cannot rely on C99 at all, since compilers like MSVC * simply don't support it. We define our own boolean type * as a result (since we cannot include ). For * compilers that are in 1999 mode (C99 compliant) we can use @@ -57,10 +81,10 @@ #ifndef __cplusplus # ifdef false # undef false -# endif /* !false */ +# endif /*! false */ # ifdef true # undef true -# endif /* !true */ +# endif /*! true */ # define false (0) # define true (1) # ifdef __STDC_VERSION__ @@ -68,13 +92,11 @@ typedef int bool; # else typedef _Bool bool; -# endif +# endif /*! __STDC_VERSION__ < 199901L && __GNUC__ < 3 */ # else typedef int bool; -# endif /* !__STDC_VERSION__ */ -#endif /* !__cplusplus */ - - +# endif /*! __STDC_VERSION__ */ +#endif /*! __cplusplus */ /* * Of some functions which are generated we want to make sure @@ -83,9 +105,11 @@ */ #if defined(__GNUC__) || defined(__CLANG__) # define GMQCC_WARN __attribute__((warn_unused_result)) +# define GMQCC_USED __attribute__((used)) #else # define GMQCC_WARN -#endif +# define GMQCC_USED +#endif /*! defined(__GNUC__) || defined (__CLANG__) */ /* * This is a hack to silent clang regarding empty * body if statements. @@ -104,13 +128,13 @@ # define GMQCC_INLINE # else # define GMQCC_INLINE __attribute__ ((always_inline)) -# endif +# endif /*! __GNUC__ < 2 */ # else # define GMQCC_INLINE -# endif +# endif /*! defined(__GNUC__) || defined (__CLANG__) */ # else # define GMQCC_INLINE inline -# endif +# endif /*! __STDC_VERSION < 199901L */ /* * Visual studio has __forcinline we can use. So lets use that * I suspect it also has just __inline of some sort, but our use @@ -120,7 +144,7 @@ # define GMQCC_INLINE __forceinline #else # define GMQCC_INLINE -#endif /* !__STDC_VERSION__ */ +#endif /*! __STDC_VERSION__ */ /* * noreturn is present in GCC and clang @@ -132,7 +156,7 @@ # define GMQCC_NORETURN __attribute__ ((noreturn)) #else # define GMQCC_NORETURN -#endif +#endif /*! (defined(__GNUC__) && __GNUC__ >= 2) || defined (__CLANG__) */ #ifndef _MSC_VER # include @@ -145,18 +169,7 @@ typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; -#endif - -/* - *windows makes these prefixed because they're C99 - * TODO: utility versions that are type-safe and not - * just plain textual subsitution. - */ -#ifdef _MSC_VER -# define snprintf(X, Y, Z, ...) _snprintf(X, Y, Z, __VA_ARGS__) - /* strtof doesn't exist -> strtod does though :) */ -# define strtof(X, Y) (float)(strtod(X, Y)) -#endif +#endif /*! _MSC_VER */ /* * Very roboust way at determining endianess at compile time: this handles @@ -170,20 +183,20 @@ # if defined (__FreeBSD__) || defined (__OpenBSD__) # include # elif defined (BSD) && (BSD >= 199103) || defined (__DJGPP__) || defined (__CYGWIN32__) -# include +# include # elif defined (__APPLE__) # if defined (__BIG_ENDIAN__) && !defined(BIG_ENDIAN) # define BIG_ENDIAN # elif defined (__LITTLE_ENDIAN__) && !defined (LITTLE_ENDIAN) # define LITTLE_ENDIAN -# endif +# endif /*! defined (__BIG_ENDIAN__) && !defined(BIG_ENDIAN) */ # elif !defined (__MINGW32__) # include # if !defined (__BEOS__) # include -# endif -# endif -#endif +# endif /*! !definde (__BEOS__) */ +# endif /*! defined (__FreeBSD__) || defined (__OpenBSD__) */ +#endif /*! defined (__GNUC__) || defined (__GNU_LIBRARY__) */ #if !defined(PLATFORM_BYTE_ORDER) # if defined (LITTLE_ENDIAN) || defined (BIG_ENDIAN) # if defined (LITTLE_ENDIAN) && !defined(BIG_ENDIAN) @@ -194,7 +207,7 @@ # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE # elif defined (BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG -# endif +# endif /*! defined (LITTLE_ENDIAN) && !defined(BIG_ENDIAN) */ # elif defined (_LITTLE_ENDIAN) || defined (_BIG_ENDIAN) # if defined (_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE @@ -204,7 +217,7 @@ # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE # elif defined (_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN) # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG -# endif +# endif /*! defined (_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) */ # elif defined (__LITTLE_ENDIAN__) || defined (__BIG_ENDIAN__) # if defined (__LITTLE_ENDIAN__) && !defined (__BIG_ENDIAN__) # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE @@ -214,9 +227,9 @@ # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE # elif defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__) # define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG -# endif -# endif -#endif +# endif /*! defined (__LITTLE_ENDIAN__) && !defined (__BIG_ENDIAN__) */ +# endif /*! defined(LITTLE_ENDIAN) || defined (BIG_ENDIAN) */ +#endif /*! !defined(PLATFORM_BYTE_ORDER) */ #if !defined (PLATFORM_BYTE_ORDER) # if defined (__alpha__) || defined (__alpha) || defined (i386) || \ defined (__i386__) || defined (_M_I86) || defined (_M_IX86) || \ @@ -236,22 +249,59 @@ # else # define PLATFORM_BYTE_ORDER -1 # endif -#endif +#endif /*! !defined (PLATFORM_BYTE_ORDER) */ +/* + * On windows systems where we're not compiling with MING32 we need a + * little extra help on dependinces for implementing our own dirent.h + * in fs.c. + */ +#if defined(_WIN32) && !defined(__MINGW32__) +# define _WIN32_LEAN_AND_MEAN +# include +# include +# include + + struct dirent { + long d_ino; + unsigned short d_reclen; + unsigned short d_namlen; + char d_name[FILENAME_MAX]; + }; + + typedef struct { + struct _finddata_t dd_dta; + struct dirent dd_dir; + long dd_handle; + int dd_stat; + char dd_name[1]; + } DIR; + /* + * Visual studio also lacks S_ISDIR for sys/stat.h, so we emulate this as well + * which is not hard at all. + */ +# ifdef S_ISDIR +# undef S_ISDIR +# endif /*! S_ISDIR */ +# define S_ISDIR(X) ((X)&_S_IFDIR) +#else +# include +#endif /*! _WIN32 && !defined(__MINGW32__) */ /*===================================================================*/ /*=========================== util.c ================================*/ /*===================================================================*/ -void *util_memory_a (size_t, unsigned int, const char *); -void util_memory_d (void *, unsigned int, const char *); -void *util_memory_r (void *, size_t, unsigned int, const char *); +void *util_memory_a (size_t, /*****/ unsigned int, const char *); +void *util_memory_r (void *, size_t, unsigned int, const char *); +void util_memory_d (void *); void util_meminfo (); bool util_filexists (const char *); bool util_strupper (const char *); bool util_strdigit (const char *); -char *util_strdup (const char *); +char *_util_Estrdup (const char *, const char *, size_t); +char *_util_Estrdup_empty(const char *, const char *, size_t); void util_debug (const char *, const char *, ...); void util_endianswap (void *, size_t, unsigned int); @@ -260,15 +310,37 @@ size_t util_strtononcmd (const char *, char *, size_t); uint16_t util_crc16(uint16_t crc, const char *data, size_t len); +void util_seed(uint32_t); +uint32_t util_rand(); + +/* + * String functions (formatting, copying, concatenating, errors). These are wrapped + * to use the MSVC _safe_ versions when using MSVC, plus some implementations of + * these are non-conformant or don't exist such as asprintf and snprintf, which are + * not supported in C90, but do exist in C99. + */ +int util_vasprintf(char **ret, const char *fmt, va_list); +int util_asprintf (char **ret, const char *fmt, ...); +int util_snprintf (char *src, size_t bytes, const char *format, ...); +char *util_strcat (char *dest, const char *src); +char *util_strncpy (char *dest, const char *src, size_t num); +const char *util_strerror (int num); + + #ifdef NOTRACK -# define mem_a(x) malloc (x) -# define mem_d(x) free ((void*)x) -# define mem_r(x, n) realloc((void*)x, n) +# define mem_a(x) malloc (x) +# define mem_d(x) free ((void*)x) +# define mem_r(x, n) realloc((void*)x, n) +# define mem_af(x,f,l) malloc (x) #else -# define mem_a(x) util_memory_a((x), __LINE__, __FILE__) -# define mem_d(x) util_memory_d((void*)(x), __LINE__, __FILE__) -# define mem_r(x, n) util_memory_r((void*)(x), (n), __LINE__, __FILE__) -#endif +# define mem_a(x) util_memory_a((x), __LINE__, __FILE__) +# define mem_d(x) util_memory_d((void*)(x)) +# define mem_r(x, n) util_memory_r((void*)(x), (n), __LINE__, __FILE__) +# define mem_af(x,f,l) util_memory_a((x), __LINE__, __FILE__) +#endif /*! NOTRACK */ + +#define util_strdup(X) _util_Estrdup((X), __FILE__, __LINE__) +#define util_strdupe(X) _util_Estrdup_empty((X), __FILE__, __LINE__) /* * A flexible vector implementation: all vector pointers contain some @@ -276,7 +348,7 @@ uint16_t util_crc16(uint16_t crc, const char *data, size_t len); * this data is represented in the structure below. Doing this allows * us to use the array [] to access individual elements from the vector * opposed to using set/get methods. - */ + */ typedef struct { size_t allocated; size_t used; @@ -293,18 +365,25 @@ void _util_vec_grow(void **a, size_t i, size_t s); ) /* exposed interface */ -#define vec_meta(A) (((vector_t*)(A)) - 1) -#define vec_free(A) ((A) ? (mem_d((void*)vec_meta(A)), (A) = NULL) : 0) -#define vec_push(A,V) (GMQCC_VEC_WILLGROW(A,1), (A)[vec_meta(A)->used++] = V) +#define vec_meta(A) (((vector_t*)((void*)A)) - 1) +#define vec_free(A) ((void)((A) ? (mem_d((void*)vec_meta(A)), (A) = NULL) : 0)) +#define vec_push(A,V) (GMQCC_VEC_WILLGROW((A),1), (A)[vec_meta(A)->used++] = (V)) #define vec_size(A) ((A) ? vec_meta(A)->used : 0) -#define vec_add(A,N) (GMQCC_VEC_WILLGROW(A,N), vec_meta(A)->used += (N), &(A)[vec_meta(A)->used-(N)]) +#define vec_add(A,N) (GMQCC_VEC_WILLGROW((A),(N)), vec_meta(A)->used += (N), &(A)[vec_meta(A)->used-(N)]) #define vec_last(A) ((A)[vec_meta(A)->used - 1]) -#define vec_pop(A) (vec_meta(A)->used -= 1) -#define vec_shrinkto(A,N) (vec_meta(A)->used = (N)) -#define vec_shrinkby(A,N) (vec_meta(A)->used -= (N)) -#define vec_append(A,N,S) memcpy(vec_add(A, N), S, N * sizeof(*S)) -#define vec_upload(X,Y,S) memcpy(vec_add(X, S * sizeof(*Y)), Y, S * sizeof(*Y)) -#define vec_remove(A,I,N) memmove((char*)A+I*sizeof(*A),(char*)A+(I+N)*sizeof(*A),sizeof(*A)*(vec_meta(A)->used-I-N)),vec_meta(A)->used-=(N) +#define vec_pop(A) ((void)(vec_meta(A)->used -= 1)) +#define vec_shrinkto(A,N) ((void)(vec_meta(A)->used = (N))) +#define vec_shrinkby(A,N) ((void)(vec_meta(A)->used -= (N))) +#define vec_append(A,N,S) ((void)(memcpy(vec_add((A), (N)), (S), (N) * sizeof(*(S))))) +#define vec_upload(X,Y,S) ((void)(memcpy(vec_add((X), (S) * sizeof(*(Y))), (Y), (S) * sizeof(*(Y))))) +#define vec_remove(A,I,N) ((void)(memmove((A)+(I),(A)+((I)+(N)),sizeof(*(A))*(vec_meta(A)->used-(I)-(N))),vec_meta(A)->used-=(N))) + +typedef struct trie_s { + void *value; + struct trie_s *entries; +} correct_trie_t; + +correct_trie_t* correct_trie_new(); typedef struct hash_table_t { size_t size; @@ -342,30 +421,56 @@ typedef struct hash_table_t { * util_htdel(foo); */ hash_table_t *util_htnew (size_t size); +void util_htrem (hash_table_t *ht, void (*callback)(void *data)); void util_htset (hash_table_t *ht, const char *key, void *value); void util_htdel (hash_table_t *ht); size_t util_hthash(hash_table_t *ht, const char *key); void util_htseth(hash_table_t *ht, const char *key, size_t hash, void *value); +void util_htrmh (hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*)); +void util_htrm (hash_table_t *ht, const char *key, void (*cb)(void*)); void *util_htget (hash_table_t *ht, const char *key); void *util_htgeth(hash_table_t *ht, const char *key, size_t hash); + /*===================================================================*/ /*============================ file.c ===============================*/ /*===================================================================*/ -GMQCC_INLINE void file_close (FILE *); -GMQCC_INLINE int file_error (FILE *); -GMQCC_INLINE int file_getc (FILE *); -GMQCC_INLINE int file_printf (FILE *, const char *, ...); -GMQCC_INLINE int file_puts (FILE *, const char *); -GMQCC_INLINE int file_seek (FILE *, long int, int); +/* file handling */ +void fs_file_close (FILE *); +int fs_file_error (FILE *); +int fs_file_getc (FILE *); +int fs_file_printf (FILE *, const char *, ...); +int fs_file_puts (FILE *, const char *); +int fs_file_seek (FILE *, long int, int); +long int fs_file_tell (FILE *); + +size_t fs_file_read (void *, size_t, size_t, FILE *); +size_t fs_file_write (const void *, size_t, size_t, FILE *); -GMQCC_INLINE size_t file_read (void *, size_t, size_t, FILE *); -GMQCC_INLINE size_t file_write (const void *, size_t, size_t, FILE *); +FILE *fs_file_open (const char *, const char *); +int fs_file_getline(char **, size_t *, FILE *); -GMQCC_INLINE FILE *file_open (const char *, const char *); -/*NOINLINE*/ int file_getline(char **, size_t *, FILE *); +/* directory handling */ +int fs_dir_make (const char *); +DIR *fs_dir_open (const char *); +int fs_dir_close (DIR *); +struct dirent *fs_dir_read (DIR *); +/*===================================================================*/ +/*=========================== correct.c =============================*/ +/*===================================================================*/ +typedef struct { + char ***edits; + size_t **lens; +} correction_t; + +void correct_del (correct_trie_t*, size_t **); +void correct_add (correct_trie_t*, size_t ***, const char *); +char *correct_str (correction_t *, correct_trie_t*, const char *); +void correct_init(correction_t *); +void correct_free(correction_t *); + /*===================================================================*/ /*=========================== code.c ================================*/ /*===================================================================*/ @@ -387,6 +492,9 @@ enum { TYPE_UNION , TYPE_ARRAY , + TYPE_NIL , /* it's its own type / untyped */ + TYPE_NOEXPR , /* simply invalid in expressions */ + TYPE_COUNT }; @@ -396,9 +504,9 @@ enum { #define CV_VAR -1 #define CV_WRONG 0x8000 /* magic number to help parsing */ -extern const char *type_name [TYPE_COUNT]; -extern uint16_t type_store_instr [TYPE_COUNT]; -extern uint16_t field_store_instr[TYPE_COUNT]; +extern const char *type_name [TYPE_COUNT]; +extern const uint16_t type_store_instr [TYPE_COUNT]; +extern const uint16_t field_store_instr[TYPE_COUNT]; /* * could use type_store_instr + INSTR_STOREP_F - INSTR_STORE_F @@ -406,10 +514,10 @@ extern uint16_t field_store_instr[TYPE_COUNT]; * instruction set, the old ones are left untouched, thus the _I instructions * are at a seperate place. */ -extern uint16_t type_storep_instr[TYPE_COUNT]; -extern uint16_t type_eq_instr [TYPE_COUNT]; -extern uint16_t type_ne_instr [TYPE_COUNT]; -extern uint16_t type_not_instr [TYPE_COUNT]; +extern const uint16_t type_storep_instr[TYPE_COUNT]; +extern const uint16_t type_eq_instr [TYPE_COUNT]; +extern const uint16_t type_ne_instr [TYPE_COUNT]; +extern const uint16_t type_not_instr [TYPE_COUNT]; typedef struct { uint32_t offset; /* Offset in file of where data begins */ @@ -584,17 +692,11 @@ enum { INSTR_BITAND, INSTR_BITOR, - /* - * Virtual instructions used by the assembler - * keep at the end but before virtual instructions - * for the IR below. - */ - AINSTR_END, - /* * Virtual instructions used by the IR * Keep at the end! */ + VINSTR_END, VINSTR_PHI, VINSTR_JUMP, VINSTR_COND, @@ -605,33 +707,38 @@ enum { VINSTR_NRCALL }; -/* TODO: cleanup this mess */ -extern prog_section_statement *code_statements; -extern int *code_linenums; -extern prog_section_def *code_defs; -extern prog_section_field *code_fields; -extern prog_section_function *code_functions; -extern int *code_globals; -extern char *code_chars; -extern uint16_t code_crc; - /* uhh? */ typedef float qcfloat; typedef int32_t qcint; +typedef struct { + prog_section_statement *statements; + int *linenums; + prog_section_def *defs; + prog_section_field *fields; + prog_section_function *functions; + int *globals; + char *chars; + uint16_t crc; + uint32_t entfields; + ht string_cache; + qcint string_cached_empty; +} code_t; + /* - * code_write -- writes out the compiled file - * code_init -- prepares the code file + * code_write -- writes out the compiled file + * code_init -- prepares the code file + * code_genstrin -- generates string for code + * code_alloc_field -- allocated a field + * code_push_statement -- keeps statements and linenumbers together + * code_pop_statement -- keeps statements and linenumbers together */ -bool code_write (const char *filename, const char *lno); -void code_init (); -uint32_t code_genstring (const char *string); -uint32_t code_cachedstring(const char *string); -qcint code_alloc_field (size_t qcsize); - -/* this function is used to keep statements and linenumbers together */ -void code_push_statement(prog_section_statement *stmt, int linenum); -void code_pop_statement(); +bool code_write (code_t *, const char *filename, const char *lno); +code_t *code_init (void); +uint32_t code_genstring (code_t *, const char *string); +qcint code_alloc_field (code_t *, size_t qcsize); +void code_push_statement(code_t *, prog_section_statement *stmt, int linenum); +void code_pop_statement (code_t *); /* * A shallow copy of a lex_file to remember where which ast node @@ -663,6 +770,9 @@ enum { LVL_ERROR }; +FILE *con_default_out(); +FILE *con_default_err(); + void con_vprintmsg (int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap); void con_printmsg (int level, const char *name, size_t line, const char *msgtype, const char *msg, ...); void con_cvprintmsg(void *ctx, int lvl, const char *msgtype, const char *msg, va_list ap); @@ -680,12 +790,14 @@ int con_out (const char *, ...); /* error/warning interface */ extern size_t compile_errors; +extern size_t compile_Werrors; extern size_t compile_warnings; void /********/ compile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, ...); void /********/ vcompile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, va_list ap); bool GMQCC_WARN compile_warning (lex_ctx ctx, int warntype, const char *fmt, ...); bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list ap); +void compile_show_werrors(); /*===================================================================*/ /*========================= assembler.c =============================*/ @@ -874,7 +986,7 @@ typedef struct qc_program_s { int argc; /* current arg count for debugging */ } qc_program; -qc_program* prog_load(const char *filename); +qc_program* prog_load(const char *filename, bool ignoreversion); void prog_delete(qc_program *prog); bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long maxjumps); @@ -889,43 +1001,59 @@ qcint prog_tempstring(qc_program *prog, const char *_str); /*===================================================================*/ /*===================== parser.c commandline ========================*/ /*===================================================================*/ +struct parser_s; -bool parser_init (); -bool parser_compile_file (const char *); -bool parser_compile_string(const char *, const char *, size_t); -bool parser_finish (const char *); -void parser_cleanup (); +struct parser_s *parser_create (); +bool parser_compile_file (struct parser_s *parser, const char *); +bool parser_compile_string(struct parser_s *parser, const char *, const char *, size_t); +bool parser_finish (struct parser_s *parser, const char *); +void parser_cleanup (struct parser_s *parser); /*===================================================================*/ /*====================== ftepp.c commandline ========================*/ /*===================================================================*/ -bool ftepp_init (); -bool ftepp_preprocess_file (const char *filename); -bool ftepp_preprocess_string(const char *name, const char *str); -void ftepp_finish (); -const char *ftepp_get (); -void ftepp_flush (); -void ftepp_add_define (const char *source, const char *name); -void ftepp_add_macro (const char *name, const char *value); +struct ftepp_s; +struct ftepp_s *ftepp_create (); +bool ftepp_preprocess_file (struct ftepp_s *ftepp, const char *filename); +bool ftepp_preprocess_string(struct ftepp_s *ftepp, const char *name, const char *str); +void ftepp_finish (struct ftepp_s *ftepp); +const char *ftepp_get (struct ftepp_s *ftepp); +void ftepp_flush (struct ftepp_s *ftepp); +void ftepp_add_define (struct ftepp_s *ftepp, const char *source, const char *name); +void ftepp_add_macro (struct ftepp_s *ftepp, const char *name, const char *value); /*===================================================================*/ /*======================= main.c commandline ========================*/ /*===================================================================*/ -#if 0 +#if 1 /* Helpers to allow for a whole lot of flags. Otherwise we'd limit * to 32 or 64 -f options... */ typedef struct { size_t idx; /* index into an array of 32 bit words */ - uint8_t bit; /* index _into_ the 32 bit word, thus just uint8 */ + uint8_t bit; /* bit index for the 8 bit group idx points to */ } longbit; #define LONGBIT(bit) { ((bit)/32), ((bit)%32) } +#define LONGBIT_SET(B, I) ((B).idx = (I)/32, (B).bit = ((I)%32)) #else typedef uint32_t longbit; #define LONGBIT(bit) (bit) +#define LONGBIT_SET(B, I) ((B) = (I)) #endif +/*===================================================================*/ +/*=========================== utf8lib.c =============================*/ +/*===================================================================*/ +typedef uint32_t uchar_t; + +bool u8_analyze (const char *_s, size_t *_start, size_t *_len, uchar_t *_ch, size_t _maxlen); +size_t u8_strlen (const char*); +size_t u8_strnlen (const char*, size_t); +uchar_t u8_getchar (const char*, const char**); +uchar_t u8_getnchar(const char*, const char**, size_t); +int u8_fromchar(uchar_t w, char *to, size_t maxlen); + /*===================================================================*/ /*============================= opts.c ==============================*/ /*===================================================================*/ @@ -944,6 +1072,12 @@ void opts_set (uint32_t *, size_t, bool); void opts_setoptimlevel(unsigned int); void opts_ini_init (const char *); +/* Saner flag handling */ +void opts_backup_non_Wall(); +void opts_restore_non_Wall(); +void opts_backup_non_Werror_all(); +void opts_restore_non_Werror_all(); + enum { # define GMQCC_TYPE_FLAGS # define GMQCC_DEFINE_FLAG(X) X, @@ -988,6 +1122,14 @@ static const unsigned int opts_opt_oflag[] = { # include "opts.def" 0 }; + +enum { +# define GMQCC_TYPE_OPTIONS +# define GMQCC_DEFINE_FLAG(X) OPTION_##X, +# include "opts.def" + OPTION_COUNT +}; + extern unsigned int opts_optimizationcount[COUNT_OPTIMIZATIONS]; /* other options: */ @@ -998,32 +1140,35 @@ typedef enum { COMPILER_GMQCC /* this QuakeC */ } opts_std_t; -/* TODO: cleanup this */ +typedef union { + bool B; + uint16_t U16; + uint32_t U32; + char *STR; +} opt_value_t; + + typedef struct { - uint32_t O; /* -Ox */ - const char *output; /* -o file */ - bool g; /* -g */ - opts_std_t standard; /* -std= */ - bool debug; /* -debug */ - bool memchk; /* -memchk */ - bool dumpfin; /* -dumpfin */ - bool dump; /* -dump */ - bool forcecrc; /* --force-crc= */ - uint16_t forced_crc; /* --force-crc= */ - bool pp_only; /* -E */ - size_t max_array_size; /* --max-array= */ - - uint32_t flags [1 + (COUNT_FLAGS / 32)]; - uint32_t warn [1 + (COUNT_WARNINGS / 32)]; - uint32_t werror [1 + (COUNT_WARNINGS / 32)]; - uint32_t optimization[1 + (COUNT_OPTIMIZATIONS / 32)]; + opt_value_t options [OPTION_COUNT]; + uint32_t flags [1 + (COUNT_FLAGS / 32)]; + uint32_t warn [1 + (COUNT_WARNINGS / 32)]; + uint32_t werror [1 + (COUNT_WARNINGS / 32)]; + uint32_t warn_backup [1 + (COUNT_WARNINGS / 32)]; + uint32_t werror_backup[1 + (COUNT_WARNINGS / 32)]; + uint32_t optimization [1 + (COUNT_OPTIMIZATIONS / 32)]; + bool optimizeoff; /* True when -O0 */ } opts_cmd_t; extern opts_cmd_t opts; -#define OPTS_FLAG(i) (!! (opts.flags [(i)/32] & (1<< ((i)%32)))) -#define OPTS_WARN(i) (!! (opts.warn [(i)/32] & (1<< ((i)%32)))) -#define OPTS_WERROR(i) (!! (opts.werror [(i)/32] & (1<< ((i)%32)))) -#define OPTS_OPTIMIZATION(i) (!! (opts.optimization[(i)/32] & (1<< ((i)%32)))) - -#endif +#define OPTS_GENERIC(f,i) (!! (((f)[(i)/32]) & (1<< ((i)%32)))) +#define OPTS_FLAG(i) OPTS_GENERIC(opts.flags, (i)) +#define OPTS_WARN(i) OPTS_GENERIC(opts.warn, (i)) +#define OPTS_WERROR(i) OPTS_GENERIC(opts.werror, (i)) +#define OPTS_OPTIMIZATION(i) OPTS_GENERIC(opts.optimization, (i)) +#define OPTS_OPTION_BOOL(X) (opts.options[X].B) +#define OPTS_OPTION_U16(X) (opts.options[X].U16) +#define OPTS_OPTION_U32(X) (opts.options[X].U32) +#define OPTS_OPTION_STR(X) (opts.options[X].STR) + +#endif /*! GMQCC_HDR */