-} const asm_instr[] = {
- [INSTR_DONE] = { "DONE" , 1, 4 },
- [INSTR_MUL_F] = { "MUL_F" , 3, 5 },
- [INSTR_MUL_V] = { "MUL_V" , 3, 5 },
- [INSTR_MUL_FV] = { "MUL_FV" , 3, 6 },
- [INSTR_MUL_VF] = { "MUL_VF" , 3, 6 },
- [INSTR_DIV_F] = { "DIV" , 0, 3 },
- [INSTR_ADD_F] = { "ADD_F" , 3, 5 },
- [INSTR_ADD_V] = { "ADD_V" , 3, 5 },
- [INSTR_SUB_F] = { "SUB_F" , 3, 5 },
- [INSTR_SUB_V] = { "DUB_V" , 3, 5 },
- [INSTR_EQ_F] = { "EQ_F" , 0, 4 },
- [INSTR_EQ_V] = { "EQ_V" , 0, 4 },
- [INSTR_EQ_S] = { "EQ_S" , 0, 4 },
- [INSTR_EQ_E] = { "EQ_E" , 0, 4 },
- [INSTR_EQ_FNC] = { "ES_FNC" , 0, 6 },
- [INSTR_NE_F] = { "NE_F" , 0, 4 },
- [INSTR_NE_V] = { "NE_V" , 0, 4 },
- [INSTR_NE_S] = { "NE_S" , 0, 4 },
- [INSTR_NE_E] = { "NE_E" , 0, 4 },
- [INSTR_NE_FNC] = { "NE_FNC" , 0, 6 },
- [INSTR_LE] = { "LE" , 0, 2 },
- [INSTR_GE] = { "GE" , 0, 2 },
- [INSTR_LT] = { "LT" , 0, 2 },
- [INSTR_GT] = { "GT" , 0, 2 },
- [INSTR_LOAD_F] = { "FIELD_F" , 0, 7 },
- [INSTR_LOAD_V] = { "FIELD_V" , 0, 7 },
- [INSTR_LOAD_S] = { "FIELD_S" , 0, 7 },
- [INSTR_LOAD_ENT] = { "FIELD_ENT" , 0, 9 },
- [INSTR_LOAD_FLD] = { "FIELD_FLD" , 0, 9 },
- [INSTR_LOAD_FNC] = { "FIELD_FNC" , 0, 9 },
- [INSTR_ADDRESS] = { "ADDRESS" , 0, 7 },
- [INSTR_STORE_F] = { "STORE_F" , 0, 7 },
- [INSTR_STORE_V] = { "STORE_V" , 0, 7 },
- [INSTR_STORE_S] = { "STORE_S" , 0, 7 },
- [INSTR_STORE_ENT] = { "STORE_ENT" , 0, 9 },
- [INSTR_STORE_FLD] = { "STORE_FLD" , 0, 9 },
- [INSTR_STORE_FNC] = { "STORE_FNC" , 0, 9 },
- [INSTR_STOREP_F] = { "STOREP_F" , 0, 8 },
- [INSTR_STOREP_V] = { "STOREP_V" , 0, 8 },
- [INSTR_STOREP_S] = { "STOREP_S" , 0, 8 },
- [INSTR_STOREP_ENT] = { "STOREP_ENT", 0, 10},
- [INSTR_STOREP_FLD] = { "STOREP_FLD", 0, 10},
- [INSTR_STOREP_FNC] = { "STOREP_FNC", 0, 10},
- [INSTR_RETURN] = { "RETURN" , 0, 6 },
- [INSTR_NOT_F] = { "NOT_F" , 0, 5 },
- [INSTR_NOT_V] = { "NOT_V" , 0, 5 },
- [INSTR_NOT_S] = { "NOT_S" , 0, 5 },
- [INSTR_NOT_ENT] = { "NOT_ENT" , 0, 7 },
- [INSTR_NOT_FNC] = { "NOT_FNC" , 0, 7 },
- [INSTR_IF] = { "IF" , 0, 2 },
- [INSTR_IFNOT] = { "IFNOT" , 0, 5 },
- [INSTR_CALL0] = { "CALL0" , 0, 5 },
- [INSTR_CALL1] = { "CALL1" , 0, 5 },
- [INSTR_CALL2] = { "CALL2" , 0, 5 },
- [INSTR_CALL3] = { "CALL3" , 0, 5 },
- [INSTR_CALL4] = { "CALL4" , 0, 5 },
- [INSTR_CALL5] = { "CALL5" , 0, 5 },
- [INSTR_CALL6] = { "CALL6" , 0, 5 },
- [INSTR_CALL7] = { "CALL7" , 0, 5 },
- [INSTR_CALL8] = { "CALL8" , 0, 5 },
- [INSTR_STATE] = { "STATE" , 0, 5 },
- [INSTR_GOTO] = { "GOTO" , 0, 4 },
- [INSTR_AND] = { "AND" , 0, 3 },
- [INSTR_OR] = { "OR" , 0, 2 },
- [INSTR_BITAND] = { "BITAND" , 0, 6 },
- [INSTR_BITOR] = { "BITOR" , 0, 5 }
+} asm_instr[] = {
+ { "DONE" , 1, 4 },
+ { "MUL_F" , 3, 5 },
+ { "MUL_V" , 3, 5 },
+ { "MUL_FV" , 3, 6 },
+ { "MUL_VF" , 3, 6 },
+ { "DIV" , 0, 3 },
+ { "ADD_F" , 3, 5 },
+ { "ADD_V" , 3, 5 },
+ { "SUB_F" , 3, 5 },
+ { "SUB_V" , 3, 5 },
+ { "EQ_F" , 0, 4 },
+ { "EQ_V" , 0, 4 },
+ { "EQ_S" , 0, 4 },
+ { "EQ_E" , 0, 4 },
+ { "EQ_FNC" , 0, 6 },
+ { "NE_F" , 0, 4 },
+ { "NE_V" , 0, 4 },
+ { "NE_S" , 0, 4 },
+ { "NE_E" , 0, 4 },
+ { "NE_FNC" , 0, 6 },
+ { "LE" , 0, 2 },
+ { "GE" , 0, 2 },
+ { "LT" , 0, 2 },
+ { "GT" , 0, 2 },
+ { "FIELD_F" , 0, 7 },
+ { "FIELD_V" , 0, 7 },
+ { "FIELD_S" , 0, 7 },
+ { "FIELD_ENT" , 0, 9 },
+ { "FIELD_FLD" , 0, 9 },
+ { "FIELD_FNC" , 0, 9 },
+ { "ADDRESS" , 0, 7 },
+ { "STORE_F" , 0, 7 },
+ { "STORE_V" , 0, 7 },
+ { "STORE_S" , 0, 7 },
+ { "STORE_ENT" , 0, 9 },
+ { "STORE_FLD" , 0, 9 },
+ { "STORE_FNC" , 0, 9 },
+ { "STOREP_F" , 0, 8 },
+ { "STOREP_V" , 0, 8 },
+ { "STOREP_S" , 0, 8 },
+ { "STOREP_ENT", 0, 10},
+ { "STOREP_FLD", 0, 10},
+ { "STOREP_FNC", 0, 10},
+ { "RETURN" , 0, 6 },
+ { "NOT_F" , 0, 5 },
+ { "NOT_V" , 0, 5 },
+ { "NOT_S" , 0, 5 },
+ { "NOT_ENT" , 0, 7 },
+ { "NOT_FNC" , 0, 7 },
+ { "IF" , 0, 2 },
+ { "IFNOT" , 0, 5 },
+ { "CALL0" , 1, 5 },
+ { "CALL1" , 2, 5 },
+ { "CALL2" , 3, 5 },
+ { "CALL3" , 4, 5 },
+ { "CALL4" , 5, 5 },
+ { "CALL5" , 6, 5 },
+ { "CALL6" , 7, 5 },
+ { "CALL7" , 8, 5 },
+ { "CALL8" , 9, 5 },
+ { "STATE" , 0, 5 },
+ { "GOTO" , 0, 4 },
+ { "AND" , 0, 3 },
+ { "OR" , 0, 2 },
+ { "BITAND" , 0, 6 },
+ { "BITOR" , 0, 5 },
+
+ { "END" , 0, 3 } /* virtual assembler instruction */
+};
+/*===================================================================*/
+/*============================= ir.c ================================*/
+/*===================================================================*/
+
+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 */
+};
+
+typedef struct {
+ qcfloat x, y, z;
+} vector;
+
+vector vec3_add (vector, vector);
+vector vec3_sub (vector, vector);
+qcfloat vec3_mulvv(vector, vector);
+vector vec3_mulvf(vector, float);
+
+/*===================================================================*/
+/*============================= exec.c ==============================*/
+/*===================================================================*/
+
+/* TODO: cleanup */
+/*
+ * 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;
+
+ prog_section_statement *code;
+ prog_section_def *defs;
+ prog_section_def *fields;
+ prog_section_function *functions;
+ char *strings;
+ qcint *globals;
+ qcint *entitydata;
+ bool *entitypool;
+
+ const char* *function_stack;
+
+ uint16_t crc16;
+
+ size_t tempstring_start;
+ size_t tempstring_at;
+
+ qcint vmerror;
+
+ size_t *profile;
+
+ prog_builtin *builtins;
+ size_t builtins_count;
+
+ /* size_t ip; */
+ qcint entities;
+ size_t entityfields;
+ bool allowworldwrites;
+
+ qcint *localstack;
+ qc_exec_stack *stack;
+ size_t statement;
+
+ size_t xflags;
+
+ 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);
+
+
+/*===================================================================*/
+/*===================== parser.c commandline ========================*/
+/*===================================================================*/
+
+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 ();
+
+/*===================================================================*/
+/*====================== 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);
+
+/*===================================================================*/
+/*======================= main.c commandline ========================*/
+/*===================================================================*/
+
+#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; /* 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 ==============================*/
+/*===================================================================*/
+typedef struct {
+ const char *name;
+ longbit bit;
+} opts_flag_def;
+
+bool opts_setflag (const char *, bool);
+bool opts_setwarn (const char *, bool);
+bool opts_setwerror(const char *, bool);
+bool opts_setoptim (const char *, bool);
+
+void opts_init (const char *, int, size_t);
+void opts_set (uint32_t *, size_t, bool);
+void opts_setoptimlevel(unsigned int);
+void opts_ini_init (const char *);
+
+enum {
+# define GMQCC_TYPE_FLAGS
+# define GMQCC_DEFINE_FLAG(X) 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) },
+# include "opts.def"
+ { NULL, LONGBIT(0) }
+};
+
+enum {
+# define GMQCC_TYPE_WARNS
+# define GMQCC_DEFINE_FLAG(X) 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) },
+# include "opts.def"
+ { NULL, LONGBIT(0) }