X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=gmqcc.h;h=b27998b1262ce1426c0f2cdb0ab8a1e3943998e8;hp=56c0ba4d0a09d13ea2cf1e364611ae041b36bb2a;hb=d68d19dbfdbe6e239048870d6e6b442a5b1290fb;hpb=1d55197097b0107abf85f47c605d989d52032b5d diff --git a/gmqcc.h b/gmqcc.h index 56c0ba4..b27998b 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -198,6 +198,9 @@ void util_debug (const char *, const char *, ...); int util_getline (char **, size_t *, FILE *); void util_endianswap (void *, int, int); +size_t util_strtocmd (const char *, char *, size_t); +size_t util_strtononcmd (const char *, char *, size_t); + uint32_t util_crc32(const char *, int, register const short); #ifdef NOTRACK @@ -250,7 +253,7 @@ uint32_t util_crc32(const char *, int, register const short); while (N##_add(*++elements) != -1 && len--); \ return N##_elements; \ } \ - typedef char VECTOR_FILL(extra_semicolon_,__COUNTER__) + typedef char VECTOR_FILL(extra_semicolon_##N,__COUNTER__) #define VECTOR_PROT(T,N) \ extern T* N##_data ; \ extern long N##_elements ; \ @@ -283,6 +286,8 @@ enum { TYPE_COUNT }; +extern const char *type_name[TYPE_COUNT]; + extern size_t type_sizeof[TYPE_COUNT]; extern uint16_t type_store_instr[TYPE_COUNT]; /* could use type_store_instr + INSTR_STOREP_F - INSTR_STORE_F @@ -292,6 +297,25 @@ extern uint16_t type_store_instr[TYPE_COUNT]; */ extern uint16_t type_storep_instr[TYPE_COUNT]; +typedef struct { + uint32_t offset; /* Offset in file of where data begins */ + uint32_t length; /* Length of section (how many of) */ +} prog_section; + +typedef struct { + uint32_t version; /* Program version (6) */ + uint16_t crc16; /* What is this? */ + uint16_t skip; /* see propsal.txt */ + + prog_section statements; /* prog_section_statement */ + prog_section defs; /* prog_section_def */ + prog_section fields; /* prog_section_field */ + prog_section functions; /* prog_section_function */ + prog_section strings; /* What is this? */ + prog_section globals; /* What is this? */ + uint32_t entfield; /* Number of entity fields */ +} prog_header; + /* * Each paramater incerements by 3 since vector types hold * 3 components (x,y,z). @@ -492,6 +516,9 @@ VECTOR_PROT(prog_section_function, code_functions ); VECTOR_PROT(int, code_globals ); VECTOR_PROT(char, code_chars ); +typedef float qcfloat; +typedef int32_t qcint; + /* * code_write -- writes out the compiled file * code_init -- prepares the code file @@ -500,6 +527,7 @@ bool code_write (const char *filename); void code_init (); uint32_t code_genstring (const char *string); uint32_t code_cachedstring(const char *string); +qcint code_alloc_field (size_t qcsize); /*===================================================================*/ /*========================= assembler.c =============================*/ @@ -600,20 +628,6 @@ void asm_init (const char *, FILE **); void asm_close(FILE *); void asm_parse(FILE *); /*===================================================================*/ -/*============================= main.c ==============================*/ -/*===================================================================*/ -enum { - COMPILER_QCC, /* circa QuakeC */ - COMPILER_FTEQCC, /* fteqcc QuakeC */ - COMPILER_QCCX, /* qccx QuakeC */ - COMPILER_GMQCC /* this QuakeC */ -}; -extern bool opts_debug; -extern bool opts_memchk; -extern bool opts_darkplaces_stringtablebug; -extern bool opts_omit_nullcode; -extern int opts_compiler; -/*===================================================================*/ /*============================= ast.c ===============================*/ /*===================================================================*/ #define MEM_VECTOR_PROTO(Towner, Tmem, mem) \ @@ -630,7 +644,7 @@ extern int opts_compiler; size_t name##_count; \ size_t name##_alloc -#define _MEM_VEC_FUN_ADD(Tself, Twhat, mem) \ +#define MEM_VEC_FUN_ADD(Tself, Twhat, mem) \ bool GMQCC_WARN Tself##_##mem##_add(Tself *self, Twhat f) \ { \ Twhat *reall; \ @@ -652,7 +666,7 @@ bool GMQCC_WARN Tself##_##mem##_add(Tself *self, Twhat f) \ return true; \ } -#define _MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ +#define MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ bool GMQCC_WARN Tself##_##mem##_remove(Tself *self, size_t idx) \ { \ size_t i; \ @@ -677,7 +691,7 @@ bool GMQCC_WARN Tself##_##mem##_remove(Tself *self, size_t idx) \ return true; \ } -#define _MEM_VEC_FUN_FIND(Tself, Twhat, mem) \ +#define MEM_VEC_FUN_FIND(Tself, Twhat, mem) \ bool GMQCC_WARN Tself##_##mem##_find(Tself *self, Twhat obj, size_t *idx) \ { \ size_t i; \ @@ -692,7 +706,57 @@ bool GMQCC_WARN Tself##_##mem##_find(Tself *self, Twhat obj, size_t *idx) \ return false; \ } -#define _MEM_VEC_FUN_CLEAR(Tself, mem) \ +#define MEM_VEC_FUN_APPEND(Tself, Twhat, mem) \ +bool GMQCC_WARN Tself##_##mem##_append(Tself *s, Twhat *p, size_t c) \ +{ \ + Twhat *reall; \ + if (s->mem##_count+c >= s->mem##_alloc) { \ + if (!s->mem##_alloc) { \ + s->mem##_alloc = c < 16 ? 16 : c; \ + } else { \ + s->mem##_alloc *= 2; \ + if (s->mem##_count+c >= s->mem##_alloc) { \ + s->mem##_alloc = s->mem##_count+c; \ + } \ + } \ + reall = (Twhat*)mem_a(sizeof(Twhat) * s->mem##_alloc); \ + if (!reall) { \ + return false; \ + } \ + memcpy(reall, s->mem, sizeof(Twhat) * s->mem##_count); \ + mem_d(s->mem); \ + s->mem = reall; \ + } \ + memcpy(&s->mem[s->mem##_count], p, c*sizeof(*p)); \ + s->mem##_count += c; \ + return true; \ +} + +#define MEM_VEC_FUN_RESIZE(Tself, Twhat, mem) \ +bool GMQCC_WARN Tself##_##mem##_resize(Tself *s, size_t c) \ +{ \ + Twhat *reall; \ + if (c > s->mem##_alloc) { \ + reall = (Twhat*)mem_a(sizeof(Twhat) * c); \ + if (!reall) { return false; } \ + memcpy(reall, s->mem, sizeof(Twhat) * s->mem##_count); \ + s->mem##_alloc = c; \ + mem_d(s->mem); \ + s->mem = reall; \ + return true; \ + } \ + s->mem##_count = c; \ + if (c < (s->mem##_alloc / 2)) { \ + reall = (Twhat*)mem_a(sizeof(Twhat) * c); \ + if (!reall) { return false; } \ + memcpy(reall, s->mem, sizeof(Twhat) * c); \ + mem_d(s->mem); \ + s->mem = reall; \ + } \ + return true; \ +} + +#define MEM_VEC_FUN_CLEAR(Tself, mem) \ void Tself##_##mem##_clear(Tself *self) \ { \ if (!self->mem) \ @@ -728,17 +792,18 @@ void Tself##_##mem##_clear(Tself *self) \ } #define MEM_VEC_FUNCTIONS(Tself, Twhat, mem) \ -_MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ -_MEM_VEC_FUN_ADD(Tself, Twhat, mem) +MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ +MEM_VEC_FUN_ADD(Tself, Twhat, mem) #define MEM_VEC_FUNCTIONS_ALL(Tself, Twhat, mem) \ MEM_VEC_FUNCTIONS(Tself, Twhat, mem) \ -_MEM_VEC_FUN_CLEAR(Tself, mem) \ -_MEM_VEC_FUN_FIND(Tself, Twhat, mem) +MEM_VEC_FUN_CLEAR(Tself, mem) \ +MEM_VEC_FUN_FIND(Tself, Twhat, mem) enum store_types { store_global, store_local, /* local, assignable for now, should get promoted later */ + store_param, /* parameters, they are locals with a fixed position */ store_value, /* unassignable */ store_return /* unassignable, at OFS_RETURN */ }; @@ -763,4 +828,166 @@ typedef struct { const char *file; size_t line; } lex_ctx; + +/*===================================================================*/ +/*============================= exec.c ==============================*/ +/*===================================================================*/ + +/* darkplaces has (or will have) a 64 bit prog loader + * where the 32 bit qc program is autoconverted on load. + * Since we may want to support that as well, let's redefine + * float and int here. + */ +typedef union { + qcint _int; + qcint string; + qcint function; + qcint edict; + qcfloat _float; + qcfloat vector[3]; + qcint ivector[3]; +} qcany; + +typedef char qcfloat_size_is_correct [sizeof(qcfloat) == 4 ?1:-1]; +typedef char qcint_size_is_correct [sizeof(qcint) == 4 ?1:-1]; + +enum { + VMERR_OK, + VMERR_TEMPSTRING_ALLOC, + + VMERR_END +}; + +#define VM_JUMPS_DEFAULT 1000000 + +/* execute-flags */ +#define VMXF_DEFAULT 0x0000 /* default flags - nothing */ +#define VMXF_TRACE 0x0001 /* trace: print statements before executing */ +#define VMXF_PROFILE 0x0002 /* profile: increment the profile counters */ + +struct qc_program_s; + +typedef int (*prog_builtin)(struct qc_program_s *prog); + +typedef struct { + qcint stmt; + size_t localsp; + prog_section_function *function; +} qc_exec_stack; + +typedef struct qc_program_s { + char *filename; + + MEM_VECTOR_MAKE(prog_section_statement, code); + MEM_VECTOR_MAKE(prog_section_def, defs); + MEM_VECTOR_MAKE(prog_section_def, fields); + MEM_VECTOR_MAKE(prog_section_function, functions); + MEM_VECTOR_MAKE(char, strings); + MEM_VECTOR_MAKE(qcint, globals); + MEM_VECTOR_MAKE(qcint, entitydata); + MEM_VECTOR_MAKE(bool, entitypool); + + size_t tempstring_start; + size_t tempstring_at; + + qcint vmerror; + + MEM_VECTOR_MAKE(size_t, profile); + + MEM_VECTOR_MAKE(prog_builtin, builtins); + + /* size_t ip; */ + qcint entities; + size_t entityfields; + bool allowworldwrites; + + MEM_VECTOR_MAKE(qcint, localstack); + MEM_VECTOR_MAKE(qc_exec_stack, stack); + size_t statement; + + int argc; /* current arg count for debugging */ +} qc_program; + +qc_program* prog_load(const char *filename); +void prog_delete(qc_program *prog); + +bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long maxjumps); + +char* prog_getstring (qc_program *prog, qcint str); +prog_section_def* prog_entfield (qc_program *prog, qcint off); +prog_section_def* prog_getdef (qc_program *prog, qcint off); +qcany* prog_getedict (qc_program *prog, qcint e); +qcint prog_tempstring(qc_program *prog, const char *_str); + +/*===================================================================*/ +/*======================= main.c commandline ========================*/ +/*===================================================================*/ + +#if 0 +/* 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 */ +} longbit; +#define LONGBIT(bit) { ((bit)/32), ((bit)%32) } +#else +typedef uint32_t longbit; +#define LONGBIT(bit) (bit) +#endif + +/* Used to store the list of flags with names */ +typedef struct { + const char *name; + longbit bit; +} opts_flag_def; + +/*===================================================================*/ +/* list of -f flags, like -fdarkplaces-string-table-bug */ +enum { +# define GMQCC_DEFINE_FLAG(X) X, +# include "flags.def" +# undef GMQCC_DEFINE_FLAG + COUNT_FLAGS +}; +static const opts_flag_def opts_flag_list[] = { +# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(X) }, +# include "flags.def" +# undef GMQCC_DEFINE_FLAG + { NULL, LONGBIT(0) } +}; + +enum { +# define GMQCC_DEFINE_FLAG(X) WARN_##X, +# include "warns.def" +# undef GMQCC_DEFINE_FLAG + COUNT_WARNINGS +}; +static const opts_flag_def opts_warn_list[] = { +# define GMQCC_DEFINE_FLAG(X) { #X, LONGBIT(WARN_##X) }, +# include "warns.def" +# undef GMQCC_DEFINE_FLAG + { NULL, LONGBIT(0) } +}; + +/* other options: */ +enum { + COMPILER_QCC, /* circa QuakeC */ + COMPILER_FTEQCC, /* fteqcc QuakeC */ + COMPILER_QCCX, /* qccx QuakeC */ + COMPILER_GMQCC /* this QuakeC */ +}; +extern uint32_t opts_O; /* -Ox */ +extern const char *opts_output; /* -o file */ +extern int opts_standard; +extern bool opts_debug; +extern bool opts_memchk; + +/*===================================================================*/ +#define OPTS_FLAG(i) (!! (opts_flags[(i)/32] & (1<< ((i)%32)))) +extern uint32_t opts_flags[1 + (COUNT_FLAGS / 32)]; +#define OPTS_WARN(i) (!! (opts_warn[(i)/32] & (1<< ((i)%32)))) +extern uint32_t opts_warn[1 + (COUNT_WARNINGS / 32)]; + #endif