/*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014, 2015
* Dale Weiler
* Wolfgang Bumiller
*
#define GMQCC_HDR
#include <stdarg.h>
#include <stddef.h>
-#include <time.h> /* TODO: remove?*/
-
-/*
- * Disable some over protective warnings in visual studio because fixing them is a waste
- * of my time.
- */
-#ifdef _MSC_VER
-# pragma warning(disable : 4244 ) /* conversion from 'int' to 'float', possible loss of data */
-#endif /*! _MSC_VER */
+#include <time.h>
#define GMQCC_VERSION_MAJOR 0
-#define GMQCC_VERSION_MINOR 4
-#define GMQCC_VERSION_PATCH 0
-#define GMQCC_VERSION_BUILD(J,N,P) (((J)<<16)|((N)<<8)|(P))
-#define GMQCC_VERSION \
- GMQCC_VERSION_BUILD(GMQCC_VERSION_MAJOR, GMQCC_VERSION_MINOR, GMQCC_VERSION_PATCH)
-/* Undefine the following on a release-tag: */
-#define GMQCC_VERSION_TYPE_DEVEL
-
-/* Full version string in case we need it */
-#ifdef GMQCC_VERSION_TYPE_DEVEL
+#define GMQCC_VERSION_MINOR 3
+#define GMQCC_VERSION_PATCH 6
+#define GMQCC_VERSION ((GMQCC_VERSION_MAJOR<<16)|(GMQCC_VERSION_MINOR<<8)|GMQCC_VERSION_PATCH)
+
+#ifdef GMQCC_VERSION_TYPE_RELEASE
# ifdef GMQCC_GITINFO
# define GMQCC_DEV_VERSION_STRING "git build: " GMQCC_GITINFO "\n"
# elif defined(GMQCC_VERSION_TYPE_DEVEL)
" Built " __DATE__ " " __TIME__ \
"\n" GMQCC_DEV_VERSION_STRING
-/*
- * We cannot rely on C99 at all, since compilers like MSVC
- * simply don't support it. We define our own boolean type
- * as a result (since we cannot include <stdbool.h>). For
- * compilers that are in 1999 mode (C99 compliant) we can use
- * the language keyword _Bool which can allow for better code
- * on GCC and GCC-like compilers, opposed to `int`.
- */
#ifndef __cplusplus
-# ifdef false
-# undef false
-# endif /*! false */
-# ifdef true
-# undef true
-# endif /*! true */
-# define false (unsigned)(0)
-# define true (unsigned)(1)
-# ifdef __STDC_VERSION__
-# if __STDC_VERSION__ < 199901L && __GNUC__ < 3
- typedef int bool;
-# else
- typedef _Bool bool;
-# endif /*! __STDC_VERSION__ < 199901L && __GNUC__ < 3 */
-# else
- typedef int bool;
-# endif /*! __STDC_VERSION__ */
-#endif /*! __cplusplus */
+# define false (unsigned char)(0)
+# define true (unsigned char)(1)
+ typedef unsigned char bool;
+#endif
-/*
- * Of some functions which are generated we want to make sure
- * that the result isn't ignored. To find such function calls,
- * we use this macro.
- */
#if defined(__GNUC__) || defined(__CLANG__)
-# define GMQCC_WARN __attribute__((warn_unused_result))
-# define GMQCC_USED __attribute__((used))
-#else
-# define GMQCC_WARN
-# define GMQCC_USED
-#endif /*! defined(__GNUC__) || defined (__CLANG__) */
-
-/*
- * Inline is not supported in < C90, however some compilers
- * like gcc and clang might have an inline attribute we can
- * use if present.
- */
-#ifdef __STDC_VERSION__
-# if __STDC_VERSION__ < 199901L
-# if defined(__GNUC__) || defined (__CLANG__)
-# if __GNUC__ < 2
-# define GMQCC_INLINE
-# else
-# define GMQCC_INLINE __attribute__ ((always_inline))
-# endif /*! __GNUC__ < 2 */
-# else
-# define GMQCC_INLINE
-# endif /*! defined(__GNUC__) || defined (__CLANG__) */
-# else
-# define GMQCC_INLINE inline
-# endif /*! __STDC_VERSION < 199901L */
-/*
- * Visual studio has __forcinline we can use. So lets use that
- * I suspect it also has just __inline of some sort, but our use
- * of inline is correct (not guessed), WE WANT IT TO BE INLINE
- */
-#elif defined(_MSC_VER)
-# define GMQCC_INLINE __forceinline
-#else
-# define GMQCC_INLINE
-#endif /*! __STDC_VERSION__ */
-
-/*
- * noreturn is present in GCC and clang
- * it's required for _ast_node_destory otherwise -Wmissing-noreturn
- * in clang complains about there being no return since abort() is
- * called.
- */
-#if (defined(__GNUC__) && __GNUC__ >= 2) || defined(__CLANG__)
-# define GMQCC_NORETURN __attribute__ ((noreturn))
-#else
-# define GMQCC_NORETURN
-#endif /*! (defined(__GNUC__) && __GNUC__ >= 2) || defined (__CLANG__) */
-
-#if (defined(__GNUC__)) || defined(__CLANG__)
+# include <stdint.h>
+# if (__GNUC__ >= 2) || defined(__CLANG__)
+# define GMQCC_NORETURN __attribute__((noreturn))
+# define GMQCC_FORCEINLINE __attribute__((always_inline))
+# define GMQCC_INLINE __inline
+# endif
# define GMQCC_LIKELY(X) __builtin_expect((X), 1)
# define GMQCC_UNLIKELY(X) __builtin_expect((X), 0)
+# define GMQCC_WARN __attribute__((warn_unused_result))
+# define GMQCC_USED __attribute__((used))
+# define GMQCC_RESTRICT __restrict__
#else
+# ifdef _MSC_VER
+ /* conversion from 'int' to 'float', possible loss of data */
+# pragma warning(disable : 4244)
+
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+ typedef __int16 int16_t;
+ typedef __int32 int32_t;
+ typedef __int64 int64_t;
+# define GMQCC_NORETURN __declspec(noreturn)
+# define GMQCC_FORCEINLINE __forceinline
+# define GMQCC_INLINE __inline
+# define GMQCC_RESTRICT __restrict
+# else
+# define GMQCC_NORETURN
+# define GMQCC_FORCEINLINE
+# define GMQCC_INLINE
+# define GMQCC_RESTRICT
+# endif
# define GMQCC_LIKELY(X) (X)
# define GMQCC_UNLIKELY(X) (X)
+# define GMQCC_WARN
+# define GMQCC_USED
#endif
-#define GMQCC_ARRAY_COUNT(X) (sizeof(X) / sizeof((X)[0]))
-
-#ifndef _MSC_VER
-# include <stdint.h>
-#else
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
- typedef unsigned __int64 uint64_t;
-
- typedef __int16 int16_t;
- typedef __int32 int32_t;
- typedef __int64 int64_t;
-#endif /*! _MSC_VER */
-
-/*
- * 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
# else
# define PLATFORM_BYTE_ORDER -1
# endif
-#endif /*! !defined (PLATFORM_BYTE_ORDER) */
+#endif
+
+#define GMQCC_ARRAY_COUNT(X) (sizeof(X) / sizeof((X)[0]))
/* stat.c */
void stat_info (void);
char *stat_mem_strdup (const char *, size_t, const char *, bool);
-void *stat_mem_reallocate(void *, size_t, size_t, const char *);
-void stat_mem_deallocate(void *);
-void *stat_mem_allocate (size_t, size_t, const char *);
+void stat_mem_deallocate(void *, size_t, const char *);
+void *stat_mem_reallocate(void *, size_t, size_t, const char *, const char *);
+void *stat_mem_allocate (size_t, size_t, const char *, const char *);
-#define mem_a(SIZE) stat_mem_allocate ((SIZE), __LINE__, __FILE__)
-#define mem_d(PTRN) stat_mem_deallocate((void*)(PTRN))
-#define mem_r(PTRN, SIZE) stat_mem_reallocate((void*)(PTRN), (SIZE), __LINE__, __FILE__)
-#define mem_af(SIZE, FILE, LINE) stat_mem_allocate ((SIZE), (LINE), (FILE))
+#define mem_a(SIZE) stat_mem_allocate ((SIZE), __LINE__, __FILE__, #SIZE)
+#define mem_d(PTRN) stat_mem_deallocate((void*)(PTRN), __LINE__, __FILE__)
+#define mem_r(PTRN, SIZE) stat_mem_reallocate((void*)(PTRN), (SIZE), __LINE__, __FILE__, #SIZE)
+#define mem_af(SIZE, FILE, LINE) stat_mem_allocate ((SIZE), (LINE), (FILE), #SIZE)
/* TODO: rename to mem variations */
#define util_strdup(SRC) stat_mem_strdup((char*)(SRC), __LINE__, __FILE__, false)
#define util_isprint(a) (((unsigned)(a)-0x20) < 0x5F)
#define util_isspace(a) (((a) >= 9 && (a) <= 13) || (a) == ' ')
-bool util_strupper (const char *);
-bool util_strdigit (const char *);
-void util_endianswap (void *, size_t, unsigned int);
+bool util_strupper(const char *);
+bool util_strdigit(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);
const char *util_ctime (const time_t *timer);
typedef struct fs_file_s fs_file_t;
-bool util_isatty (fs_file_t *);
+
+bool util_isatty(fs_file_t *);
+size_t hash(const char *key);
/*
* A flexible vector implementation: all vector pointers contain some
/* hidden interface */
void _util_vec_grow(void **a, size_t i, size_t s);
+void _util_vec_delete(void *vec, size_t line, const char *file);
+
#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))) : \
)
/* exposed interface */
-#define vec_meta(A) (((vector_t*)((void*)A)) - 1)
-#define vec_free(A) ((void)((A) ? (mem_d((void*)vec_meta(A)), (A) = NULL) : 0))
+#define vec_meta(A) ((vector_t*)(((char *)(A)) - (sizeof(vector_t) + 4)))
+#define vec_free(A) ((void)((A) ? (_util_vec_delete((void *)(A), __LINE__, __FILE__), (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)])
/* TODO: elide */
extern const char *util_instr_str[VINSTR_END];
+void util_swap_header (prog_header_t *code_header);
+void util_swap_statements (prog_section_statement_t *statements);
+void util_swap_defs_fields(prog_section_both_t *section);
+void util_swap_functions (prog_section_function_t *functions);
+void util_swap_globals (int32_t *globals);
typedef float qcfloat_t;
typedef int32_t qcint_t;
} qc_exec_stack_t;
typedef struct qc_program_s {
- char *filename;
+ char *filename;
prog_section_statement_t *code;
prog_section_def_t *defs;
prog_section_def_t *fields;
prog_section_function_t *functions;
- char *strings;
- qcint_t *globals;
- qcint_t *entitydata;
- bool *entitypool;
+ char *strings;
+ qcint_t *globals;
+ qcint_t *entitydata;
+ bool *entitypool;
- const char* *function_stack;
+ const char* *function_stack;
uint16_t crc16;
size_t xflags;
int argc; /* current arg count for debugging */
+
+ /* cached fields */
+ struct {
+ qcint_t frame;
+ qcint_t nextthink;
+ qcint_t think;
+ } cached_fields;
+
+ struct {
+ qcint_t self;
+ qcint_t time;
+ } cached_globals;
+
+ bool supports_state; /* is INSTR_STATE supported? */
} qc_program_t;
qc_program_t* prog_load (const char *filename, bool ignoreversion);
COMPILER_GMQCC /* this QuakeC */
} opts_std_t;
-typedef union {
- bool B;
- uint16_t U16;
- uint32_t U32;
- char *STR;
+typedef struct {
+ union {
+ bool b;
+ uint16_t u16;
+ uint32_t u32;
+
+ union {
+ char *p;
+ const char *c;
+ } str;
+ } data;
+
+ bool allocated;
} opt_value_t;
extern opts_cmd_t opts;
-#define OPTS_GENERIC(f,i) (!! (((f)[(i)/32]) & (1<< (unsigned)((i)%32))))
+#define OPTS_GENERIC(f,i) (!! (((f)[(i)/32]) & (1U << (unsigned)((i)%32))))
+
#define OPTS_FLAG(i) OPTS_GENERIC(opts.flags, (i))
#define OPTS_WARN(i) OPTS_GENERIC(opts.warn, (i))
#define OPTS_WERROR(i) OPTS_GENERIC(opts.werror, (i))
#define OPTS_OPTIMIZATION(i) OPTS_GENERIC(opts.optimization, (i))
-#define OPTS_OPTION_BOOL(X) (opts.options[X].B)
-#define OPTS_OPTION_U16(X) (opts.options[X].U16)
-#define OPTS_OPTION_U32(X) (opts.options[X].U32)
-#define OPTS_OPTION_STR(X) (opts.options[X].STR)
+
+#define OPTS_OPTION_DUPED(X) (opts.options[X].allocated)
+#define OPTS_OPTION_BOOL(X) (opts.options[X].data.b)
+#define OPTS_OPTION_U16(X) (opts.options[X].data.u16)
+#define OPTS_OPTION_U32(X) (opts.options[X].data.u32)
+#define OPTS_OPTION_STR(X) (opts.options[X].data.str.c)
+#define OPTS_OPTION_DUP(X) *(OPTS_OPTION_DUPED(X)=true, &(opts.options[X].data.str.p))
#endif /*! GMQCC_HDR */