+/*===================================================================*/
+/*========================= assembler.c =============================*/
+/*===================================================================*/
+static const struct {
+ const char *m; /* menomic */
+ const size_t o; /* operands */
+ const size_t l; /* menomic len */
+} asm_instr[] = {
+ { "DONE" , 1, 4 },
+ { "MUL_F" , 3, 5 },
+ { "MUL_V" , 3, 5 },
+ { "MUL_VF" , 3, 6 },
+ { "MUL_Q" , 3, 5 },
+ { "MUL_QF" , 3, 6 },
+ { "MUL_M" , 3, 5 },
+ { "MUL_MF" , 3, 6 },
+ { "DIV" , 0, 3 },
+ { "ADD_F" , 3, 5 },
+ { "ADD_V" , 3, 5 },
+ { "SUB_F" , 3, 5 },
+ { "DUB_V" , 3, 5 },
+ { "EQ_F" , 0, 4 },
+ { "EQ_V" , 0, 4 },
+ { "EQ_S" , 0, 4 },
+ { "EQ_E" , 0, 4 },
+ { "EQ_FNC" , 0, 6 },
+ { "EQ_Q" , 0, 4 },
+ { "EQ_M" , 0, 4 },
+ { "NE_F" , 0, 4 },
+ { "NE_V" , 0, 4 },
+ { "NE_S" , 0, 4 },
+ { "NE_E" , 0, 4 },
+ { "NE_FNC" , 0, 6 },
+ { "NE_Q" , 0, 4 },
+ { "NE_M" , 0, 4 },
+ { "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 },
+ { "FIELD_Q" , 0, 7 },
+ { "FIELD_M" , 0, 7 },
+ { "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 },
+ { "STORE_Q" , 0, 7 },
+ { "STORE_M" , 0, 7 },
+ { "STOREP_F" , 0, 8 },
+ { "STOREP_V" , 0, 8 },
+ { "STOREP_S" , 0, 8 },
+ { "STOREP_ENT", 0, 10},
+ { "STOREP_FLD", 0, 10},
+ { "STOREP_FNC", 0, 10},
+ { "STOREP_Q" , 0, 8 },
+ { "STOREP_M" , 0, 8 },
+ { "RETURN" , 0, 6 },
+ { "NOT_F" , 0, 5 },
+ { "NOT_V" , 0, 5 },
+ { "NOT_S" , 0, 5 },
+ { "NOT_ENT" , 0, 7 },
+ { "NOT_FNC" , 0, 7 },
+ { "INV_Q" , 0, 5 },
+ { "INV_M" , 0, 5 },
+ { "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 */
+};
+
+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) \
+ bool GMQCC_WARN Towner##_##mem##_add(Towner*, Tmem); \
+ bool GMQCC_WARN Towner##_##mem##_remove(Towner*, size_t)
+
+#define MEM_VECTOR_PROTO_ALL(Towner, Tmem, mem) \
+ MEM_VECTOR_PROTO(Towner, Tmem, mem); \
+ bool GMQCC_WARN Towner##_##mem##_find(Towner*, Tmem, size_t*); \
+ void Towner##_##mem##_clear(Towner*)
+
+#define MEM_VECTOR_MAKE(Twhat, name) \
+ Twhat *name; \
+ size_t name##_count; \
+ size_t name##_alloc
+
+#define _MEM_VEC_FUN_ADD(Tself, Twhat, mem) \
+bool GMQCC_WARN Tself##_##mem##_add(Tself *self, Twhat f) \
+{ \
+ Twhat *reall; \
+ if (self->mem##_count == self->mem##_alloc) { \
+ if (!self->mem##_alloc) { \
+ self->mem##_alloc = 16; \
+ } else { \
+ self->mem##_alloc *= 2; \
+ } \
+ reall = (Twhat*)mem_a(sizeof(Twhat) * self->mem##_alloc); \
+ if (!reall) { \
+ return false; \
+ } \
+ memcpy(reall, self->mem, sizeof(Twhat) * self->mem##_count); \
+ mem_d(self->mem); \
+ self->mem = reall; \
+ } \
+ self->mem[self->mem##_count++] = f; \
+ return true; \
+}
+
+#define _MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \
+bool GMQCC_WARN Tself##_##mem##_remove(Tself *self, size_t idx) \
+{ \
+ size_t i; \
+ Twhat *reall; \
+ if (idx >= self->mem##_count) { \
+ return true; /* huh... */ \
+ } \
+ for (i = idx; i < self->mem##_count-1; ++i) { \
+ self->mem[i] = self->mem[i+1]; \
+ } \
+ self->mem##_count--; \
+ if (self->mem##_count < self->mem##_count/2) { \
+ self->mem##_alloc /= 2; \
+ reall = (Twhat*)mem_a(sizeof(Twhat) * self->mem##_count); \
+ if (!reall) { \
+ return false; \
+ } \
+ memcpy(reall, self->mem, sizeof(Twhat) * self->mem##_count); \
+ mem_d(self->mem); \
+ self->mem = reall; \
+ } \
+ return true; \
+}
+
+#define _MEM_VEC_FUN_FIND(Tself, Twhat, mem) \
+bool GMQCC_WARN Tself##_##mem##_find(Tself *self, Twhat obj, size_t *idx) \
+{ \
+ size_t i; \
+ for (i = 0; i < self->mem##_count; ++i) { \
+ if (self->mem[i] == obj) { \
+ if (idx) { \
+ *idx = i; \
+ } \
+ return true; \
+ } \
+ } \
+ return false; \
+}
+
+#define _MEM_VEC_FUN_CLEAR(Tself, mem) \
+void Tself##_##mem##_clear(Tself *self) \
+{ \
+ if (!self->mem) \
+ return; \
+ mem_d((void*) self->mem); \
+ self->mem = NULL; \
+ self->mem##_count = 0; \
+ self->mem##_alloc = 0; \
+}
+
+#define MEM_VECTOR_CLEAR(owner, mem) \
+ if ((owner)->mem) \
+ mem_d((void*)((owner)->mem)); \
+ (owner)->mem = NULL; \
+ (owner)->mem##_count = 0; \
+ (owner)->mem##_alloc = 0
+
+#define MEM_VECTOR_INIT(owner, mem) \
+{ \
+ (owner)->mem = NULL; \
+ (owner)->mem##_count = 0; \
+ (owner)->mem##_alloc = 0; \
+}
+
+#define MEM_VEC_FUNCTIONS(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)
+
+enum store_types {
+ store_global,
+ store_local, /* local, assignable for now, should get promoted later */
+ store_value, /* unassignable */
+ store_return /* unassignable, at OFS_RETURN */
+};
+
+typedef struct {
+ float x, y, z;
+} vector;
+
+typedef float matrix[4][4]; /* OpenGL layout */
+typedef float quaternion[4]; /* order: x, y, z, w */
+#define MATRIX(axis, elem) ((4*(axis)) + (elem))
+#define QUAT_X 0
+#define QUAT_Y 1
+#define QUAT_Z 2
+#define QUAT_W 3
+
+/*
+ * A shallow copy of a lex_file to remember where which ast node
+ * came from.
+ */
+typedef struct {
+ const char *file;
+ size_t line;
+} lex_ctx;