+ *windows makes these prefixed because they're C99
+ * TODO: utility versions that are type-safe and not
+ * just plain textual subsitution.
+ */
+#ifdef _MSC_VER
+# define snprintf(X, Y, Z, ...) _snprintf(X, Y, Z, __VA_ARGS__)
+ /* strtof doesn't exist -> strtod does though :) */
+# define strtof(X, Y) (float)(strtod(X, Y))
+#endif
+
+/*
+ * Very roboust way at determining endianess at compile time: this handles
+ * almost every possible situation. Otherwise a runtime check has to be
+ * performed.
+ */
+#define GMQCC_BYTE_ORDER_LITTLE 1234
+#define GMQCC_BYTE_ORDER_BIG 4321
+
+#if defined (__GNUC__) || defined (__GNU_LIBRARY__)
+# if defined (__FreeBSD__) || defined (__OpenBSD__)
+# include <sys/endian.h>
+# elif defined (BSD) && (BSD >= 199103) || defined (__DJGPP__) || defined (__CYGWIN32__)
+# include <machine/endiane.h>
+# elif defined (__APPLE__)
+# if defined (__BIG_ENDIAN__) && !defined(BIG_ENDIAN)
+# define BIG_ENDIAN
+# elif defined (__LITTLE_ENDIAN__) && !defined (LITTLE_ENDIAN)
+# define LITTLE_ENDIAN
+# endif
+# elif !defined (__MINGW32__)
+# include <endian.h>
+# if !defined (__BEOS__)
+# include <byteswap.h>
+# endif
+# endif
+#endif
+#if !defined(PLATFORM_BYTE_ORDER)
+# if defined (LITTLE_ENDIAN) || defined (BIG_ENDIAN)
+# if defined (LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif !defined (LITTLE_ENDIAN) && defined (BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# elif defined (BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif defined (BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# endif
+# elif defined (_LITTLE_ENDIAN) || defined (_BIG_ENDIAN)
+# if defined (_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif !defined (_LITTLE_ENDIAN) && defined (_BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# elif defined (_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif defined (_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# endif
+# elif defined (__LITTLE_ENDIAN__) || defined (__BIG_ENDIAN__)
+# if defined (__LITTLE_ENDIAN__) && !defined (__BIG_ENDIAN__)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif !defined (__LITTLE_ENDIAN__) && defined (__BIG_ENDIAN__)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# elif defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __LITTLE_ENDIAN__)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# endif
+# endif
+#endif
+#if !defined (PLATFORM_BYTE_ORDER)
+# if defined (__alpha__) || defined (__alpha) || defined (i386) || \
+ defined (__i386__) || defined (_M_I86) || defined (_M_IX86) || \
+ defined (__OS2__) || defined (sun386) || defined (__TURBOC__) || \
+ defined (vax) || defined (vms) || defined (VMS) || \
+ defined (__VMS) || defined (__x86_64__) || defined (_M_IA64) || \
+ defined (_M_X64) || defined (__i386) || defined (__x86_64)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE
+# elif defined (AMIGA) || defined (applec) || defined (__AS400__) || \
+ defined (_CRAY) || defined (__hppa) || defined (__hp9000) || \
+ defined (ibm370) || defined (mc68000) || defined (m68k) || \
+ defined (__MRC__) || defined (__MVS__) || defined (__MWERKS__) || \
+ defined (sparc) || defined (__sparc) || defined (SYMANTEC_C) || \
+ defined (__TANDEM) || defined (THINK_C) || defined (__VMCMS__) || \
+ defined (__PPC__) || defined (__PPC) || defined (PPC)
+# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG
+# else
+# define PLATFORM_BYTE_ORDER -1
+# endif
+#endif
+
+
+
+/*===================================================================*/
+/*=========================== 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_meminfo ();
+
+bool util_filexists (const char *);
+bool util_strupper (const char *);
+bool util_strdigit (const char *);
+char *util_strdup (const char *);
+void util_debug (const char *, const char *, ...);
+void util_endianswap (void *, size_t, unsigned int);
+
+size_t util_strtocmd (const char *, char *, size_t);
+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();
+
+#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_r(x, n) util_memory_r((void*)(x), (n), __LINE__, __FILE__)
+#endif
+
+/*
+ * A flexible vector implementation: all vector pointers contain some
+ * data about themselfs exactly - sizeof(vector_t) behind the pointer
+ * this data is represented in the structure below. Doing this allows
+ * us to use the array [] to access individual elements from the vector
+ * opposed to using set/get methods.
+ */
+typedef struct {
+ size_t allocated;
+ size_t used;
+
+ /* can be extended now! whoot */
+} vector_t;
+
+/* hidden interface */
+void _util_vec_grow(void **a, size_t i, size_t s);
+#define GMQCC_VEC_WILLGROW(X,Y) ( \
+ ((!(X) || vec_meta(X)->used + Y >= vec_meta(X)->allocated)) ? \
+ (void)_util_vec_grow(((void**)&(X)), (Y), sizeof(*(X))) : \
+ (void)0 \
+)
+
+/* 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_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_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((A)+(I),(A)+((I)+(N)),sizeof(*(A))*(vec_meta(A)->used-(I)-(N))),vec_meta(A)->used-=(N)
+
+typedef struct hash_table_t {
+ size_t size;
+ struct hash_node_t **table;
+} hash_table_t, *ht;
+
+/*
+ * hashtable implementation:
+ *
+ * Note:
+ * 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_htnew(size) -- to make a new hashtable
+ * util_htset(table, key, value, sizeof(value)) -- to set something in the table
+ * util_htget(table, key) -- to get something from the table
+ * util_htdel(table) -- to delete the table
+ *
+ * example of use:
+ *
+ * ht foo = util_htnew(1024);
+ * int data = 100;
+ * char *test = "hello world\n";
+ * util_htset(foo, "foo", (void*)&data);
+ * util_gtset(foo, "bar", (void*)test);
+ *
+ * printf("foo: %d, bar %s",
+ * *((int *)util_htget(foo, "foo")),
+ * ((char*)util_htget(foo, "bar"))
+ * );
+ *
+ * util_htdel(foo);
+ */
+hash_table_t *util_htnew (size_t size);
+void util_htset (hash_table_t *ht, const char *key, void *value);
+void util_htdel (hash_table_t *ht);
+size_t util_hthash(hash_table_t *ht, const char *key);
+void util_htseth(hash_table_t *ht, const char *key, size_t hash, void *value);
+
+void *util_htget (hash_table_t *ht, const char *key);
+void *util_htgeth(hash_table_t *ht, const char *key, size_t hash);
+/*===================================================================*/
+/*============================ file.c ===============================*/
+/*===================================================================*/
+GMQCC_INLINE void file_close (FILE *);
+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_seek (FILE *, long int, int);
+
+GMQCC_INLINE size_t file_read (void *, size_t, size_t, FILE *);
+GMQCC_INLINE size_t file_write (const void *, size_t, size_t, FILE *);
+
+GMQCC_INLINE FILE *file_open (const char *, const char *);
+/*NOINLINE*/ int file_getline(char **, size_t *, FILE *);
+
+
+/*===================================================================*/
+/*=========================== code.c ================================*/
+/*===================================================================*/
+
+/* TODO: cleanup */
+/* Note: if you change the order, fix type_sizeof in ir.c */
+enum {
+ TYPE_VOID ,
+ TYPE_STRING ,
+ TYPE_FLOAT ,
+ TYPE_VECTOR ,
+ TYPE_ENTITY ,
+ TYPE_FIELD ,
+ TYPE_FUNCTION ,
+ TYPE_POINTER ,
+ TYPE_INTEGER ,
+ TYPE_VARIANT ,
+ TYPE_STRUCT ,
+ TYPE_UNION ,
+ TYPE_ARRAY ,
+
+ TYPE_COUNT
+};
+
+/* const/var qualifiers */
+#define CV_NONE 0
+#define CV_CONST 1
+#define CV_VAR -1
+#define CV_WRONG 0x8000 /* magic number to help parsing */
+
+extern const char *type_name [TYPE_COUNT];
+extern uint16_t type_store_instr [TYPE_COUNT];
+extern uint16_t field_store_instr[TYPE_COUNT];
+
+/*
+ * could use type_store_instr + INSTR_STOREP_F - INSTR_STORE_F
+ * but this breaks when TYPE_INTEGER is added, since with the enhanced
+ * instruction set, the old ones are left untouched, thus the _I instructions
+ * are at a seperate place.
+ */
+extern uint16_t type_storep_instr[TYPE_COUNT];
+extern uint16_t type_eq_instr [TYPE_COUNT];
+extern uint16_t type_ne_instr [TYPE_COUNT];
+extern uint16_t type_not_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;
+ uint16_t skip;
+
+ 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;
+ prog_section globals;
+ uint32_t entfield; /* Number of entity fields */
+} prog_header;
+
+/*
+ * Each paramater incerements by 3 since vector types hold
+ * 3 components (x,y,z).
+ */
+#define OFS_NULL 0
+#define OFS_RETURN 1
+#define OFS_PARM0 (OFS_RETURN+3)
+#define OFS_PARM1 (OFS_PARM0 +3)
+#define OFS_PARM2 (OFS_PARM1 +3)
+#define OFS_PARM3 (OFS_PARM2 +3)
+#define OFS_PARM4 (OFS_PARM3 +3)
+#define OFS_PARM5 (OFS_PARM4 +3)
+#define OFS_PARM6 (OFS_PARM5 +3)
+#define OFS_PARM7 (OFS_PARM6 +3)
+
+typedef struct {
+ uint16_t opcode;
+
+ /* operand 1 */
+ union {
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
+ } o1;
+ /* operand 2 */
+ union {
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
+ } o2;
+ /* operand 3 */
+ union {
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
+ } o3;
+
+ /*
+ * This is the same as the structure in darkplaces
+ * {
+ * unsigned short op;
+ * short a,b,c;
+ * }
+ * But this one is more sane to work with, and the
+ * type sizes are guranteed.
+ */
+} prog_section_statement;
+
+typedef struct {
+ /*
+ * The types:
+ * 0 = ev_void
+ * 1 = ev_string
+ * 2 = ev_float
+ * 3 = ev_vector
+ * 4 = ev_entity
+ * 5 = ev_field
+ * 6 = ev_function
+ * 7 = ev_pointer -- engine only
+ * 8 = ev_bad -- engine only
+ */
+ uint16_t type;
+ uint16_t offset;
+ uint32_t name;
+} prog_section_both;
+
+typedef prog_section_both prog_section_def;
+typedef prog_section_both prog_section_field;
+
+/* this is ORed to the type */
+#define DEF_SAVEGLOBAL (1<<15)
+#define DEF_TYPEMASK ((1<<15)-1)
+
+typedef struct {
+ int32_t entry; /* in statement table for instructions */
+ uint32_t firstlocal; /* First local in local table */
+ uint32_t locals; /* Total ints of params + locals */
+ uint32_t profile; /* Always zero (engine uses this) */
+ uint32_t name; /* name of function in string table */
+ uint32_t file; /* file of the source file */
+ int32_t nargs; /* number of arguments */
+ uint8_t argsize[8]; /* size of arguments (keep 8 always?) */
+} prog_section_function;
+
+/*
+ * Instructions