X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=gmqcc.h;h=0b97e2f40c4d6fb9f8f55c4f8df96cd45be55224;hp=7913034fe91692bc1183201179a398d3267ad198;hb=36c5722273f1ea87603621c6ee20b7178a7a641b;hpb=e72d141ec42590277dd88efd57d15c0449333b51 diff --git a/gmqcc.h b/gmqcc.h index 7913034..0b97e2f 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012, 2013 * Dale Weiler * Wolfgang Bumiller * @@ -45,9 +45,30 @@ #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_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 + +#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 @@ -74,8 +95,6 @@ # endif /* !__STDC_VERSION__ */ #endif /* !__cplusplus */ - - /* * Of some functions which are generated we want to make sure * that the result isn't ignored. To find such function calls, @@ -170,7 +189,7 @@ # 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 @@ -243,9 +262,9 @@ /*===================================================================*/ /*=========================== 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 *); @@ -260,13 +279,20 @@ 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(); + +int util_vasprintf(char **ret, const char *fmt, va_list); +int util_asprintf (char **ret, const char *fmt, ...); + + #ifdef NOTRACK # define mem_a(x) malloc (x) # define mem_d(x) free ((void*)x) # define mem_r(x, n) realloc((void*)x, n) #else # define mem_a(x) util_memory_a((x), __LINE__, __FILE__) -# define mem_d(x) util_memory_d((void*)(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__) #endif @@ -294,23 +320,38 @@ 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_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; struct hash_node_t **table; } hash_table_t, *ht; +typedef struct hash_set_t { + size_t bits; + size_t mask; + size_t capacity; + size_t *items; + size_t total; +} hash_set_t, *hs; + /* * hashtable implementation: * @@ -349,6 +390,45 @@ void util_htseth(hash_table_t *ht, const char *key, size_t hash, void * void *util_htget (hash_table_t *ht, const char *key); void *util_htgeth(hash_table_t *ht, const char *key, size_t hash); + +/* + * hashset implementation: + * This was designed for pointers: you manage the life of the object yourself + * if you do use this for non-pointers please be warned that the object may not + * be valid if the duration of it exceeds (i.e on stack). So you need to allocate + * yourself, or put those in global scope to ensure duration is for the whole + * runtime. + * + * util_hsnew() -- to make a new hashset + * util_hsadd(set, key) -- to add something in the set + * util_hshas(set, key) -- to check if something is in the set + * util_hsrem(set, key) -- to remove something in the set + * util_hsdel(set) -- to delete the set + * + * example of use: + * + * hs foo = util_hsnew(); + * char *bar = "hello blub\n"; + * char *baz = "hello dale\n"; + * + * util_hsadd(foo, bar); + * util_hsadd(foo, baz); + * util_hsrem(foo, baz); + * + * printf("bar %d | baz %d\n", + * util_hshas(foo, bar), + * util_hshad(foo, baz) + * ); + * + * util_hsdel(foo); + */ + +hash_set_t *util_hsnew(void); +int util_hsadd(hash_set_t *, void *); +int util_hshas(hash_set_t *, void *); +int util_hsrem(hash_set_t *, void *); +void util_hsdel(hash_set_t *); + /*===================================================================*/ /*============================ file.c ===============================*/ /*===================================================================*/ @@ -357,6 +437,7 @@ 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_putc (FILE *, int); GMQCC_INLINE int file_seek (FILE *, long int, int); GMQCC_INLINE size_t file_read (void *, size_t, size_t, FILE *); @@ -366,6 +447,19 @@ GMQCC_INLINE FILE *file_open (const char *, const char *); /*NOINLINE*/ int file_getline(char **, size_t *, FILE *); +/*===================================================================*/ +/*=========================== correct.c =============================*/ +/*===================================================================*/ +typedef struct { + char ***edits; +} 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 +481,9 @@ enum { TYPE_UNION , TYPE_ARRAY , + TYPE_NIL , /* it's its own type / untyped */ + TYPE_NOEXPR , /* simply invalid in expressions */ + TYPE_COUNT }; @@ -626,7 +723,6 @@ typedef int32_t qcint; 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 */ @@ -683,12 +779,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 =============================*/ @@ -877,7 +975,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); @@ -902,6 +1000,18 @@ void parser_cleanup (); /*===================================================================*/ /*====================== ftepp.c commandline ========================*/ /*===================================================================*/ +struct lex_file_s; +typedef struct { + const char *name; + char *(*func)(struct lex_file_s *); +} ftepp_predef_t; + +/* + * line, file, counter, counter_last, random, random_last, date, time + * increment when items are added + */ +#define FTEPP_PREDEF_COUNT 8 + bool ftepp_init (); bool ftepp_preprocess_file (const char *filename); bool ftepp_preprocess_string(const char *name, const char *str); @@ -911,22 +1021,26 @@ void ftepp_flush (); void ftepp_add_define (const char *source, const char *name); void ftepp_add_macro (const char *name, const char *value); +extern const ftepp_predef_t ftepp_predefs[FTEPP_PREDEF_COUNT]; + /*===================================================================*/ /*======================= 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 /*===================================================================*/ @@ -947,6 +1061,7 @@ int u8_fromchar(uchar_t w, char *to, size_t maxlen); typedef struct { const char *name; longbit bit; + const char *description; } opts_flag_def; bool opts_setflag (const char *, bool); @@ -959,50 +1074,74 @@ 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, +# define GMQCC_DEFINE_FLAG(X, Y) X, # include "opts.def" COUNT_FLAGS }; static const opts_flag_def opts_flag_list[] = { # define GMQCC_TYPE_FLAGS -# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(X) }, +# define GMQCC_DEFINE_FLAG(X, Y) { #X, LONGBIT(X), Y}, # include "opts.def" - { NULL, LONGBIT(0) } + { NULL, LONGBIT(0), "" } }; enum { # define GMQCC_TYPE_WARNS -# define GMQCC_DEFINE_FLAG(X) WARN_##X, +# define GMQCC_DEFINE_FLAG(X, Y) WARN_##X, # include "opts.def" COUNT_WARNINGS }; static const opts_flag_def opts_warn_list[] = { # define GMQCC_TYPE_WARNS -# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(WARN_##X) }, +# define GMQCC_DEFINE_FLAG(X, Y) { #X, LONGBIT(WARN_##X), Y }, # include "opts.def" - { NULL, LONGBIT(0) } + { NULL, LONGBIT(0), "" } }; enum { # define GMQCC_TYPE_OPTIMIZATIONS -# define GMQCC_DEFINE_FLAG(NAME, MIN_O) OPTIM_##NAME, +# define GMQCC_DEFINE_FLAG(NAME, MIN_O, Y) OPTIM_##NAME, # include "opts.def" COUNT_OPTIMIZATIONS }; static const opts_flag_def opts_opt_list[] = { # define GMQCC_TYPE_OPTIMIZATIONS -# define GMQCC_DEFINE_FLAG(NAME, MIN_O) { #NAME, LONGBIT(OPTIM_##NAME) }, +# define GMQCC_DEFINE_FLAG(NAME, MIN_O, Y) { #NAME, LONGBIT(OPTIM_##NAME), Y}, # include "opts.def" - { NULL, LONGBIT(0) } + { NULL, LONGBIT(0), "" } }; static const unsigned int opts_opt_oflag[] = { # define GMQCC_TYPE_OPTIMIZATIONS -# define GMQCC_DEFINE_FLAG(NAME, MIN_O) MIN_O, +# define GMQCC_DEFINE_FLAG(NAME, MIN_O, Y) MIN_O, # include "opts.def" 0 }; + +enum { +# define GMQCC_TYPE_OPTIONS +# define GMQCC_DEFINE_FLAG(X, Y) OPTION_##X, +# include "opts.def" + OPTION_COUNT +}; + +/* disabled for now */ +#if 0 +static const char *opts_options_descriptions[OPTION_COUNT + 1] = { +# define GMQCC_TYPE_OPTIONS +# define GMQCC_DEFINE_FLAG(X, Y) Y, +# include "opts.def" + "" +}; +#endif + extern unsigned int opts_optimizationcount[COUNT_OPTIMIZATIONS]; /* other options: */ @@ -1013,32 +1152,41 @@ typedef enum { COMPILER_GMQCC /* this QuakeC */ } opts_std_t; -/* TODO: cleanup this */ +typedef enum { + OPT_TYPE_BOOL, + OPT_TYPE_U16, + OPT_TYPE_U32, + OPT_TYPE_STR +} opt_type_t; + +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)]; } 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)))) +#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