#include <string.h>
#include <stdio.h>
#include <ctype.h>
+
+#define GMQCC_VERSION_MAJOR 0
+#define GMQCC_VERSION_MINOR 1
+#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)
+
+/*
+ * We cannoy 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 (0)
+# define true (1)
+# define bool _Bool
+# if __STDC_VERSION__ < 199901L && __GNUC__ < 3
+ typedef int _Bool
+# endif
+# endif /* !__cplusplus */
+
+/*
+ * 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))
+#else
+# define GMQCC_WARN
+#endif
+
/*
* stdint.h and inttypes.h -less subset
* for systems that don't have it, which we must
typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1];
typedef char uint16_size_if_correct [sizeof(uint16_t) == 2?1:-1];
typedef char uint32_size_is_correct [sizeof(uint32_t) == 4?1:-1];
-typedef char int8_size_is_correct [sizeof(int8_t) == 1?1:-1];
+//typedef char int8_size_is_correct [sizeof(int8_t) == 1?1:-1];
typedef char int16_size_if_correct [sizeof(int16_t) == 2?1:-1];
typedef char int32_size_is_correct [sizeof(int32_t) == 4?1:-1];
/* intptr_t / uintptr_t correct size check */
* It's important that this table never exceed 32 keywords, the ascii
* table starts at 33 (and we don't want conflicts)
*/
-#define TOKEN_DO 0
-#define TOKEN_ELSE 1
-#define TOKEN_IF 2
-#define TOKEN_WHILE 3
-#define TOKEN_BREAK 4
-#define TOKEN_CONTINUE 5
-#define TOKEN_RETURN 6
-#define TOKEN_GOTO 7
-#define TOKEN_FOR 8 // extension
-#define TOKEN_TYPEDEF 9 // extension
+enum {
+ TOKEN_DO ,
+ TOKEN_ELSE ,
+ TOKEN_IF ,
+ TOKEN_WHILE ,
+ TOKEN_BREAK ,
+ TOKEN_CONTINUE ,
+ TOKEN_RETURN ,
+ TOKEN_GOTO ,
+ TOKEN_FOR , // extension
+ TOKEN_TYPEDEF , // extension
-// ensure the token types are out of the
-// bounds of anyothers that may conflict.
-#define TOKEN_FLOAT 110
-#define TOKEN_VECTOR 111
-#define TOKEN_STRING 112
-#define TOKEN_ENTITY 113
-#define TOKEN_VOID 114
+ // ensure the token types are out of the
+ // bounds of anyothers that may conflict.
+ TOKEN_FLOAT = 110,
+ TOKEN_VECTOR ,
+ TOKEN_STRING ,
+ TOKEN_ENTITY ,
+ TOKEN_VOID
+};
/*
* Lexer state constants, these are numbers for where exactly in
* error occurs. These numbers must be > where the ascii-table ends
* and > the last type token which is TOKEN_VOID
*/
-#define LEX_COMMENT 1128
-#define LEX_CHRLIT 1129
-#define LEX_STRLIT 1130
-#define LEX_IDENT 1131
+enum {
+ LEX_COMMENT = 1128,
+ LEX_CHRLIT ,
+ LEX_STRLIT ,
+ LEX_IDENT
+};
int lex_token (struct lex_file *);
void lex_reset (struct lex_file *);
//===================================================================
//=========================== util.c ================================
//===================================================================
-void *util_memory_a (unsigned int, unsigned int, const char *);
-void util_memory_d (void *, unsigned int, const char *);
-void util_meminfo ();
+void *util_memory_a (unsigned int, unsigned int, const char *);
+void util_memory_d (void *, unsigned int, const char *);
+void util_meminfo ();
-char *util_strdup (const char *);
-char *util_strrq (char *);
-char *util_strrnl (char *);
-void util_debug (const char *, const char *, ...);
-int util_getline (char **, size_t *, FILE *);
-void util_endianswap(void *, int, int);
+char *util_strdup (const char *);
+char *util_strrq (char *);
+char *util_strrnl (char *);
+void util_debug (const char *, const char *, ...);
+int util_getline (char **, size_t *, FILE *);
+void util_endianswap (void *, int, int);
uint32_t util_crc32(const char *, int, register const short);
# define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
#endif
-#define VECTOR_MAKE(T,N) \
- T* N##_data = NULL; \
- long N##_elements = 0; \
- long N##_allocated = 0; \
- int N##_add(T element) { \
- if (N##_elements == N##_allocated) { \
- if (N##_allocated == 0) { \
- N##_allocated = 12; \
- } else { \
- N##_allocated *= 2; \
- } \
- void *temp = mem_a(N##_allocated * sizeof(T)); \
- if (!temp) { \
- mem_d(temp); \
- return -1; \
- } \
- memcpy(temp, N##_data, (N##_elements * sizeof(T))); \
- mem_d(N##_data); \
- N##_data = (T*)temp; \
- } \
- N##_data[N##_elements] = element; \
- return N##_elements++; \
+/* Builds vector type (usefull for inside structures) */
+#define VECTOR_TYPE(T,N) \
+ T* N##_data = NULL; \
+ long N##_elements = 0; \
+ long N##_allocated = 0
+/* Builds vector add */
+#define VECTOR_CORE(T,N) \
+ int N##_add(T element) { \
+ if (N##_elements == N##_allocated) { \
+ if (N##_allocated == 0) { \
+ N##_allocated = 12; \
+ } else { \
+ N##_allocated *= 2; \
+ } \
+ void *temp = mem_a(N##_allocated * sizeof(T)); \
+ if (!temp) { \
+ mem_d(temp); \
+ return -1; \
+ } \
+ memcpy(temp, N##_data, (N##_elements * sizeof(T))); \
+ mem_d(N##_data); \
+ N##_data = (T*)temp; \
+ } \
+ N##_data[N##_elements] = element; \
+ return N##_elements++; \
+ } \
+ int N##_put(T* elements, size_t len) { \
+ len --; \
+ elements--; \
+ while (N##_add(*++elements) != -1 && len--); \
+ return N##_elements; \
}
+/* Builds a full vector inspot */
+#define VECTOR_MAKE(T,N) \
+ VECTOR_TYPE(T,N); \
+ VECTOR_CORE(T,N)
+/* Builds a vector add function pointer for inside structures */
+#define VECTOR_IMPL(T,N) int (*N##_add)(T)
//===================================================================
//=========================== code.c ================================
//===================================================================
-#define TYPE_VOID 0
-#define TYPE_STRING 1
-#define TYPE_FLOAT 2
-#define TYPE_VECTOR 3
-#define TYPE_ENTITY 4
-#define TYPE_FIELD 5
-#define TYPE_FUNCTION 6
-#define TYPE_POINTER 7
+enum {
+ TYPE_VOID ,
+ TYPE_STRING ,
+ TYPE_FLOAT ,
+ TYPE_VECTOR ,
+ TYPE_ENTITY ,
+ TYPE_FIELD ,
+ TYPE_FUNCTION ,
+ TYPE_POINTER
+};
/*
* Each paramater incerements by 3 since vector types hold
INSTR_AND,
INSTR_OR,
INSTR_BITAND,
- INSTR_BITOR
+ INSTR_BITOR,
+
+ /* Virtual instructions used by the IR
+ * Keep at the end!
+ */
+ VINSTR_PHI,
+ VINSTR_JUMP,
+ VINSTR_COND,
};
/*
int code_functions_add (prog_section_function);
int code_globals_add (int);
int code_chars_add (char);
-int code_strings_add (const char *); /* function wrapping code_chars_add */
+int code_statements_put(prog_section_statement*, size_t);
+int code_defs_put (prog_section_def*, size_t);
+int code_fields_put (prog_section_field*, size_t);
+int code_functions_put (prog_section_function*, size_t);
+int code_globals_put (int*, size_t);
+int code_chars_put (char*, size_t);
extern long code_statements_elements;
extern long code_chars_elements;
extern long code_globals_elements;
COMPILER_QCCX, /* qccx QuakeC */
COMPILER_GMQCC /* this QuakeC */
};
-extern int opts_debug;
-extern int opts_memchk;
+extern bool opts_debug;
+extern bool opts_memchk;
+extern bool opts_darkplaces_stringtablebug;
+extern bool opts_omit_nullcode;
+extern int opts_compiler;
#endif