+
+/*===================================================================*/
+/*============================= 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 float qcfloat;
+typedef int32_t qcint;
+
+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);
+
+ 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) 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(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)];
+