mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-31 03:50:36 +00:00
All code is now C89/C90 compat
This commit is contained in:
parent
206952b920
commit
3e7a8c0e78
10 changed files with 361 additions and 263 deletions
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
CC ?= clang
|
||||
CFLAGS += -Wall -pedantic-errors -std=c99
|
||||
CFLAGS += -Wall -pedantic-errors -std=c90
|
||||
OBJ = main.o \
|
||||
lex.o \
|
||||
error.o \
|
||||
|
|
38
asm.c
38
asm.c
|
@ -77,7 +77,7 @@ void asm_clear() {
|
|||
* globals with no assignments are globals. Function body types
|
||||
* are locals.
|
||||
*/
|
||||
static inline bool asm_parse_type(const char *skip, size_t line, asm_state *state) {
|
||||
static GMQCC_INLINE bool asm_parse_type(const char *skip, size_t line, asm_state *state) {
|
||||
if (!(strstr(skip, "FLOAT:") == &skip[0]) &&
|
||||
(strstr(skip, "VECTOR:") == &skip[0]) &&
|
||||
(strstr(skip, "ENTITY:") == &skip[0]) &&
|
||||
|
@ -141,7 +141,7 @@ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *stat
|
|||
* names among other things. Ensures valid name as well, and even
|
||||
* internal engine function selection.
|
||||
*/
|
||||
static inline bool asm_parse_func(const char *skip, size_t line, asm_state *state) {
|
||||
static GMQCC_INLINE bool asm_parse_func(const char *skip, size_t line, asm_state *state) {
|
||||
if (*state == ASM_FUNCTION && (strstr(skip, "FUNCTION:") == &skip[0]))
|
||||
return false;
|
||||
|
||||
|
@ -169,6 +169,9 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
* to determine this.
|
||||
*/
|
||||
if (strchr(name, ',')) {
|
||||
prog_section_function function;
|
||||
prog_section_def def;
|
||||
|
||||
char *find = strchr(name, ',') + 1;
|
||||
|
||||
/* skip whitespace */
|
||||
|
@ -197,21 +200,20 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
* global (optional)
|
||||
* name
|
||||
*/
|
||||
code_functions_add((prog_section_function){
|
||||
-atoi(find), /* needs to be negated */
|
||||
0, 0, 0,
|
||||
.name = code_chars_elements,
|
||||
0, 0,{0}
|
||||
});
|
||||
code_defs_add((prog_section_def){
|
||||
.type = TYPE_FUNCTION,
|
||||
.offset = code_globals_elements,
|
||||
.name = code_chars_elements
|
||||
});
|
||||
code_globals_add(code_chars_elements);
|
||||
|
||||
code_chars_put(name, strlen(name));
|
||||
code_chars_add('\0');
|
||||
function.entry = -atoi(find);
|
||||
function.firstlocal = 0;
|
||||
function.profile = 0;
|
||||
function.name = code_chars_elements;
|
||||
function.file = 0;
|
||||
function.nargs = 0;
|
||||
def.type = TYPE_FUNCTION;
|
||||
def.offset = code_globals_elements;
|
||||
def.name = code_chars_elements;
|
||||
code_functions_add(function);
|
||||
code_defs_add (def);
|
||||
code_globals_add (code_chars_elements);
|
||||
code_chars_put (name, strlen(name));
|
||||
code_chars_add ('\0');
|
||||
|
||||
/*
|
||||
* Sanatize the numerical constant used to select the
|
||||
|
@ -225,7 +227,7 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
printf("invalid internal function identifier, must be all numeric\n");
|
||||
|
||||
} else {
|
||||
/* TODO: function bodies */
|
||||
printf("Found function %s\n", name);
|
||||
}
|
||||
|
||||
mem_d(copy);
|
||||
|
|
15
ast.c
15
ast.c
|
@ -27,10 +27,10 @@
|
|||
#include "gmqcc.h"
|
||||
#include "ast.h"
|
||||
|
||||
#define ast_instantiate(T, ctx, destroyfn) \
|
||||
T *self = (T*)mem_a(sizeof(T)); \
|
||||
ast_node_init((ast_node*)self, ctx); \
|
||||
( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn;
|
||||
#define ast_instantiate(T, ctx, destroyfn) \
|
||||
T* self = (T*)mem_a(sizeof(T)); \
|
||||
ast_node_init((ast_node*)self, ctx); \
|
||||
( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
|
||||
|
||||
/* It must not be possible to get here. */
|
||||
static void _ast_node_destroy(ast_node *self)
|
||||
|
@ -180,6 +180,8 @@ void ast_block_delete(ast_block *self)
|
|||
|
||||
ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
||||
{
|
||||
ast_instantiate(ast_function, ctx, ast_function_delete);
|
||||
|
||||
if (!vtype)
|
||||
return NULL;
|
||||
if (vtype->isconst)
|
||||
|
@ -187,8 +189,6 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
|||
if (vtype->vtype != TYPE_FUNCTION)
|
||||
return NULL;
|
||||
|
||||
ast_instantiate(ast_function, ctx, ast_function_delete);
|
||||
|
||||
self->vtype = vtype;
|
||||
self->name = name ? util_strdup(name) : NULL;
|
||||
MEM_VECTOR_INIT(self, blocks);
|
||||
|
@ -241,6 +241,7 @@ bool ast_value_codegen(ast_value *self, ast_function *func, ir_value **out)
|
|||
|
||||
bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
||||
{
|
||||
ir_value *v = NULL;
|
||||
if (self->isconst && self->vtype == TYPE_FUNCTION)
|
||||
{
|
||||
ir_function *func = ir_builder_create_function(ir, self->name);
|
||||
|
@ -252,7 +253,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
|||
return true;
|
||||
}
|
||||
|
||||
ir_value *v = ir_builder_create_global(ir, self->name, self->vtype);
|
||||
v = ir_builder_create_global(ir, self->name, self->vtype);
|
||||
if (!v)
|
||||
return false;
|
||||
|
||||
|
|
136
code.c
136
code.c
|
@ -84,6 +84,10 @@ VECTOR_MAKE(int, code_globals );
|
|||
VECTOR_MAKE(char, code_chars );
|
||||
|
||||
void code_init() {
|
||||
prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
|
||||
prog_section_statement empty_statement = {0,{0},{0},{0}};
|
||||
int i = 0;
|
||||
|
||||
/* omit creation of null code */
|
||||
if (opts_omit_nullcode)
|
||||
return;
|
||||
|
@ -92,10 +96,7 @@ void code_init() {
|
|||
* The way progs.dat is suppose to work is odd, there needs to be
|
||||
* some null (empty) statements, functions, and 28 globals
|
||||
*/
|
||||
prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
|
||||
prog_section_statement empty_statement = {0,{0},{0},{0}};
|
||||
int i;
|
||||
for(i = 0; i < 28; i++)
|
||||
for(; i < 28; i++)
|
||||
code_globals_add(0);
|
||||
|
||||
code_chars_add ('\0');
|
||||
|
@ -104,6 +105,19 @@ void code_init() {
|
|||
}
|
||||
|
||||
void code_test() {
|
||||
prog_section_def d1 = { TYPE_VOID, 28, 1 };
|
||||
prog_section_def d2 = { TYPE_FUNCTION, 29, 8 };
|
||||
prog_section_def d3 = { TYPE_STRING, 30, 14};
|
||||
prog_section_function f1 = { 1, 0, 0, 0, 1, 0,0, {0}};
|
||||
prog_section_function f2 = {-4, 0, 0, 0, 8, 0,0, {0}};
|
||||
prog_section_function f3 = { 0, 0, 0, 0, 14+13, 0,0, {0}};
|
||||
prog_section_function f4 = { 0, 0, 0, 0, 14+13+10, 0,0, {0}};
|
||||
prog_section_function f5 = { 0, 0, 0, 0, 14+13+10+7, 0,0, {0}};
|
||||
prog_section_function f6 = { 0, 0, 0, 0, 14+13+10+7+9, 0,0, {0}};
|
||||
prog_section_statement s1 = { INSTR_STORE_F, {30}, {OFS_PARM0}, {0}};
|
||||
prog_section_statement s2 = { INSTR_CALL1, {29}, {0}, {0}};
|
||||
prog_section_statement s3 = { INSTR_RETURN, {0}, {0}, {0}};
|
||||
|
||||
code_chars_put("m_init", 0x6);
|
||||
code_chars_put("print", 0x5);
|
||||
code_chars_put("hello world\n", 0xC);
|
||||
|
@ -117,24 +131,30 @@ void code_test() {
|
|||
code_globals_add(14); /* hello world in string table */
|
||||
|
||||
/* now the defs */
|
||||
code_defs_add((prog_section_def){.type=TYPE_VOID, .offset=28/*globals[28]*/, .name=1 }); /* m_init */
|
||||
code_defs_add((prog_section_def){.type=TYPE_FUNCTION,.offset=29/*globals[29]*/, .name=8 }); /* print */
|
||||
code_defs_add((prog_section_def){.type=TYPE_STRING, .offset=30/*globals[30]*/, .name=14}); /*hello_world*/
|
||||
|
||||
code_functions_add((prog_section_function){1, 0, 0, 0, .name=1, 0, 0, {0}}); /* m_init */
|
||||
code_functions_add((prog_section_function){-4, 0, 0, 0, .name=8, 0, 0, {0}}); /* print */
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13, 0,0, {0}}); /* m_keydown */
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10, 0,0, {0}});
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7, 0,0, {0}});
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7+9, 0,0, {0}});
|
||||
|
||||
code_statements_add((prog_section_statement){INSTR_STORE_F, {30}/*30 is hello_world */, {OFS_PARM0}, {0}});
|
||||
code_statements_add((prog_section_statement){INSTR_CALL1, {29}/*29 is print */, {0}, {0}});
|
||||
code_statements_add((prog_section_statement){INSTR_RETURN, {0}, {0}, {0}});
|
||||
code_defs_add (d1); /* m_init */
|
||||
code_defs_add (d2); /* print */
|
||||
code_defs_add (d3); /*hello_world*/
|
||||
code_functions_add (f1); /* m_init */
|
||||
code_functions_add (f2); /* print */
|
||||
code_functions_add (f3); /* m_keydown */
|
||||
code_functions_add (f4);
|
||||
code_functions_add (f5);
|
||||
code_functions_add (f6);
|
||||
code_statements_add(s1);
|
||||
code_statements_add(s2);
|
||||
code_statements_add(s3);
|
||||
}
|
||||
|
||||
void code_write() {
|
||||
prog_header code_header={0};
|
||||
prog_header code_header = {0};
|
||||
prog_section statements;
|
||||
prog_section defs;
|
||||
prog_section fields;
|
||||
prog_section functions;
|
||||
prog_section globals;
|
||||
prog_section strings;
|
||||
FILE *fp = NULL;
|
||||
size_t it = 1;
|
||||
|
||||
/* see proposal.txt */
|
||||
if (opts_omit_nullcode) {
|
||||
|
@ -142,14 +162,27 @@ void code_write() {
|
|||
code_header.flags = 1;
|
||||
}
|
||||
|
||||
statements.offset = sizeof(prog_header);
|
||||
statements.length = code_statements_elements;
|
||||
defs.offset = code_header.statements.offset + sizeof(prog_section_statement) * code_statements_elements;
|
||||
defs.length = code_defs_elements;
|
||||
fields.offset = code_header.defs.offset + sizeof(prog_section_def) * code_defs_elements;
|
||||
fields.length = code_fields_elements;
|
||||
functions.offset = code_header.fields.offset + sizeof(prog_section_field) * code_fields_elements;
|
||||
functions.length = code_functions_elements;
|
||||
globals.offset = code_header.functions.offset + sizeof(prog_section_function) * code_functions_elements;
|
||||
globals.length = code_globals_elements;
|
||||
strings.offset = code_header.globals.offset + sizeof(int) * code_globals_elements;
|
||||
strings.length = code_chars_elements;
|
||||
|
||||
code_header.version = 6;
|
||||
code_header.crc16 = 0; /* TODO: */
|
||||
code_header.statements = (prog_section){sizeof(prog_header), code_statements_elements };
|
||||
code_header.defs = (prog_section){code_header.statements.offset + sizeof(prog_section_statement)*code_statements_elements, code_defs_elements };
|
||||
code_header.fields = (prog_section){code_header.defs.offset + sizeof(prog_section_def) *code_defs_elements, code_fields_elements };
|
||||
code_header.functions = (prog_section){code_header.fields.offset + sizeof(prog_section_field) *code_fields_elements, code_functions_elements };
|
||||
code_header.globals = (prog_section){code_header.functions.offset + sizeof(prog_section_function) *code_functions_elements, code_globals_elements };
|
||||
code_header.strings = (prog_section){code_header.globals.offset + sizeof(int) *code_globals_elements, code_chars_elements };
|
||||
code_header.statements = statements;
|
||||
code_header.defs = defs;
|
||||
code_header.fields = fields;
|
||||
code_header.functions = functions;
|
||||
code_header.globals = globals;
|
||||
code_header.strings = strings;
|
||||
code_header.entfield = 0; /* TODO: */
|
||||
|
||||
if (opts_darkplaces_stringtablebug) {
|
||||
|
@ -162,21 +195,21 @@ void code_write() {
|
|||
}
|
||||
|
||||
/* ensure all data is in LE format */
|
||||
util_endianswap(&code_header, 1, sizeof(prog_header));
|
||||
util_endianswap(code_statements_data, code_statements_elements, sizeof(prog_section_statement));
|
||||
util_endianswap(code_defs_data, code_defs_elements, sizeof(prog_section_def));
|
||||
util_endianswap(code_fields_data, code_fields_elements, sizeof(prog_section_field));
|
||||
util_endianswap(code_functions_data, code_functions_elements, sizeof(prog_section_function));
|
||||
util_endianswap(code_globals_data, code_globals_elements, sizeof(int));
|
||||
util_endianswap(&code_header, 1, sizeof(prog_header));
|
||||
util_endianswap (code_statements_data, code_statements_elements, sizeof(prog_section_statement));
|
||||
util_endianswap (code_defs_data, code_defs_elements, sizeof(prog_section_def));
|
||||
util_endianswap (code_fields_data, code_fields_elements, sizeof(prog_section_field));
|
||||
util_endianswap (code_functions_data, code_functions_elements, sizeof(prog_section_function));
|
||||
util_endianswap (code_globals_data, code_globals_elements, sizeof(int));
|
||||
|
||||
FILE *fp = fopen("program.dat", "wb");
|
||||
fwrite(&code_header, 1, sizeof(prog_header), fp);
|
||||
fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
|
||||
fwrite(code_defs_data, 1, sizeof(prog_section_def) *code_defs_elements, fp);
|
||||
fwrite(code_fields_data, 1, sizeof(prog_section_field) *code_fields_elements, fp);
|
||||
fwrite(code_functions_data, 1, sizeof(prog_section_function) *code_functions_elements, fp);
|
||||
fwrite(code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
|
||||
fwrite(code_chars_data, 1, 1 *code_chars_elements, fp);
|
||||
fp = fopen("program.dat", "wb");
|
||||
fwrite(&code_header, 1, sizeof(prog_header), fp);
|
||||
fwrite (code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
|
||||
fwrite (code_defs_data, 1, sizeof(prog_section_def) *code_defs_elements, fp);
|
||||
fwrite (code_fields_data, 1, sizeof(prog_section_field) *code_fields_elements, fp);
|
||||
fwrite (code_functions_data, 1, sizeof(prog_section_function) *code_functions_elements, fp);
|
||||
fwrite (code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
|
||||
fwrite (code_chars_data, 1, 1 *code_chars_elements, fp);
|
||||
|
||||
util_debug("GEN","HEADER:\n");
|
||||
util_debug("GEN"," version: = %d\n", code_header.version );
|
||||
|
@ -191,22 +224,21 @@ void code_write() {
|
|||
|
||||
/* FUNCTIONS */
|
||||
util_debug("GEN", "FUNCTIONS:\n");
|
||||
size_t i = 1;
|
||||
for (; i < code_functions_elements; i++) {
|
||||
size_t j = code_functions_data[i].entry;
|
||||
for (; it < code_functions_elements; it++) {
|
||||
size_t j = code_functions_data[it].entry;
|
||||
util_debug("GEN", " {.entry =% 5d, .firstlocal =% 5d, .locals =% 5d, .profile =% 5d, .name =% 5d, .file =% 5d, .nargs =% 5d, .argsize =%0X }\n",
|
||||
code_functions_data[i].entry,
|
||||
code_functions_data[i].firstlocal,
|
||||
code_functions_data[i].locals,
|
||||
code_functions_data[i].profile,
|
||||
code_functions_data[i].name,
|
||||
code_functions_data[i].file,
|
||||
code_functions_data[i].nargs,
|
||||
*((int32_t*)&code_functions_data[i].argsize)
|
||||
code_functions_data[it].entry,
|
||||
code_functions_data[it].firstlocal,
|
||||
code_functions_data[it].locals,
|
||||
code_functions_data[it].profile,
|
||||
code_functions_data[it].name,
|
||||
code_functions_data[it].file,
|
||||
code_functions_data[it].nargs,
|
||||
*((int32_t*)&code_functions_data[it].argsize)
|
||||
);
|
||||
util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[i].name]);
|
||||
util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[it].name]);
|
||||
/* Internal functions have no code */
|
||||
if (code_functions_data[i].entry >= 0) {
|
||||
if (code_functions_data[it].entry >= 0) {
|
||||
util_debug("GEN", " CODE:\n");
|
||||
for (;;) {
|
||||
if (code_statements_data[j].opcode != INSTR_DONE &&
|
||||
|
|
233
gmqcc.h
233
gmqcc.h
|
@ -74,6 +74,25 @@
|
|||
*/
|
||||
#define GMQCC_SUPRESS_EMPTY_BODY do { } while (0)
|
||||
|
||||
/*
|
||||
* Inline is not supported in < C90, however some compilers
|
||||
* like gcc and clang might have an inline attribute we can
|
||||
* use if present.
|
||||
*/
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
# if defined(__GNUC__) || defined (__CLANG__)
|
||||
# if __GNUC__ < 2
|
||||
# define GMQCC_INLINE
|
||||
# else
|
||||
# define GMQCC_INLINE __attribute__ ((always_inline))
|
||||
# endif
|
||||
# else
|
||||
# define GMQCC_INLINE
|
||||
# endif
|
||||
#else
|
||||
# define GMQCC_INLINE inline
|
||||
#endif
|
||||
|
||||
/*
|
||||
* stdint.h and inttypes.h -less subset
|
||||
* for systems that don't have it, which we must
|
||||
|
@ -94,9 +113,15 @@
|
|||
#if INT_MAX == 0x7FFFFFFF
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long int64_t;
|
||||
typedef unsigned long uint64_t;
|
||||
#elif LONG_MAX == 0x7FFFFFFF
|
||||
typedef long int32_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
/* bail on 64 bit type! */
|
||||
typedef char int64_t;
|
||||
typedef char uint64_t;
|
||||
#endif
|
||||
#ifdef _LP64 /* long pointer == 64 */
|
||||
typedef unsigned long uintptr_t;
|
||||
|
@ -109,15 +134,17 @@
|
|||
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 uint64_size_is_correct [sizeof(uint64_t) == 8?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];
|
||||
typedef char int64_size_is_correct [sizeof(int64_t) == 8?1:-1];
|
||||
/* intptr_t / uintptr_t correct size check */
|
||||
typedef char uintptr_size_is_correct[sizeof(intptr_t) == sizeof(int*)?1:-1];
|
||||
typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1];
|
||||
|
||||
//===================================================================
|
||||
//============================ lex.c ================================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*============================ lex.c ================================*/
|
||||
/*===================================================================*/
|
||||
typedef struct lex_file_t {
|
||||
FILE *file; /* file handler */
|
||||
char *name; /* name of file */
|
||||
|
@ -144,11 +171,11 @@ enum {
|
|||
TOKEN_CONTINUE ,
|
||||
TOKEN_RETURN ,
|
||||
TOKEN_GOTO ,
|
||||
TOKEN_FOR , // extension
|
||||
TOKEN_TYPEDEF , // extension
|
||||
TOKEN_FOR , /* extension */
|
||||
TOKEN_TYPEDEF , /* extension */
|
||||
|
||||
// ensure the token types are out of the
|
||||
// bounds of anyothers that may conflict.
|
||||
/* ensure the token types are out of the */
|
||||
/* bounds of anyothers that may conflict. */
|
||||
TOKEN_FLOAT = 110,
|
||||
TOKEN_VECTOR ,
|
||||
TOKEN_STRING ,
|
||||
|
@ -176,9 +203,9 @@ void lex_parse (lex_file *);
|
|||
lex_file *lex_include(lex_file *, const char *);
|
||||
void lex_init (const char *, lex_file **);
|
||||
|
||||
//===================================================================
|
||||
//========================== error.c ================================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*========================== error.c ================================*/
|
||||
/*===================================================================*/
|
||||
#define ERROR_LEX (SHRT_MAX+0)
|
||||
#define ERROR_PARSE (SHRT_MAX+1)
|
||||
#define ERROR_INTERNAL (SHRT_MAX+2)
|
||||
|
@ -186,14 +213,14 @@ void lex_init (const char *, lex_file **);
|
|||
#define ERROR_PREPRO (SHRT_MAX+4)
|
||||
int error(lex_file *, int, const char *, ...);
|
||||
|
||||
//===================================================================
|
||||
//========================== parse.c ================================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*========================== parse.c ================================*/
|
||||
/*===================================================================*/
|
||||
int parse_gen(lex_file *);
|
||||
|
||||
//===================================================================
|
||||
//========================== typedef.c ==============================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*========================== typedef.c ==============================*/
|
||||
/*===================================================================*/
|
||||
typedef struct typedef_node_t {
|
||||
char *name;
|
||||
} typedef_node;
|
||||
|
@ -204,9 +231,9 @@ typedef_node *typedef_find(const char *);
|
|||
int typedef_add (lex_file *file, const char *, const char *);
|
||||
|
||||
|
||||
//===================================================================
|
||||
//=========================== util.c ================================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*=========================== util.c ================================*/
|
||||
/*===================================================================*/
|
||||
void *util_memory_a (unsigned int, unsigned int, const char *);
|
||||
void util_memory_d (void *, unsigned int, const char *);
|
||||
void util_meminfo ();
|
||||
|
@ -242,14 +269,14 @@ uint32_t util_crc32(const char *, int, register const short);
|
|||
/* Builds vector add */
|
||||
#define VECTOR_CORE(T,N) \
|
||||
int N##_add(T element) { \
|
||||
void *temp = NULL; \
|
||||
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) { \
|
||||
if (!(temp = mem_a(N##_allocated * sizeof(T)))) { \
|
||||
mem_d(temp); \
|
||||
return -1; \
|
||||
} \
|
||||
|
@ -272,9 +299,9 @@ uint32_t util_crc32(const char *, int, register const short);
|
|||
VECTOR_TYPE(T,N); \
|
||||
VECTOR_CORE(T,N)
|
||||
|
||||
//===================================================================
|
||||
//=========================== code.c ================================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*=========================== code.c ================================*/
|
||||
/*===================================================================*/
|
||||
enum {
|
||||
TYPE_VOID ,
|
||||
TYPE_STRING ,
|
||||
|
@ -285,7 +312,7 @@ enum {
|
|||
TYPE_FUNCTION ,
|
||||
TYPE_POINTER ,
|
||||
/* TYPE_INTEGER , */
|
||||
TYPE_VARIANT ,
|
||||
TYPE_VARIANT
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -441,7 +468,7 @@ enum {
|
|||
*/
|
||||
VINSTR_PHI,
|
||||
VINSTR_JUMP,
|
||||
VINSTR_COND,
|
||||
VINSTR_COND
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -481,88 +508,88 @@ extern long code_defs_elements;
|
|||
void code_write ();
|
||||
void code_init ();
|
||||
|
||||
//===================================================================
|
||||
//========================= assembler.c =============================
|
||||
//===================================================================
|
||||
/*===================================================================*/
|
||||
/*========================= assembler.c =============================*/
|
||||
/*===================================================================*/
|
||||
static const struct {
|
||||
const char *m; /* menomic */
|
||||
const size_t o; /* operands */
|
||||
const size_t l; /* menomic len */
|
||||
} const asm_instr[] = {
|
||||
[INSTR_DONE] = { "DONE" , 1, 4 },
|
||||
[INSTR_MUL_F] = { "MUL_F" , 3, 5 },
|
||||
[INSTR_MUL_V] = { "MUL_V" , 3, 5 },
|
||||
[INSTR_MUL_FV] = { "MUL_FV" , 3, 6 },
|
||||
[INSTR_MUL_VF] = { "MUL_VF" , 3, 6 },
|
||||
[INSTR_DIV_F] = { "DIV" , 0, 3 },
|
||||
[INSTR_ADD_F] = { "ADD_F" , 3, 5 },
|
||||
[INSTR_ADD_V] = { "ADD_V" , 3, 5 },
|
||||
[INSTR_SUB_F] = { "SUB_F" , 3, 5 },
|
||||
[INSTR_SUB_V] = { "DUB_V" , 3, 5 },
|
||||
[INSTR_EQ_F] = { "EQ_F" , 0, 4 },
|
||||
[INSTR_EQ_V] = { "EQ_V" , 0, 4 },
|
||||
[INSTR_EQ_S] = { "EQ_S" , 0, 4 },
|
||||
[INSTR_EQ_E] = { "EQ_E" , 0, 4 },
|
||||
[INSTR_EQ_FNC] = { "ES_FNC" , 0, 6 },
|
||||
[INSTR_NE_F] = { "NE_F" , 0, 4 },
|
||||
[INSTR_NE_V] = { "NE_V" , 0, 4 },
|
||||
[INSTR_NE_S] = { "NE_S" , 0, 4 },
|
||||
[INSTR_NE_E] = { "NE_E" , 0, 4 },
|
||||
[INSTR_NE_FNC] = { "NE_FNC" , 0, 6 },
|
||||
[INSTR_LE] = { "LE" , 0, 2 },
|
||||
[INSTR_GE] = { "GE" , 0, 2 },
|
||||
[INSTR_LT] = { "LT" , 0, 2 },
|
||||
[INSTR_GT] = { "GT" , 0, 2 },
|
||||
[INSTR_LOAD_F] = { "FIELD_F" , 0, 7 },
|
||||
[INSTR_LOAD_V] = { "FIELD_V" , 0, 7 },
|
||||
[INSTR_LOAD_S] = { "FIELD_S" , 0, 7 },
|
||||
[INSTR_LOAD_ENT] = { "FIELD_ENT" , 0, 9 },
|
||||
[INSTR_LOAD_FLD] = { "FIELD_FLD" , 0, 9 },
|
||||
[INSTR_LOAD_FNC] = { "FIELD_FNC" , 0, 9 },
|
||||
[INSTR_ADDRESS] = { "ADDRESS" , 0, 7 },
|
||||
[INSTR_STORE_F] = { "STORE_F" , 0, 7 },
|
||||
[INSTR_STORE_V] = { "STORE_V" , 0, 7 },
|
||||
[INSTR_STORE_S] = { "STORE_S" , 0, 7 },
|
||||
[INSTR_STORE_ENT] = { "STORE_ENT" , 0, 9 },
|
||||
[INSTR_STORE_FLD] = { "STORE_FLD" , 0, 9 },
|
||||
[INSTR_STORE_FNC] = { "STORE_FNC" , 0, 9 },
|
||||
[INSTR_STOREP_F] = { "STOREP_F" , 0, 8 },
|
||||
[INSTR_STOREP_V] = { "STOREP_V" , 0, 8 },
|
||||
[INSTR_STOREP_S] = { "STOREP_S" , 0, 8 },
|
||||
[INSTR_STOREP_ENT] = { "STOREP_ENT", 0, 10},
|
||||
[INSTR_STOREP_FLD] = { "STOREP_FLD", 0, 10},
|
||||
[INSTR_STOREP_FNC] = { "STOREP_FNC", 0, 10},
|
||||
[INSTR_RETURN] = { "RETURN" , 0, 6 },
|
||||
[INSTR_NOT_F] = { "NOT_F" , 0, 5 },
|
||||
[INSTR_NOT_V] = { "NOT_V" , 0, 5 },
|
||||
[INSTR_NOT_S] = { "NOT_S" , 0, 5 },
|
||||
[INSTR_NOT_ENT] = { "NOT_ENT" , 0, 7 },
|
||||
[INSTR_NOT_FNC] = { "NOT_FNC" , 0, 7 },
|
||||
[INSTR_IF] = { "IF" , 0, 2 },
|
||||
[INSTR_IFNOT] = { "IFNOT" , 0, 5 },
|
||||
[INSTR_CALL0] = { "CALL0" , 0, 5 },
|
||||
[INSTR_CALL1] = { "CALL1" , 0, 5 },
|
||||
[INSTR_CALL2] = { "CALL2" , 0, 5 },
|
||||
[INSTR_CALL3] = { "CALL3" , 0, 5 },
|
||||
[INSTR_CALL4] = { "CALL4" , 0, 5 },
|
||||
[INSTR_CALL5] = { "CALL5" , 0, 5 },
|
||||
[INSTR_CALL6] = { "CALL6" , 0, 5 },
|
||||
[INSTR_CALL7] = { "CALL7" , 0, 5 },
|
||||
[INSTR_CALL8] = { "CALL8" , 0, 5 },
|
||||
[INSTR_STATE] = { "STATE" , 0, 5 },
|
||||
[INSTR_GOTO] = { "GOTO" , 0, 4 },
|
||||
[INSTR_AND] = { "AND" , 0, 3 },
|
||||
[INSTR_OR] = { "OR" , 0, 2 },
|
||||
[INSTR_BITAND] = { "BITAND" , 0, 6 },
|
||||
[INSTR_BITOR] = { "BITOR" , 0, 5 }
|
||||
} asm_instr[] = {
|
||||
{ "DONE" , 1, 4 },
|
||||
{ "MUL_F" , 3, 5 },
|
||||
{ "MUL_V" , 3, 5 },
|
||||
{ "MUL_FV" , 3, 6 },
|
||||
{ "MUL_VF" , 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 },
|
||||
{ "ES_FNC" , 0, 6 },
|
||||
{ "NE_F" , 0, 4 },
|
||||
{ "NE_V" , 0, 4 },
|
||||
{ "NE_S" , 0, 4 },
|
||||
{ "NE_E" , 0, 4 },
|
||||
{ "NE_FNC" , 0, 6 },
|
||||
{ "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 },
|
||||
{ "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 },
|
||||
{ "STOREP_F" , 0, 8 },
|
||||
{ "STOREP_V" , 0, 8 },
|
||||
{ "STOREP_S" , 0, 8 },
|
||||
{ "STOREP_ENT", 0, 10},
|
||||
{ "STOREP_FLD", 0, 10},
|
||||
{ "STOREP_FNC", 0, 10},
|
||||
{ "RETURN" , 0, 6 },
|
||||
{ "NOT_F" , 0, 5 },
|
||||
{ "NOT_V" , 0, 5 },
|
||||
{ "NOT_S" , 0, 5 },
|
||||
{ "NOT_ENT" , 0, 7 },
|
||||
{ "NOT_FNC" , 0, 7 },
|
||||
{ "IF" , 0, 2 },
|
||||
{ "IFNOT" , 0, 5 },
|
||||
{ "CALL0" , 0, 5 },
|
||||
{ "CALL1" , 0, 5 },
|
||||
{ "CALL2" , 0, 5 },
|
||||
{ "CALL3" , 0, 5 },
|
||||
{ "CALL4" , 0, 5 },
|
||||
{ "CALL5" , 0, 5 },
|
||||
{ "CALL6" , 0, 5 },
|
||||
{ "CALL7" , 0, 5 },
|
||||
{ "CALL8" , 0, 5 },
|
||||
{ "STATE" , 0, 5 },
|
||||
{ "GOTO" , 0, 4 },
|
||||
{ "AND" , 0, 3 },
|
||||
{ "OR" , 0, 2 },
|
||||
{ "BITAND" , 0, 6 },
|
||||
{ "BITOR" , 0, 5 }
|
||||
};
|
||||
|
||||
void asm_init (const char *, FILE **);
|
||||
void asm_close(FILE *);
|
||||
void asm_parse(FILE *);
|
||||
//======================================================================
|
||||
//============================= main.c =================================
|
||||
//======================================================================
|
||||
/*===================================================================*/
|
||||
/*============================= main.c ==============================*/
|
||||
/*===================================================================*/
|
||||
enum {
|
||||
COMPILER_QCC, /* circa QuakeC */
|
||||
COMPILER_FTEQCC, /* fteqcc QuakeC */
|
||||
|
@ -574,9 +601,9 @@ extern bool opts_memchk;
|
|||
extern bool opts_darkplaces_stringtablebug;
|
||||
extern bool opts_omit_nullcode;
|
||||
extern int opts_compiler;
|
||||
//======================================================================
|
||||
//============================= ast.c ==================================
|
||||
//======================================================================
|
||||
/*===================================================================*/
|
||||
/*============================= 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)
|
||||
|
@ -690,7 +717,7 @@ _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_value /* unassignable */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
15
ir.c
15
ir.c
|
@ -511,6 +511,7 @@ bool ir_value_life_merge(ir_value *self, size_t s)
|
|||
}
|
||||
/* nothing found? append */
|
||||
if (i == self->life_count) {
|
||||
ir_life_entry_t e;
|
||||
if (life && life->end+1 == s)
|
||||
{
|
||||
/* previous life range can be merged in */
|
||||
|
@ -519,7 +520,6 @@ bool ir_value_life_merge(ir_value *self, size_t s)
|
|||
}
|
||||
if (life && life->end >= s)
|
||||
return false;
|
||||
ir_life_entry_t e;
|
||||
e.start = e.end = s;
|
||||
if (!ir_value_life_add(self, e))
|
||||
return false; /* failing */
|
||||
|
@ -657,7 +657,7 @@ bool ir_block_create_if(ir_block *self, ir_value *v,
|
|||
return false;
|
||||
}
|
||||
self->final = true;
|
||||
//in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));
|
||||
/*in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
|
||||
in = ir_instr_new(self, VINSTR_COND);
|
||||
if (!in)
|
||||
return false;
|
||||
|
@ -786,6 +786,9 @@ ir_value* ir_block_create_binop(ir_block *self,
|
|||
const char *label, int opcode,
|
||||
ir_value *left, ir_value *right)
|
||||
{
|
||||
ir_value *out = NULL;
|
||||
ir_instr *in = NULL;
|
||||
|
||||
int ot = TYPE_VOID;
|
||||
switch (opcode) {
|
||||
case INSTR_ADD_F:
|
||||
|
@ -854,7 +857,7 @@ ir_value* ir_block_create_binop(ir_block *self,
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
// ranges:
|
||||
/* ranges: */
|
||||
/* boolean operations result in floats */
|
||||
if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT)
|
||||
ot = TYPE_FLOAT;
|
||||
|
@ -871,11 +874,11 @@ ir_value* ir_block_create_binop(ir_block *self,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ir_value *out = ir_value_out(self->owner, label, store_local, ot);
|
||||
out = ir_value_out(self->owner, label, store_local, ot);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
ir_instr *in = ir_instr_new(self, opcode);
|
||||
in = ir_instr_new(self, opcode);
|
||||
if (!in) {
|
||||
ir_value_delete(out);
|
||||
return NULL;
|
||||
|
@ -1433,7 +1436,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
|
|||
}
|
||||
/* (A) */
|
||||
tempbool = ir_block_living_add_instr(self, instr->eid);
|
||||
//fprintf(stderr, "living added values\n");
|
||||
/*fprintf(stderr, "living added values\n");*/
|
||||
*changed = *changed || tempbool;
|
||||
|
||||
/* new reads: */
|
||||
|
|
6
lex.c
6
lex.c
|
@ -67,7 +67,7 @@ static void lex_addch(int ch, lex_file *file) {
|
|||
if (file->current == sizeof(file->lastok)-1)
|
||||
file->lastok[file->current] = (char)'\0';
|
||||
}
|
||||
static inline void lex_clear(lex_file *file) {
|
||||
static GMQCC_INLINE void lex_clear(lex_file *file) {
|
||||
file->current = 0;
|
||||
}
|
||||
|
||||
|
@ -342,13 +342,13 @@ void lex_parse(lex_file *file) {
|
|||
* recrusion.
|
||||
*/
|
||||
lex_file *lex_include(lex_file *lex, const char *file) {
|
||||
lex_file *set = NULL;
|
||||
|
||||
util_strrq(file);
|
||||
if (strncmp(lex->name, file, strlen(lex->name)) == 0) {
|
||||
error(lex, ERROR_LEX, "Source file cannot include itself\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
lex_file *set = NULL;
|
||||
lex_init(file, &set);
|
||||
|
||||
return set;
|
||||
|
|
50
main.c
50
main.c
|
@ -21,7 +21,6 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
#include "gmqcc.h"
|
||||
// todo CLEANUP this argitem thing
|
||||
typedef struct { char *name, type; } argitem;
|
||||
VECTOR_MAKE(argitem, items);
|
||||
|
||||
|
@ -39,21 +38,22 @@ static const int usage(const char *const app) {
|
|||
" %s -c<file> -i<file> -oprog.dat -- compile together (allowed multiple -i<file>)\n"
|
||||
" %s -a<file> -i<file> -oprog.dat -- assemble together(allowed multiple -i<file>)\n"
|
||||
" example:\n"
|
||||
" %s -cfoo.qc -ibar.qc -oqc.dat -afoo.qs -ibar.qs -oqs.dat\n"
|
||||
" additional flags:\n"
|
||||
" %s -cfoo.qc -ibar.qc -oqc.dat -afoo.qs -ibar.qs -oqs.dat\n", app, app, app, app, app);
|
||||
|
||||
printf(" additional flags:\n"
|
||||
" -debug -- turns on compiler debug messages\n"
|
||||
" -memchk -- turns on compiler memory leak check\n"
|
||||
" -help -- prints this help/usage text\n"
|
||||
" -std -- select the QuakeC compile type (types below):\n"
|
||||
" -std=qcc -- original QuakeC\n"
|
||||
" -std -- select the QuakeC compile type (types below):\n");
|
||||
|
||||
printf(" -std=qcc -- original QuakeC\n"
|
||||
" -std=ftqecc -- fteqcc QuakeC\n"
|
||||
" -std=qccx -- qccx QuakeC\n"
|
||||
" -std=gmqcc -- this compiler QuakeC (default selection)\n"
|
||||
" codegen flags:\n"
|
||||
" -std=gmqcc -- this compiler QuakeC (default selection)\n");
|
||||
|
||||
printf(" codegen flags:\n"
|
||||
" -fdarkplaces-string-table-bug -- patches the string table to work with bugged versions of darkplaces\n"
|
||||
" -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n",
|
||||
app,app,app,app,app
|
||||
);
|
||||
" -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -87,20 +87,25 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
#define param_argument(argtype) do { \
|
||||
argitem item; \
|
||||
if (argv[1][2]) { \
|
||||
items_add((argitem){util_strdup(&argv[1][2]), argtype}); \
|
||||
item.name = util_strdup(&argv[1][2]); \
|
||||
item.type = argtype; \
|
||||
items_add(item); \
|
||||
} else { \
|
||||
++argv; \
|
||||
--argc; \
|
||||
if (argc <= 1) \
|
||||
goto clean_params_usage; \
|
||||
items_add((argitem){util_strdup(&argv[1][0]), argtype}); \
|
||||
} \
|
||||
item.name = util_strdup(argv[1]); \
|
||||
item.type = argtype; \
|
||||
items_add(item); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
case 'c': param_argument(0); break; /* compile */
|
||||
case 'a': param_argument(1); break; /* assemble */
|
||||
case 'i': param_argument(2); break; /* includes */
|
||||
case 'c': { param_argument(0); break; } /* compile */
|
||||
case 'a': { param_argument(1); break; } /* assemble */
|
||||
case 'i': { param_argument(2); break; } /* includes */
|
||||
#undef parm_argument
|
||||
default:
|
||||
if (!strncmp(&argv[1][1], "debug" , 5)) { opts_debug = true; break; }
|
||||
|
@ -152,13 +157,17 @@ int main(int argc, char **argv) {
|
|||
switch (items_data[itr].type) {
|
||||
case 0:
|
||||
lex_init (items_data[itr].name, &lex);
|
||||
lex_parse(lex);
|
||||
lex_close(lex);
|
||||
if (lex) {
|
||||
lex_parse(lex);
|
||||
lex_close(lex);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
asm_init (items_data[itr].name, &fpp);
|
||||
asm_parse(fpp);
|
||||
asm_close(fpp);
|
||||
if (fpp) {
|
||||
asm_parse(fpp);
|
||||
asm_close(fpp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +180,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
util_meminfo();
|
||||
return 0;
|
||||
|
||||
clean_params_usage:
|
||||
for (itr = 0; itr < items_elements; itr++)
|
||||
mem_d(items_data[itr].name);
|
||||
|
|
95
parse.c
95
parse.c
|
@ -82,7 +82,7 @@ int parse_gen(lex_file *file) {
|
|||
case TOKEN_ENTITY: goto fall;
|
||||
case TOKEN_FLOAT: goto fall;
|
||||
{
|
||||
fall:;
|
||||
fall:; {
|
||||
char *name = NULL;
|
||||
int type = token; /* story copy */
|
||||
|
||||
|
@ -119,12 +119,16 @@ int parse_gen(lex_file *file) {
|
|||
if (*file->lastok != '"')
|
||||
error(file, ERROR_PARSE, "Expected a '\"' (quote) for string constant\n");
|
||||
/* add the compile-time constant */
|
||||
compile_constants_add((constant){
|
||||
.name = util_strdup(name),
|
||||
.type = TYPE_STRING,
|
||||
.value = {0,0,0},
|
||||
.string = util_strdup(file->lastok)
|
||||
});
|
||||
{
|
||||
constant c;
|
||||
c.name = util_strdup(name),
|
||||
c.type = TYPE_STRING,
|
||||
c.value[0] = 0;
|
||||
c.value[1] = 0;
|
||||
c.value[2] = 0;
|
||||
c.string = util_strdup(file->lastok);
|
||||
compile_constants_add(c);
|
||||
}
|
||||
break;
|
||||
/* TODO: name constant, old qc vec literals, whitespace fixes, name constant */
|
||||
case TOKEN_VECTOR: {
|
||||
|
@ -206,16 +210,17 @@ int parse_gen(lex_file *file) {
|
|||
error(file, ERROR_PARSE, "Expected `;` on end of constant initialization for vector\n");
|
||||
|
||||
/* add the compile-time constant */
|
||||
compile_constants_add((constant){
|
||||
.name = util_strdup(name),
|
||||
.type = TYPE_VECTOR,
|
||||
.value = {
|
||||
[0] = compile_calc_x,
|
||||
[1] = compile_calc_y,
|
||||
[2] = compile_calc_z
|
||||
},
|
||||
.string = NULL
|
||||
});
|
||||
{
|
||||
constant c;
|
||||
|
||||
c.name = util_strdup(name),
|
||||
c.type = TYPE_VECTOR,
|
||||
c.value[0] = compile_calc_x;
|
||||
c.value[1] = compile_calc_y;
|
||||
c.value[2] = compile_calc_z;
|
||||
c.string = NULL;
|
||||
compile_constants_add(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -223,19 +228,24 @@ int parse_gen(lex_file *file) {
|
|||
case TOKEN_FLOAT: /*TODO: validate, constant generation, name constant */
|
||||
if (!isdigit(token))
|
||||
error(file, ERROR_PARSE, "Expected numeric constant for float constant\n");
|
||||
compile_constants_add((constant){
|
||||
.name = util_strdup(name),
|
||||
.type = TOKEN_FLOAT,
|
||||
.value = {0,0,0},
|
||||
.string = NULL
|
||||
});
|
||||
/* constant */
|
||||
{
|
||||
constant c;
|
||||
c.name = util_strdup(name),
|
||||
c.type = TOKEN_FLOAT,
|
||||
c.value[0] = 0;
|
||||
c.value[1] = 0;
|
||||
c.value[2] = 0;
|
||||
c.string = NULL;
|
||||
compile_constants_add(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (token == '(') {
|
||||
printf("FUNCTION ??\n");
|
||||
}
|
||||
mem_d(name);
|
||||
}
|
||||
}}
|
||||
|
||||
/*
|
||||
* From here down is all language punctuation: There is no
|
||||
|
@ -253,6 +263,8 @@ int parse_gen(lex_file *file) {
|
|||
* directives so far are #include.
|
||||
*/
|
||||
if (strncmp(file->lastok, "include", sizeof("include")) == 0) {
|
||||
char *copy = NULL;
|
||||
lex_file *next = NULL;
|
||||
/*
|
||||
* We only suport include " ", not <> like in C (why?)
|
||||
* because the latter is silly.
|
||||
|
@ -262,19 +274,24 @@ int parse_gen(lex_file *file) {
|
|||
if (token == '\n')
|
||||
return error(file, ERROR_PARSE, "Invalid use of include preprocessor directive: wanted #include \"file.h\"\n");
|
||||
|
||||
char *copy = util_strdup(file->lastok);
|
||||
lex_file *next = lex_include(file, copy);
|
||||
copy = util_strdup(file->lastok);
|
||||
next = lex_include(file, copy);
|
||||
|
||||
if (!next) {
|
||||
error(file, ERROR_INTERNAL, "Include subsystem failure\n");
|
||||
exit (-1);
|
||||
}
|
||||
compile_constants_add((constant) {
|
||||
.name = "#include",
|
||||
.type = TYPE_VOID,
|
||||
.value = {0,0,0},
|
||||
.string = copy
|
||||
});
|
||||
/* constant */
|
||||
{
|
||||
constant c;
|
||||
c.name = "#include",
|
||||
c.type = TYPE_VOID,
|
||||
c.value[0] = 0;
|
||||
c.value[1] = 0;
|
||||
c.value[2] = 0;
|
||||
c.string = copy;
|
||||
compile_constants_add(c);
|
||||
}
|
||||
parse_gen(next);
|
||||
mem_d (copy);
|
||||
lex_close(next);
|
||||
|
@ -293,12 +310,12 @@ int parse_gen(lex_file *file) {
|
|||
lex_reset(file);
|
||||
/* free constants */
|
||||
{
|
||||
size_t i = 0;
|
||||
for (; i < compile_constants_elements; i++) {
|
||||
mem_d(compile_constants_data[i].name);
|
||||
mem_d(compile_constants_data[i].string);
|
||||
}
|
||||
mem_d(compile_constants_data);
|
||||
}
|
||||
size_t i = 0;
|
||||
for (; i < compile_constants_elements; i++) {
|
||||
mem_d(compile_constants_data[i].name);
|
||||
mem_d(compile_constants_data[i].string);
|
||||
}
|
||||
mem_d(compile_constants_data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
34
util.c
34
util.c
|
@ -24,10 +24,10 @@
|
|||
#include <errno.h>
|
||||
#include "gmqcc.h"
|
||||
|
||||
unsigned long long mem_ab = 0;
|
||||
unsigned long long mem_db = 0;
|
||||
unsigned long long mem_at = 0;
|
||||
unsigned long long mem_dt = 0;
|
||||
uint64_t mem_ab = 0;
|
||||
uint64_t mem_db = 0;
|
||||
uint64_t mem_at = 0;
|
||||
uint64_t mem_dt = 0;
|
||||
|
||||
struct memblock_t {
|
||||
const char *file;
|
||||
|
@ -51,10 +51,12 @@ void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
|
|||
}
|
||||
|
||||
void util_memory_d(void *ptrn, unsigned int line, const char *file) {
|
||||
void *data = NULL;
|
||||
struct memblock_t *info = NULL;
|
||||
if (!ptrn) return;
|
||||
void *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
|
||||
struct memblock_t *info = (struct memblock_t*)data;
|
||||
|
||||
data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
|
||||
info = (struct memblock_t*)data;
|
||||
|
||||
util_debug("MEM", "released: % 8u (bytes) address 0x%08X @ %s:%u\n", info->byte, data, file, line);
|
||||
mem_db += info->byte;
|
||||
mem_dt++;
|
||||
|
@ -124,10 +126,11 @@ char *util_strrq(const char *s) {
|
|||
* copy of it and null terminating it at the required position.
|
||||
*/
|
||||
char *util_strchp(const char *s, const char *e) {
|
||||
const char *c = NULL;
|
||||
if (!s || !e)
|
||||
return NULL;
|
||||
|
||||
const char *c = s;
|
||||
c = s;
|
||||
while (c != e)
|
||||
c++;
|
||||
|
||||
|
@ -140,12 +143,15 @@ char *util_strchp(const char *s, const char *e) {
|
|||
* access.
|
||||
*/
|
||||
char *util_strrnl(const char *src) {
|
||||
if (!src) return NULL;
|
||||
char *cpy = (char*)src;
|
||||
while (*cpy && *cpy != '\n')
|
||||
cpy++;
|
||||
char *cpy = NULL;
|
||||
|
||||
*cpy = '\0';
|
||||
if (src) {
|
||||
cpy = (char*)src;
|
||||
while (*cpy && *cpy != '\n')
|
||||
cpy++;
|
||||
|
||||
*cpy = '\0';
|
||||
}
|
||||
return (char*)src;
|
||||
}
|
||||
|
||||
|
@ -191,10 +197,10 @@ bool util_strdigit(const char *str) {
|
|||
}
|
||||
|
||||
void util_debug(const char *area, const char *ms, ...) {
|
||||
va_list va;
|
||||
if (!opts_debug)
|
||||
return;
|
||||
|
||||
va_list va;
|
||||
va_start(va, ms);
|
||||
fprintf (stdout, "DEBUG: ");
|
||||
fputc ('[', stdout);
|
||||
|
|
Loading…
Reference in a new issue