/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* and also I plan to allow inline assembly for the compiler.
*/
static const struct {
- const char *m; /* menomic */
- const size_t o; /* operands */
- const size_t l; /* menomic len */
+ 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 }
+ [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 }
};
/*
* for creating functions, or constants.
*/
const char *const asm_keys[] = {
- "FLOAT" , /* define float */
- "VECTOR" , /* define vector */
- "ENTITY" , /* define ent */
- "FIELD" , /* define field */
- "STRING" , /* define string */
- "FUNCTION"
+ "FLOAT" , /* define float */
+ "VECTOR" , /* define vector */
+ "ENTITY" , /* define ent */
+ "FIELD" , /* define field */
+ "STRING" , /* define string */
+ "FUNCTION"
};
static char *const asm_getline(size_t *byte, FILE *fp) {
- char *line = NULL;
- ssize_t read = util_getline(&line, byte, fp);
- *byte = read;
- if (read == -1) {
- mem_d (line);
- return NULL;
- }
- return line;
+ char *line = NULL;
+ ssize_t read = util_getline(&line, byte, fp);
+ *byte = read;
+ if (read == -1) {
+ mem_d (line);
+ return NULL;
+ }
+ return line;
}
#define asm_rmnewline(L,S) *((L)+*(S)-1) = '\0'
}
void asm_init(const char *file, FILE **fp) {
- *fp = fopen(file, "r");
- code_init();
+ *fp = fopen(file, "r");
+ code_init();
}
void asm_close(FILE *fp) {
- fclose(fp);
- code_write();
+ fclose(fp);
+ code_write();
}
/*
* Following parse states:
- * ASM_FUNCTION -- in a function accepting input statements
- * ....
+ * ASM_FUNCTION -- in a function accepting input statements
+ * ....
*/
typedef enum {
- ASM_NULL,
- ASM_FUNCTION
+ ASM_NULL,
+ ASM_FUNCTION
} asm_state;
typedef struct {
- char *name; /* name of constant */
- int offset; /* location in globals */
+ char *name; /* name of constant */
+ int offset; /* location in globals */
} globals;
VECTOR_MAKE(globals, assembly_constants);
-
+
void asm_parse(FILE *fp) {
- char *data = NULL;
- char *skip = NULL;
- long line = 1; /* current line */
- size_t size = 0; /* size of line */
- asm_state state = ASM_NULL;
-
- while ((data = asm_getline(&size, fp)) != NULL) {
- skip = data;
- asm_skipwhite(skip);
- asm_rmnewline(skip, &size);
-
- #define DECLTYPE(X, CODE) \
- if (!strncmp(X, skip, strlen(X))) { \
- if (skip[strlen(X)] != ':') { \
- printf("%li: Missing `:` after decltype\n",line); \
- exit (1); \
- } \
- skip += strlen(X)+1; \
- asm_skipwhite(skip); \
- if(!isalpha(*skip)) { \
- printf("%li: Invalid identififer: %s\n", line, skip); \
- exit (1); \
- } else { \
- size_t offset_code = code_statements_elements+1; \
- size_t offset_chars = code_strings_elements +1; \
- size_t offset_globals = code_globals_elements +1; \
- size_t offset_functions = code_functions_elements +1; \
- size_t offset_fields = code_fields_elements +1; \
- size_t offset_defs = code_defs_elements +1; \
- CODE \
- /* silent unused warnings */ \
- (void)offset_code; \
- (void)offset_chars; \
- (void)offset_globals; \
- (void)offset_functions; \
- (void)offset_fields; \
- (void)offset_defs; \
- assembly_constants_add((globals){ \
- .name = util_strdup(skip), \
- .offset = offset_globals \
- }); \
- } \
- goto end; \
- }
-
- /* FLOAT */
- DECLTYPE(asm_keys[0], {
- code_defs_add((prog_section_def){
- .type = TYPE_FLOAT,
- .offset = offset_globals, /* global table */
- .name = offset_chars /* string table TODO */
- });
- float f = 0; /*TODO*/
- code_globals_add(*(int*)&f);
-
- });
- DECLTYPE(asm_keys[1], {
- code_defs_add((prog_section_def){
- .type = TYPE_FLOAT,
- .offset = offset_globals, /* global table */
- .name = offset_chars /* string table TODO */
- });
- float f1 = 0;
- float f2 = 0;
- float f3 = 0;
- code_globals_add(*(int*)&f1);
- code_globals_add(*(int*)&f2);
- code_globals_add(*(int*)&f3);
- });
- /* ENTITY */ DECLTYPE(asm_keys[2], {});
- /* FIELD */ DECLTYPE(asm_keys[3], {});
- /* STRING */
- DECLTYPE(asm_keys[4], {
- code_defs_add((prog_section_def){
- .type = TYPE_STRING,
- .offset = offset_globals, /* offset to offset in string table (for data)*/
- .name = offset_chars /* location of name in string table (for name)*/
- });
- code_strings_add('h');
- });
- /* FUNCTION */
- DECLTYPE(asm_keys[5], {
- /* TODO: parse */
- if (state != ASM_NULL) {
- printf("%li: Error unfinished function block, expected DONE or RETURN\n", line);
- goto end;
- }
-
- state = ASM_FUNCTION;
- code_defs_add((prog_section_def){
- .type = TYPE_VOID,
- .offset = offset_globals,
- .name = offset_chars
- });
- code_globals_add(offset_functions);
- code_functions_add((prog_section_function){
- .entry = offset_code,
- .firstlocal = 0,
- .locals = 0,
- .profile = 0,
- .name = offset_chars,
- .file = 0,
- .nargs = 0,
- .argsize = {0}
- });
- });
-
- /* if we make it this far then we have statements */
- {
- size_t i = 0; /* counter */
- size_t o = 0; /* operands */
- char *t = NULL; /* token */
-
- /*
- * Most ops a single statement can have is three.
- * lets allocate some space for all of those here.
- */
- char op[3][32768] = {{0},{0},{0}};
- for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
- if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
- if (state != ASM_FUNCTION) {
- printf("%li: Statement not inside function block\n", line);
- goto end;
- }
-
- /* update parser state */
- if (i == INSTR_DONE || i == INSTR_RETURN) {
- goto end;
- state = ASM_NULL;
- }
-
- /* parse the statement */
- o = asm_instr[i].o; /* operands */
- skip += asm_instr[i].l; /* skip instruction */
- t = strtok(skip, " ,");
- i = 0;
- while (t != NULL && i < 3) {
- strcpy(op[i], t);
- t = strtok(NULL, " ,");
- i ++;
- }
-
- util_debug("ASM", "Operand 1: %s\n", util_strrnl(op[0]));
- util_debug("ASM", "Operand 2: %s\n", util_strrnl(op[1]));
- util_debug("ASM", "Operand 3: %s\n", util_strrnl(op[2]));
-
- /* check */
- if (i != o) {
- printf("not enough operands, expected: %li, got %li\n", o, i);
- }
-
- /* TODO: hashtable value LOAD .... etc */
- code_statements_add((prog_section_statement){
- i, {0}, {0}, {0}
- });
- goto end;
- }
- }
- }
-
- /* if we made it this far something is wrong */
- if (*skip != '\0')
- printf("%li: Invalid statement, expression, or decleration\n", line);
-
- end:
- //free(data);
- mem_d(data);
- line ++;
- }
+ char *data = NULL;
+ char *skip = NULL;
+ long line = 1; /* current line */
+ size_t size = 0; /* size of line */
+ asm_state state = ASM_NULL;
+
+ while ((data = asm_getline(&size, fp)) != NULL) {
+ skip = data;
+ asm_skipwhite(skip);
+ asm_rmnewline(skip, &size);
+
+ #define DECLTYPE(X, CODE) \
+ if (!strncmp(X, skip, strlen(X))) { \
+ if (skip[strlen(X)] != ':') { \
+ printf("%li: Missing `:` after decltype\n",line); \
+ exit (1); \
+ } \
+ skip += strlen(X)+1; \
+ asm_skipwhite(skip); \
+ if(!isalpha(*skip)) { \
+ printf("%li: Invalid identififer: %s\n", line, skip); \
+ exit (1); \
+ } else { \
+ size_t offset_code = code_statements_elements+1; \
+ size_t offset_chars = code_strings_elements +1; \
+ size_t offset_globals = code_globals_elements +1; \
+ size_t offset_functions = code_functions_elements +1; \
+ size_t offset_fields = code_fields_elements +1; \
+ size_t offset_defs = code_defs_elements +1; \
+ CODE \
+ /* silent unused warnings */ \
+ (void)offset_code; \
+ (void)offset_chars; \
+ (void)offset_globals; \
+ (void)offset_functions; \
+ (void)offset_fields; \
+ (void)offset_defs; \
+ assembly_constants_add((globals){ \
+ .name = util_strdup(skip), \
+ .offset = offset_globals \
+ }); \
+ } \
+ goto end; \
+ }
+
+ /* FLOAT */
+ DECLTYPE(asm_keys[0], {
+ code_defs_add((prog_section_def){
+ .type = TYPE_FLOAT,
+ .offset = offset_globals, /* global table */
+ .name = offset_chars /* string table TODO */
+ });
+ float f = 0; /*TODO*/
+ code_globals_add(*(int*)&f);
+
+ });
+ DECLTYPE(asm_keys[1], {
+ code_defs_add((prog_section_def){
+ .type = TYPE_FLOAT,
+ .offset = offset_globals, /* global table */
+ .name = offset_chars /* string table TODO */
+ });
+ float f1 = 0;
+ float f2 = 0;
+ float f3 = 0;
+ code_globals_add(*(int*)&f1);
+ code_globals_add(*(int*)&f2);
+ code_globals_add(*(int*)&f3);
+ });
+ /* ENTITY */ DECLTYPE(asm_keys[2], {});
+ /* FIELD */ DECLTYPE(asm_keys[3], {});
+ /* STRING */
+ DECLTYPE(asm_keys[4], {
+ code_defs_add((prog_section_def){
+ .type = TYPE_STRING,
+ .offset = offset_globals, /* offset to offset in string table (for data)*/
+ .name = offset_chars /* location of name in string table (for name)*/
+ });
+ code_strings_add('h');
+ });
+ /* FUNCTION */
+ DECLTYPE(asm_keys[5], {
+ /* TODO: parse */
+ if (state != ASM_NULL) {
+ printf("%li: Error unfinished function block, expected DONE or RETURN\n", line);
+ goto end;
+ }
+
+ state = ASM_FUNCTION;
+ code_defs_add((prog_section_def){
+ .type = TYPE_VOID,
+ .offset = offset_globals,
+ .name = offset_chars
+ });
+ code_globals_add(offset_functions);
+ code_functions_add((prog_section_function){
+ .entry = offset_code,
+ .firstlocal = 0,
+ .locals = 0,
+ .profile = 0,
+ .name = offset_chars,
+ .file = 0,
+ .nargs = 0,
+ .argsize = {0}
+ });
+ });
+
+ /* if we make it this far then we have statements */
+ {
+ size_t i = 0; /* counter */
+ size_t o = 0; /* operands */
+ char *t = NULL; /* token */
+
+ /*
+ * Most ops a single statement can have is three.
+ * lets allocate some space for all of those here.
+ */
+ char op[3][32768] = {{0},{0},{0}};
+ for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
+ if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
+ if (state != ASM_FUNCTION) {
+ printf("%li: Statement not inside function block\n", line);
+ goto end;
+ }
+
+ /* update parser state */
+ if (i == INSTR_DONE || i == INSTR_RETURN) {
+ goto end;
+ state = ASM_NULL;
+ }
+
+ /* parse the statement */
+ o = asm_instr[i].o; /* operands */
+ skip += asm_instr[i].l; /* skip instruction */
+ t = strtok(skip, " ,");
+ i = 0;
+ while (t != NULL && i < 3) {
+ strcpy(op[i], t);
+ t = strtok(NULL, " ,");
+ i ++;
+ }
+
+ util_debug("ASM", "Operand 1: %s\n", util_strrnl(op[0]));
+ util_debug("ASM", "Operand 2: %s\n", util_strrnl(op[1]));
+ util_debug("ASM", "Operand 3: %s\n", util_strrnl(op[2]));
+
+ /* check */
+ if (i != o) {
+ printf("not enough operands, expected: %li, got %li\n", o, i);
+ }
+
+ /* TODO: hashtable value LOAD .... etc */
+ code_statements_add((prog_section_statement){
+ i, {0}, {0}, {0}
+ });
+ goto end;
+ }
+ }
+ }
+
+ /* if we made it this far something is wrong */
+ if (*skip != '\0')
+ printf("%li: Invalid statement, expression, or decleration\n", line);
+
+ end:
+ //free(data);
+ mem_d(data);
+ line ++;
+ }
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
#include "gmqcc.h"
typedef struct {
- uint32_t offset; /* Offset in file of where data begins */
- uint32_t length; /* Length of section (how many of) */
+ 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) */
- uint32_t crc16; /* What is this? */
- 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; /* What is this? */
- prog_section globals; /* What is this? */
- uint32_t entfield; /* Number of entity fields */
+ uint32_t version; /* Program version (6) */
+ uint32_t crc16; /* What is this? */
+ 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; /* What is this? */
+ prog_section globals; /* What is this? */
+ uint32_t entfield; /* Number of entity fields */
} prog_header;
/*
VECTOR_MAKE(char, code_strings );
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++)
- code_globals_add(0);
-
- code_strings_add ('\0');
- code_functions_add (empty_function);
- code_statements_add(empty_statement);
+ /*
+ * 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++)
+ code_globals_add(0);
+
+ code_strings_add ('\0');
+ code_functions_add (empty_function);
+ code_statements_add(empty_statement);
}
void code_test() {
- const char *X;
- size_t size = sizeof(X);
- size_t iter = 0;
-
- #define FOO(Y) \
- X = Y; \
- size = sizeof(Y); \
- for (iter=0; iter < size; iter++) { \
- code_strings_add(X[iter]); \
- }
-
- FOO("m_init");
- FOO("print");
- FOO("hello world\n");
- FOO("m_keydown");
- FOO("m_draw");
- FOO("m_toggle");
- FOO("m_shutdown");
-
- code_globals_add(1); /* m_init */
- code_globals_add(2); /* print */
- 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}});
+ const char *X;
+ size_t size = sizeof(X);
+ size_t iter = 0;
+
+ #define FOO(Y) \
+ X = Y; \
+ size = sizeof(Y); \
+ for (iter=0; iter < size; iter++) { \
+ code_strings_add(X[iter]); \
+ }
+
+ FOO("m_init");
+ FOO("print");
+ FOO("hello world\n");
+ FOO("m_keydown");
+ FOO("m_draw");
+ FOO("m_toggle");
+ FOO("m_shutdown");
+
+ code_globals_add(1); /* m_init */
+ code_globals_add(2); /* print */
+ 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}});
}
void code_write() {
- prog_header code_header={0};
- 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_strings_elements };
- code_header.entfield = 0; /* TODO: */
-
- 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_strings_data, 1, 1 *code_strings_elements, fp);
-
- mem_d(code_statements_data);
- mem_d(code_defs_data);
- mem_d(code_fields_data);
- mem_d(code_functions_data);
- mem_d(code_globals_data);
- mem_d(code_strings_data);
-
- util_debug("GEN","wrote program.dat:\n\
+ prog_header code_header={0};
+ 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_strings_elements };
+ code_header.entfield = 0; /* TODO: */
+
+ 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_strings_data, 1, 1 *code_strings_elements, fp);
+
+ mem_d(code_statements_data);
+ mem_d(code_defs_data);
+ mem_d(code_fields_data);
+ mem_d(code_functions_data);
+ mem_d(code_globals_data);
+ mem_d(code_strings_data);
+
+ util_debug("GEN","wrote program.dat:\n\
version: = %d\n\
crc16: = %d\n\
entfield: = %d\n\
functions {.offset = % 8d, .length = % 8d}\n\
globals {.offset = % 8d, .length = % 8d}\n\
strings {.offset = % 8d, .length = % 8d}\n",
- code_header.version,
- code_header.crc16,
- code_header.entfield,
- code_header.statements.offset,
- code_header.statements.length,
- code_header.defs.offset,
- code_header.defs.length,
- code_header.fields.offset,
- code_header.fields.length,
- code_header.functions.offset,
- code_header.functions.length,
- code_header.strings.offset,
- code_header.strings.length,
- code_header.globals.offset,
- code_header.globals.length
- );
-
- fclose(fp);
+ code_header.version,
+ code_header.crc16,
+ code_header.entfield,
+ code_header.statements.offset,
+ code_header.statements.length,
+ code_header.defs.offset,
+ code_header.defs.length,
+ code_header.fields.offset,
+ code_header.fields.length,
+ code_header.functions.offset,
+ code_header.functions.length,
+ code_header.strings.offset,
+ code_header.strings.length,
+ code_header.globals.offset,
+ code_header.globals.length
+ );
+
+ fclose(fp);
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* intereting like colors for the console.
*/
#ifndef WIN32
-# define CON_BLACK 30
-# define CON_RED 31
-# define CON_GREEN 32
-# define CON_BROWN 33
-# define CON_BLUE 34
-# define CON_MAGENTA 35
-# define CON_CYAN 36
-# define CON_WHITE 37
+# define CON_BLACK 30
+# define CON_RED 31
+# define CON_GREEN 32
+# define CON_BROWN 33
+# define CON_BLUE 34
+# define CON_MAGENTA 35
+# define CON_CYAN 36
+# define CON_WHITE 37
static const int error_color[] = {
- CON_RED,
- CON_CYAN,
- CON_MAGENTA,
- CON_BLUE,
- CON_BROWN,
- CON_WHITE
+ CON_RED,
+ CON_CYAN,
+ CON_MAGENTA,
+ CON_BLUE,
+ CON_BROWN,
+ CON_WHITE
};
#endif
int error_total = 0;
int error_max = 10;
static const char *const error_list[] = {
- "Parsing Error:",
- "Lexing Error:",
- "Internal Error:",
- "Compilation Error:",
- "Preprocessor Error:"
+ "Parsing Error:",
+ "Lexing Error:",
+ "Internal Error:",
+ "Compilation Error:",
+ "Preprocessor Error:"
};
int error(struct lex_file *file, int status, const char *msg, ...) {
- char bu[1024*4]; /* enough? */
- char fu[1024*4]; /* enough? */
- va_list va;
-
- if (error_total + 1 > error_max) {
- fprintf(stderr, "%d errors and more following, bailing\n", error_total);
- exit (-1);
- }
- error_total ++;
+ char bu[1024*4]; /* enough? */
+ char fu[1024*4]; /* enough? */
+ va_list va;
+
+ if (error_total + 1 > error_max) {
+ fprintf(stderr, "%d errors and more following, bailing\n", error_total);
+ exit (-1);
+ }
+ error_total ++;
/* color */
-# ifndef WIN32
- sprintf (bu, "\033[0;%dm%s \033[0;%dm %s:%d ", error_color[status-SHRT_MAX], error_list[status-SHRT_MAX], error_color[(status-1)-SHRT_MAX], file->name, file->line);
+# ifndef WIN32
+ sprintf (bu, "\033[0;%dm%s \033[0;%dm %s:%d ", error_color[status-SHRT_MAX], error_list[status-SHRT_MAX], error_color[(status-1)-SHRT_MAX], file->name, file->line);
#else
- sprintf (bu, "%s ", error_list[status-SHRT_MAX]);
+ sprintf (bu, "%s ", error_list[status-SHRT_MAX]);
#endif
- va_start (va, msg);
- vsprintf (fu, msg, va);
- va_end (va);
- fputs (bu, stderr);
- fputs (fu, stderr);
+ va_start (va, msg);
+ vsprintf (fu, msg, va);
+ va_end (va);
+ fputs (bu, stderr);
+ fputs (fu, stderr);
/* color */
-# ifndef WIN32
- fputs ("\033[0m", stderr);
-# endif
-
- fflush (stderr);
-
- return status;
+# ifndef WIN32
+ fputs ("\033[0m", stderr);
+# endif
+
+ fflush (stderr);
+
+ return status;
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* assume is all systems. (int8_t not required)
*/
#if CHAR_MIN == -128
- typedef unsigned char uint8_t; /* same as below */
+ typedef unsigned char uint8_t; /* same as below */
#elif SCHAR_MIN == -128
- typedef unsigned char uint8_t; /* same as above */
+ typedef unsigned char uint8_t; /* same as above */
#endif
#if SHRT_MAX == 0x7FFF
- typedef short int16_t;
- typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
#elif INT_MAX == 0x7FFF
- typedef int int16_t;
- typedef unsigned int uint16_t;
+ typedef int int16_t;
+ typedef unsigned int uint16_t;
#endif
#if INT_MAX == 0x7FFFFFFF
- typedef int int32_t;
- typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
#elif LONG_MAX == 0x7FFFFFFF
- typedef long int32_t;
- typedef unsigned long uint32_t;
+ typedef long int32_t;
+ typedef unsigned long uint32_t;
#endif
#ifdef _LP64 /* long pointer == 64 */
- typedef unsigned long uintptr_t;
- typedef long intptr_t;
+ typedef unsigned long uintptr_t;
+ typedef long intptr_t;
#else
- typedef unsigned int uintptr_t;
- typedef int intptr_t;
+ typedef unsigned int uintptr_t;
+ typedef int intptr_t;
#endif
/* Ensure type sizes are correct: */
typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1];
//============================ lex.c ================================
//===================================================================
struct lex_file {
- FILE *file; /* file handler */
- char *name; /* name of file */
- char peek [5];
- char lastok[8192];
-
- int last; /* last token */
- int current; /* current token */
- int length; /* bytes left to parse */
- int size; /* never changes (size of file) */
- int line; /* what line are we on? */
+ FILE *file; /* file handler */
+ char *name; /* name of file */
+ char peek [5];
+ char lastok[8192];
+
+ int last; /* last token */
+ int current; /* current token */
+ int length; /* bytes left to parse */
+ int size; /* never changes (size of file) */
+ int line; /* what line are we on? */
};
/*
//========================== typedef.c ==============================
//===================================================================
typedef struct typedef_node_t {
- char *name;
+ char *name;
} typedef_node;
void typedef_init();
int util_getline (char **, size_t *, FILE *);
#ifdef NOTRACK
-# define mem_a(x) malloc(x)
-# define mem_d(x) free (x)
+# define mem_a(x) malloc(x)
+# define mem_d(x) free (x)
#else
-# define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
-# define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
+# define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
+# define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
#endif
#define VECTOR_MAKE(T,N) \
* 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_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 */
- };
- /* operand 2 */
- union {
- int16_t s2; /* signed */
- uint16_t u2; /* unsigned */
- };
- /* operand 3 */
- union {
- int16_t s3; /* signed */
- uint16_t u3; /* unsigned */
- };
-
- /*
- * 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.
- */
+ uint16_t opcode;
+
+ /* operand 1 */
+ union {
+ int16_t s1; /* signed */
+ uint16_t u1; /* unsigned */
+ };
+ /* operand 2 */
+ union {
+ int16_t s2; /* signed */
+ uint16_t u2; /* unsigned */
+ };
+ /* operand 3 */
+ union {
+ int16_t s3; /* signed */
+ uint16_t u3; /* unsigned */
+ };
+
+ /*
+ * 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;
+ /* 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;
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 */
- uint32_t nargs; /* number of arguments */
- uint8_t argsize[8]; /* size of arguments (keep 8 always?) */
+ 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 */
+ uint32_t nargs; /* number of arguments */
+ uint8_t argsize[8]; /* size of arguments (keep 8 always?) */
} prog_section_function;
/*
* this is what things compile to (from the C code).
*/
enum {
- INSTR_DONE,
- INSTR_MUL_F,
- INSTR_MUL_V,
- INSTR_MUL_FV,
- INSTR_MUL_VF,
- INSTR_DIV_F,
- INSTR_ADD_F,
- INSTR_ADD_V,
- INSTR_SUB_F,
- INSTR_SUB_V,
- INSTR_EQ_F,
- INSTR_EQ_V,
- INSTR_EQ_S,
- INSTR_EQ_E,
- INSTR_EQ_FNC,
- INSTR_NE_F,
- INSTR_NE_V,
- INSTR_NE_S,
- INSTR_NE_E,
- INSTR_NE_FNC,
- INSTR_LE,
- INSTR_GE,
- INSTR_LT,
- INSTR_GT,
- INSTR_LOAD_F,
- INSTR_LOAD_V,
- INSTR_LOAD_S,
- INSTR_LOAD_ENT,
- INSTR_LOAD_FLD,
- INSTR_LOAD_FNC,
- INSTR_ADDRESS,
- INSTR_STORE_F,
- INSTR_STORE_V,
- INSTR_STORE_S,
- INSTR_STORE_ENT,
- INSTR_STORE_FLD,
- INSTR_STORE_FNC,
- INSTR_STOREP_F,
- INSTR_STOREP_V,
- INSTR_STOREP_S,
- INSTR_STOREP_ENT,
- INSTR_STOREP_FLD,
- INSTR_STOREP_FNC,
- INSTR_RETURN,
- INSTR_NOT_F,
- INSTR_NOT_V,
- INSTR_NOT_S,
- INSTR_NOT_ENT,
- INSTR_NOT_FNC,
- INSTR_IF,
- INSTR_IFNOT,
- INSTR_CALL0,
- INSTR_CALL1,
- INSTR_CALL2,
- INSTR_CALL3,
- INSTR_CALL4,
- INSTR_CALL5,
- INSTR_CALL6,
- INSTR_CALL7,
- INSTR_CALL8,
- INSTR_STATE,
- INSTR_GOTO,
- INSTR_AND,
- INSTR_OR,
- INSTR_BITAND,
- INSTR_BITOR
+ INSTR_DONE,
+ INSTR_MUL_F,
+ INSTR_MUL_V,
+ INSTR_MUL_FV,
+ INSTR_MUL_VF,
+ INSTR_DIV_F,
+ INSTR_ADD_F,
+ INSTR_ADD_V,
+ INSTR_SUB_F,
+ INSTR_SUB_V,
+ INSTR_EQ_F,
+ INSTR_EQ_V,
+ INSTR_EQ_S,
+ INSTR_EQ_E,
+ INSTR_EQ_FNC,
+ INSTR_NE_F,
+ INSTR_NE_V,
+ INSTR_NE_S,
+ INSTR_NE_E,
+ INSTR_NE_FNC,
+ INSTR_LE,
+ INSTR_GE,
+ INSTR_LT,
+ INSTR_GT,
+ INSTR_LOAD_F,
+ INSTR_LOAD_V,
+ INSTR_LOAD_S,
+ INSTR_LOAD_ENT,
+ INSTR_LOAD_FLD,
+ INSTR_LOAD_FNC,
+ INSTR_ADDRESS,
+ INSTR_STORE_F,
+ INSTR_STORE_V,
+ INSTR_STORE_S,
+ INSTR_STORE_ENT,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FNC,
+ INSTR_STOREP_F,
+ INSTR_STOREP_V,
+ INSTR_STOREP_S,
+ INSTR_STOREP_ENT,
+ INSTR_STOREP_FLD,
+ INSTR_STOREP_FNC,
+ INSTR_RETURN,
+ INSTR_NOT_F,
+ INSTR_NOT_V,
+ INSTR_NOT_S,
+ INSTR_NOT_ENT,
+ INSTR_NOT_FNC,
+ INSTR_IF,
+ INSTR_IFNOT,
+ INSTR_CALL0,
+ INSTR_CALL1,
+ INSTR_CALL2,
+ INSTR_CALL3,
+ INSTR_CALL4,
+ INSTR_CALL5,
+ INSTR_CALL6,
+ INSTR_CALL7,
+ INSTR_CALL8,
+ INSTR_STATE,
+ INSTR_GOTO,
+ INSTR_AND,
+ INSTR_OR,
+ INSTR_BITAND,
+ INSTR_BITOR
};
/*
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* than keyword lexing.
*/
static const char *const lex_keywords[] = {
- "do", "else", "if", "while",
- "break", "continue", "return", "goto",
- "for", "typedef"
+ "do", "else", "if", "while",
+ "break", "continue", "return", "goto",
+ "for", "typedef"
};
struct lex_file *lex_open(FILE *fp) {
- struct lex_file *lex = mem_a(sizeof(struct lex_file));
- if (!lex || !fp)
- return NULL;
-
- lex->file = fp;
- fseek(lex->file, 0, SEEK_END);
- lex->length = ftell(lex->file);
- lex->size = lex->length; /* copy, this is never changed */
- fseek(lex->file, 0, SEEK_SET);
- lex->last = 0;
- lex->line = 0;
-
- memset(lex->peek, 0, sizeof(lex->peek));
- return lex;
+ struct lex_file *lex = mem_a(sizeof(struct lex_file));
+ if (!lex || !fp)
+ return NULL;
+
+ lex->file = fp;
+ fseek(lex->file, 0, SEEK_END);
+ lex->length = ftell(lex->file);
+ lex->size = lex->length; /* copy, this is never changed */
+ fseek(lex->file, 0, SEEK_SET);
+ lex->last = 0;
+ lex->line = 0;
+
+ memset(lex->peek, 0, sizeof(lex->peek));
+ return lex;
}
void lex_close(struct lex_file *file) {
- if (!file) return;
-
- fclose(file->file); /* may already be closed */
- mem_d (file);
+ if (!file) return;
+
+ fclose(file->file); /* may already be closed */
+ mem_d (file);
}
static void lex_addch(int ch, struct lex_file *file) {
- if (file->current < sizeof(file->lastok)-1)
- file->lastok[file->current++] = (char)ch;
- if (file->current == sizeof(file->lastok)-1)
- file->lastok[file->current] = (char)'\0';
+ if (file->current < sizeof(file->lastok)-1)
+ file->lastok[file->current++] = (char)ch;
+ if (file->current == sizeof(file->lastok)-1)
+ file->lastok[file->current] = (char)'\0';
}
static inline void lex_clear(struct lex_file *file) {
- file->current = 0;
+ file->current = 0;
}
/*
* it's own internal state for this.
*/
static int lex_inget(struct lex_file *file) {
- file->length --;
- if (file->last > 0)
- return file->peek[--file->last];
- return fgetc(file->file);
+ file->length --;
+ if (file->last > 0)
+ return file->peek[--file->last];
+ return fgetc(file->file);
}
static void lex_unget(int ch, struct lex_file *file) {
- if (file->last < sizeof(file->peek))
- file->peek[file->last++] = ch;
- file->length ++;
+ if (file->last < sizeof(file->peek))
+ file->peek[file->last++] = ch;
+ file->length ++;
}
/*
* supports. Moving up in this world!
*/
static int lex_trigraph(struct lex_file *file) {
- int ch;
- if ((ch = lex_inget(file)) != '?') {
- lex_unget(ch, file);
- return '?';
- }
-
- ch = lex_inget(file);
- switch (ch) {
- case '(' : return '[' ;
- case ')' : return ']' ;
- case '/' : return '\\';
- case '\'': return '^' ;
- case '<' : return '{' ;
- case '>' : return '}' ;
- case '!' : return '|' ;
- case '-' : return '~' ;
- case '=' : return '#' ;
- default:
- lex_unget('?', file);
- lex_unget(ch , file);
- return '?';
- }
- return '?';
+ int ch;
+ if ((ch = lex_inget(file)) != '?') {
+ lex_unget(ch, file);
+ return '?';
+ }
+
+ ch = lex_inget(file);
+ switch (ch) {
+ case '(' : return '[' ;
+ case ')' : return ']' ;
+ case '/' : return '\\';
+ case '\'': return '^' ;
+ case '<' : return '{' ;
+ case '>' : return '}' ;
+ case '!' : return '|' ;
+ case '-' : return '~' ;
+ case '=' : return '#' ;
+ default:
+ lex_unget('?', file);
+ lex_unget(ch , file);
+ return '?';
+ }
+ return '?';
}
static int lex_digraph(struct lex_file *file, int first) {
- int ch = lex_inget(file);
- switch (first) {
- case '<':
- if (ch == '%') return '{';
- if (ch == ':') return '[';
- break;
- case '%':
- if (ch == '>') return '}';
- if (ch == ':') return '#';
- break;
- case ':':
- if (ch == '>') return ']';
- break;
- }
-
- lex_unget(ch, file);
- return first;
+ int ch = lex_inget(file);
+ switch (first) {
+ case '<':
+ if (ch == '%') return '{';
+ if (ch == ':') return '[';
+ break;
+ case '%':
+ if (ch == '>') return '}';
+ if (ch == ':') return '#';
+ break;
+ case ':':
+ if (ch == '>') return ']';
+ break;
+ }
+
+ lex_unget(ch, file);
+ return first;
}
static int lex_getch(struct lex_file *file) {
- int ch = lex_inget(file);
+ int ch = lex_inget(file);
- static int str = 0;
- switch (ch) {
- case '?' :
- return lex_trigraph(file);
- case '<' :
- case ':' :
- case '%' :
- case '"' : str = !str; if (str) { file->line ++; }
- return lex_digraph(file, ch);
-
- case '\n':
- if (!str)
- file->line++;
- }
-
- return ch;
+ static int str = 0;
+ switch (ch) {
+ case '?' :
+ return lex_trigraph(file);
+ case '<' :
+ case ':' :
+ case '%' :
+ case '"' : str = !str; if (str) { file->line ++; }
+ return lex_digraph(file, ch);
+
+ case '\n':
+ if (!str)
+ file->line++;
+ }
+
+ return ch;
}
static int lex_get(struct lex_file *file) {
- int ch;
- if (!isspace(ch = lex_getch(file)))
- return ch;
-
- /* skip over all spaces */
- while (isspace(ch) && ch != '\n')
- ch = lex_getch(file);
-
- if (ch == '\n')
- return ch;
- lex_unget(ch, file);
- return ' ';
+ int ch;
+ if (!isspace(ch = lex_getch(file)))
+ return ch;
+
+ /* skip over all spaces */
+ while (isspace(ch) && ch != '\n')
+ ch = lex_getch(file);
+
+ if (ch == '\n')
+ return ch;
+ lex_unget(ch, file);
+ return ' ';
}
static int lex_skipchr(struct lex_file *file) {
- int ch;
- int it;
-
- lex_clear(file);
- lex_addch('\'', file);
-
- for (it = 0; it < 2 && ((ch = lex_inget(file)) != '\''); it++) {
- lex_addch(ch, file);
-
- if (ch == '\n')
- return ERROR_LEX;
- if (ch == '\\')
- lex_addch(lex_getch(file), file);
- }
- lex_addch('\'', file);
- lex_addch('\0', file);
-
- if (it > 2)
- return ERROR_LEX;
-
- return LEX_CHRLIT;
+ int ch;
+ int it;
+
+ lex_clear(file);
+ lex_addch('\'', file);
+
+ for (it = 0; it < 2 && ((ch = lex_inget(file)) != '\''); it++) {
+ lex_addch(ch, file);
+
+ if (ch == '\n')
+ return ERROR_LEX;
+ if (ch == '\\')
+ lex_addch(lex_getch(file), file);
+ }
+ lex_addch('\'', file);
+ lex_addch('\0', file);
+
+ if (it > 2)
+ return ERROR_LEX;
+
+ return LEX_CHRLIT;
}
static int lex_skipstr(struct lex_file *file) {
- int ch;
- lex_clear(file);
- lex_addch('"', file);
-
- while ((ch = lex_getch(file)) != '"') {
- if (ch == '\n' || ch == EOF)
- return ERROR_LEX;
-
- lex_addch(ch, file);
- if (ch == '\\')
- lex_addch(lex_inget(file), file);
- }
-
- lex_addch('"', file);
- lex_addch('\0', file);
-
- return LEX_STRLIT;
+ int ch;
+ lex_clear(file);
+ lex_addch('"', file);
+
+ while ((ch = lex_getch(file)) != '"') {
+ if (ch == '\n' || ch == EOF)
+ return ERROR_LEX;
+
+ lex_addch(ch, file);
+ if (ch == '\\')
+ lex_addch(lex_inget(file), file);
+ }
+
+ lex_addch('"', file);
+ lex_addch('\0', file);
+
+ return LEX_STRLIT;
}
static int lex_skipcmt(struct lex_file *file) {
- int ch;
- lex_clear(file);
- ch = lex_getch(file);
-
- if (ch == '/') {
- lex_addch('/', file);
- lex_addch('/', file);
-
- while ((ch = lex_getch(file)) != '\n') {
- if (ch == '\\') {
- lex_addch(ch, file);
- lex_addch(lex_getch(file), file);
- } else {
- lex_addch(ch, file);
- }
- }
- lex_addch('\0', file);
- return LEX_COMMENT;
- }
-
- if (ch != '*') {
- lex_unget(ch, file);
- return '/';
- }
-
- lex_addch('/', file);
-
- /* hate this */
- do {
- lex_addch(ch, file);
- while ((ch = lex_getch(file)) != '*') {
- if (ch == EOF)
- return error(file, ERROR_LEX, "malformatted comment");
- else
- lex_addch(ch, file);
- }
- lex_addch(ch, file);
- } while ((ch = lex_getch(file)) != '/');
-
- lex_addch('/', file);
- lex_addch('\0', file);
-
- return LEX_COMMENT;
+ int ch;
+ lex_clear(file);
+ ch = lex_getch(file);
+
+ if (ch == '/') {
+ lex_addch('/', file);
+ lex_addch('/', file);
+
+ while ((ch = lex_getch(file)) != '\n') {
+ if (ch == '\\') {
+ lex_addch(ch, file);
+ lex_addch(lex_getch(file), file);
+ } else {
+ lex_addch(ch, file);
+ }
+ }
+ lex_addch('\0', file);
+ return LEX_COMMENT;
+ }
+
+ if (ch != '*') {
+ lex_unget(ch, file);
+ return '/';
+ }
+
+ lex_addch('/', file);
+
+ /* hate this */
+ do {
+ lex_addch(ch, file);
+ while ((ch = lex_getch(file)) != '*') {
+ if (ch == EOF)
+ return error(file, ERROR_LEX, "malformatted comment");
+ else
+ lex_addch(ch, file);
+ }
+ lex_addch(ch, file);
+ } while ((ch = lex_getch(file)) != '/');
+
+ lex_addch('/', file);
+ lex_addch('\0', file);
+
+ return LEX_COMMENT;
}
static int lex_getsource(struct lex_file *file) {
- int ch = lex_get(file);
-
- /* skip char/string/comment */
- switch (ch) {
- case '\'': return lex_skipchr(file);
- case '"': return lex_skipstr(file);
- case '/': return lex_skipcmt(file);
- default:
- return ch;
- }
+ int ch = lex_get(file);
+
+ /* skip char/string/comment */
+ switch (ch) {
+ case '\'': return lex_skipchr(file);
+ case '"': return lex_skipstr(file);
+ case '/': return lex_skipcmt(file);
+ default:
+ return ch;
+ }
}
int lex_token(struct lex_file *file) {
- int ch = lex_getsource(file);
- int it;
-
- /* valid identifier */
- if (ch > 0 && (ch == '_' || isalpha(ch))) {
- lex_clear(file);
-
- /*
- * Yes this is dirty, but there is no other _sane_ easy
- * way to do it, this is what I call defensive programming
- * if something breaks, add more defense :-)
- */
- while (ch > 0 && ch != ' ' && ch != '(' &&
- ch != '\n' && ch != ';' && ch != ')') {
- lex_addch(ch, file);
- ch = lex_getsource(file);
- }
- lex_unget(ch, file);
- lex_addch('\0', file);
-
- /* look inside the table for a keyword .. */
- for (it = 0; it < sizeof(lex_keywords)/sizeof(*lex_keywords); it++)
- if (!strncmp(file->lastok, lex_keywords[it], sizeof(lex_keywords[it])))
- return it;
-
- /* try a type? */
- #define TEST_TYPE(X) \
- do { \
- if (!strncmp(X, "float", sizeof("float"))) \
- return TOKEN_FLOAT; \
- if (!strncmp(X, "vector", sizeof("vector"))) \
- return TOKEN_VECTOR; \
- if (!strncmp(X, "string", sizeof("string"))) \
- return TOKEN_STRING; \
- if (!strncmp(X, "entity", sizeof("entity"))) \
- return TOKEN_ENTITY; \
- if (!strncmp(X, "void" , sizeof("void"))) \
- return TOKEN_VOID; \
- } while(0)
-
- TEST_TYPE(file->lastok);
-
- /* try the hashtable for typedefs? */
- if (typedef_find(file->lastok))
- TEST_TYPE(typedef_find(file->lastok)->name);
-
- #undef TEST_TYPE
- return LEX_IDENT;
- }
- return ch;
+ int ch = lex_getsource(file);
+ int it;
+
+ /* valid identifier */
+ if (ch > 0 && (ch == '_' || isalpha(ch))) {
+ lex_clear(file);
+
+ /*
+ * Yes this is dirty, but there is no other _sane_ easy
+ * way to do it, this is what I call defensive programming
+ * if something breaks, add more defense :-)
+ */
+ while (ch > 0 && ch != ' ' && ch != '(' &&
+ ch != '\n' && ch != ';' && ch != ')') {
+ lex_addch(ch, file);
+ ch = lex_getsource(file);
+ }
+ lex_unget(ch, file);
+ lex_addch('\0', file);
+
+ /* look inside the table for a keyword .. */
+ for (it = 0; it < sizeof(lex_keywords)/sizeof(*lex_keywords); it++)
+ if (!strncmp(file->lastok, lex_keywords[it], sizeof(lex_keywords[it])))
+ return it;
+
+ /* try a type? */
+ #define TEST_TYPE(X) \
+ do { \
+ if (!strncmp(X, "float", sizeof("float"))) \
+ return TOKEN_FLOAT; \
+ if (!strncmp(X, "vector", sizeof("vector"))) \
+ return TOKEN_VECTOR; \
+ if (!strncmp(X, "string", sizeof("string"))) \
+ return TOKEN_STRING; \
+ if (!strncmp(X, "entity", sizeof("entity"))) \
+ return TOKEN_ENTITY; \
+ if (!strncmp(X, "void" , sizeof("void"))) \
+ return TOKEN_VOID; \
+ } while(0)
+
+ TEST_TYPE(file->lastok);
+
+ /* try the hashtable for typedefs? */
+ if (typedef_find(file->lastok))
+ TEST_TYPE(typedef_find(file->lastok)->name);
+
+ #undef TEST_TYPE
+ return LEX_IDENT;
+ }
+ return ch;
}
void lex_reset(struct lex_file *file) {
- file->current = 0;
- file->last = 0;
- file->length = file->size;
- fseek(file->file, 0, SEEK_SET);
-
- memset(file->peek, 0, sizeof(file->peek ));
- memset(file->lastok, 0, sizeof(file->lastok));
+ file->current = 0;
+ file->last = 0;
+ file->length = file->size;
+ fseek(file->file, 0, SEEK_SET);
+
+ memset(file->peek, 0, sizeof(file->peek ));
+ memset(file->lastok, 0, sizeof(file->lastok));
}
/*
* recrusion.
*/
struct lex_file *lex_include(struct lex_file *lex, char *file) {
- util_strrq(file);
- if (strncmp(lex->name, file, strlen(lex->name)) == 0) {
- error(lex, ERROR_LEX, "Source file cannot include itself\n");
- exit (-1);
- }
-
- FILE *fp = fopen(file, "r");
- if (!fp) {
- error(lex, ERROR_LEX, "Include file `%s` doesn't exist\n", file);
- exit (-1);
- }
-
- return lex_open(fp);
+ util_strrq(file);
+ if (strncmp(lex->name, file, strlen(lex->name)) == 0) {
+ error(lex, ERROR_LEX, "Source file cannot include itself\n");
+ exit (-1);
+ }
+
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error(lex, ERROR_LEX, "Include file `%s` doesn't exist\n", file);
+ exit (-1);
+ }
+
+ return lex_open(fp);
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
*/
#include "gmqcc.h"
int main(int argc, char **argv) {
- argc--;
- argv++;
-
- //const char *ifile = argv[0];
- FILE *fp;
-
- /*TODO: proper interface swith switches*/
-
- asm_init ("test.qs", &fp);
- asm_parse(fp);
- asm_close(fp);
- return 0;
+ argc--;
+ argv++;
+
+ //const char *ifile = argv[0];
+ FILE *fp;
+
+ /*TODO: proper interface swith switches*/
+
+ asm_init ("test.qs", &fp);
+ asm_parse(fp);
+ asm_close(fp);
+ return 0;
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
/* compile-time constant for type constants */
typedef struct {
- char *name;
- int type;
- float value[3];
- char *string; /* string value if constant is string literal */
+ char *name;
+ int type;
+ float value[3];
+ char *string; /* string value if constant is string literal */
} constant;
VECTOR_MAKE(constant, compile_constants);
void compile_constant_debug() {
- int iter = 0;
- for(; iter < compile_constants_elements; iter++) {
- constant *c = &compile_constants_data[iter];
- switch(c->type) {
- case TYPE_FLOAT: printf("constant: %s FLOAT %f\n", c->name, c->value[0]); break;
- case TYPE_VECTOR: printf("constant: %s VECTOR {%f,%f,%f}\n",c->name, c->value[0], c->value[1], c->value[2]); break;
- case TYPE_STRING: printf("constant: %s STRING %s\n", c->name, c->string); break;
- case TYPE_VOID: printf("constant: %s VOID %s\n", c->name, c->string); break;
- }
- }
+ int iter = 0;
+ for(; iter < compile_constants_elements; iter++) {
+ constant *c = &compile_constants_data[iter];
+ switch(c->type) {
+ case TYPE_FLOAT: printf("constant: %s FLOAT %f\n", c->name, c->value[0]); break;
+ case TYPE_VECTOR: printf("constant: %s VECTOR {%f,%f,%f}\n",c->name, c->value[0], c->value[1], c->value[2]); break;
+ case TYPE_STRING: printf("constant: %s STRING %s\n", c->name, c->string); break;
+ case TYPE_VOID: printf("constant: %s VOID %s\n", c->name, c->string); break;
+ }
+ }
}
/*
* Generates a parse tree out of the lexees generated by the lexer. This
* is where the tree is built. This is where valid check is performed.
*/
-int parse_gen(struct lex_file *file) {
- int token = 0;
- while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0) {
- switch (token) {
- case TOKEN_TYPEDEF: {
- char *f; /* from */
- char *t; /* to */
-
- token = lex_token(file);
- token = lex_token(file); f = util_strdup(file->lastok);
- token = lex_token(file);
- token = lex_token(file); t = util_strdup(file->lastok);
-
- typedef_add(file, f, t);
- mem_d(f);
- mem_d(t);
-
- token = lex_token(file);
- if (token == ' ')
- token = lex_token(file);
-
- if (token != ';')
- error(file, ERROR_PARSE, "Expected a `;` at end of typedef statement");
-
- token = lex_token(file);
- break;
- }
-
- case TOKEN_VOID: goto fall;
- case TOKEN_STRING: goto fall;
- case TOKEN_VECTOR: goto fall;
- case TOKEN_ENTITY: goto fall;
- case TOKEN_FLOAT: goto fall;
- {
- fall:;
- char *name = NULL;
- int type = token; /* story copy */
-
- /* skip over space */
- token = lex_token(file);
- if (token == ' ')
- token = lex_token(file);
-
- /* save name */
- name = util_strdup(file->lastok);
-
- /* skip spaces */
- token = lex_token(file);
- if (token == ' ')
- token = lex_token(file);
-
- if (token == ';') {
- /*
- * Definitions go to the defs table, they don't have
- * any sort of data with them yet.
- */
- } else if (token == '=') {
- token = lex_token(file);
- if (token == ' ')
- token = lex_token(file);
-
- /* strings are in file->lastok */
- switch (type) {
- case TOKEN_VOID:
- error(file, ERROR_PARSE, "Cannot assign value to type void\n");
-
- /* TODO: Validate (end quote), strip quotes for constant add, name constant */
- case TOKEN_STRING:
- 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)
- });
- break;
- /* TODO: name constant, old qc vec literals, whitespace fixes, name constant */
- case TOKEN_VECTOR: {
- float compile_calc_x = 0;
- float compile_calc_y = 0;
- float compile_calc_z = 0;
- int compile_calc_d = 0; /* dot? */
- int compile_calc_s = 0; /* sign (-, +) */
-
- char compile_data[1024];
- char *compile_eval = compile_data;
-
- if (token != '{')
- error(file, ERROR_PARSE, "Expected initializer list {} for vector constant\n");
-
- /*
- * This parses a single vector element: x,y & z. This will handle all the
- * complicated mechanics of a vector, and can be extended as well. This
- * is a rather large macro, and is #undef'd after it's use below.
- */
- #define PARSE_VEC_ELEMENT(NAME, BIT) \
- token = lex_token(file); \
- if (token == ' ') \
- token = lex_token(file); \
- if (token == '.') \
- compile_calc_d = 1; \
- if (!isdigit(token) && !compile_calc_d && token != '+' && token != '-') \
- error(file, ERROR_PARSE,"Invalid constant initializer element %c for vector, must be numeric\n", NAME); \
- if (token == '+') \
- compile_calc_s = '+'; \
- if (token == '-' && !compile_calc_s) \
- compile_calc_s = '-'; \
- while (isdigit(token) || token == '.' || token == '+' || token == '-') { \
- *compile_eval++ = token; \
- token = lex_token(file); \
- if (token == '.' && compile_calc_d) { \
- error(file, ERROR_PARSE, "Invalid constant initializer element %c for vector, must be numeric.\n", NAME); \
- token = lex_token(file); \
- } \
- if ((token == '-' || token == '+') && compile_calc_s) { \
- error(file, ERROR_PARSE, "Invalid constant initializer sign for vector element %c\n", NAME); \
- token = lex_token(file); \
- } \
- else if (token == '.' && !compile_calc_d) \
- compile_calc_d = 1; \
- else if (token == '-' && !compile_calc_s) \
- compile_calc_s = '-'; \
- else if (token == '+' && !compile_calc_s) \
- compile_calc_s = '+'; \
- } \
- if (token == ' ') \
- token = lex_token(file); \
- if (NAME != 'z') { \
- if (token != ',' && token != ' ') \
- error(file, ERROR_PARSE, "invalid constant initializer element %c for vector (missing spaces, or comma delimited list?)\n", NAME); \
- } else if (token != '}') { \
- error(file, ERROR_PARSE, "Expected `}` on end of constant initialization for vector\n"); \
- } \
- compile_calc_##BIT = atof(compile_data); \
- compile_calc_d = 0; \
- compile_calc_s = 0; \
- compile_eval = &compile_data[0]; \
- memset(compile_data, 0, sizeof(compile_data))
-
- /*
- * Parse all elements using the macro above.
- * We must undef the macro afterwards.
- */
- PARSE_VEC_ELEMENT('x', x);
- PARSE_VEC_ELEMENT('y', y);
- PARSE_VEC_ELEMENT('z', z);
- #undef PARSE_VEC_ELEMENT
-
- /* Check for the semi-colon... */
- token = lex_token(file);
- if (token == ' ')
- token = lex_token(file);
- if (token != ';')
- 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
- });
- break;
- }
-
- case TOKEN_ENTITY:
- 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
- });
- break;
- }
- } else if (token == '(') {
- printf("FUNCTION ??\n");
- }
- mem_d(name);
- }
-
- /*
- * From here down is all language punctuation: There is no
- * need to actual create tokens from these because they're already
- * tokenized as these individual tokens (which are in a special area
- * of the ascii table which doesn't conflict with our other tokens
- * which are higer than the ascii table.)
- */
- case '#':
- token = lex_token(file); /* skip '#' */
- if (token == ' ')
- token = lex_token(file);
- /*
- * If we make it here we found a directive, the supported
- * directives so far are #include.
- */
- if (strncmp(file->lastok, "include", sizeof("include")) == 0) {
- /*
- * We only suport include " ", not <> like in C (why?)
- * because the latter is silly.
- */
- while (*file->lastok != '"' && token != '\n')
- token = lex_token(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);
- struct lex_file *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
- });
- parse_gen(next);
- mem_d (copy);
- lex_close(next);
- }
- /* skip all tokens to end of directive */
- while (token != '\n')
- token = lex_token(file);
- break;
-
- case LEX_IDENT:
- token = lex_token(file);
- break;
- }
- }
- compile_constant_debug();
- lex_reset(file);
- return 1;
-}
+int parse_gen(struct lex_file *file) {
+ int token = 0;
+ while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0) {
+ switch (token) {
+ case TOKEN_TYPEDEF: {
+ char *f; /* from */
+ char *t; /* to */
+
+ token = lex_token(file);
+ token = lex_token(file); f = util_strdup(file->lastok);
+ token = lex_token(file);
+ token = lex_token(file); t = util_strdup(file->lastok);
+
+ typedef_add(file, f, t);
+ mem_d(f);
+ mem_d(t);
+
+ token = lex_token(file);
+ if (token == ' ')
+ token = lex_token(file);
+
+ if (token != ';')
+ error(file, ERROR_PARSE, "Expected a `;` at end of typedef statement");
+
+ token = lex_token(file);
+ break;
+ }
+
+ case TOKEN_VOID: goto fall;
+ case TOKEN_STRING: goto fall;
+ case TOKEN_VECTOR: goto fall;
+ case TOKEN_ENTITY: goto fall;
+ case TOKEN_FLOAT: goto fall;
+ {
+ fall:;
+ char *name = NULL;
+ int type = token; /* story copy */
+
+ /* skip over space */
+ token = lex_token(file);
+ if (token == ' ')
+ token = lex_token(file);
+
+ /* save name */
+ name = util_strdup(file->lastok);
+
+ /* skip spaces */
+ token = lex_token(file);
+ if (token == ' ')
+ token = lex_token(file);
+
+ if (token == ';') {
+ /*
+ * Definitions go to the defs table, they don't have
+ * any sort of data with them yet.
+ */
+ } else if (token == '=') {
+ token = lex_token(file);
+ if (token == ' ')
+ token = lex_token(file);
+
+ /* strings are in file->lastok */
+ switch (type) {
+ case TOKEN_VOID:
+ error(file, ERROR_PARSE, "Cannot assign value to type void\n");
+
+ /* TODO: Validate (end quote), strip quotes for constant add, name constant */
+ case TOKEN_STRING:
+ 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)
+ });
+ break;
+ /* TODO: name constant, old qc vec literals, whitespace fixes, name constant */
+ case TOKEN_VECTOR: {
+ float compile_calc_x = 0;
+ float compile_calc_y = 0;
+ float compile_calc_z = 0;
+ int compile_calc_d = 0; /* dot? */
+ int compile_calc_s = 0; /* sign (-, +) */
+
+ char compile_data[1024];
+ char *compile_eval = compile_data;
+
+ if (token != '{')
+ error(file, ERROR_PARSE, "Expected initializer list {} for vector constant\n");
+
+ /*
+ * This parses a single vector element: x,y & z. This will handle all the
+ * complicated mechanics of a vector, and can be extended as well. This
+ * is a rather large macro, and is #undef'd after it's use below.
+ */
+ #define PARSE_VEC_ELEMENT(NAME, BIT) \
+ token = lex_token(file); \
+ if (token == ' ') \
+ token = lex_token(file); \
+ if (token == '.') \
+ compile_calc_d = 1; \
+ if (!isdigit(token) && !compile_calc_d && token != '+' && token != '-') \
+ error(file, ERROR_PARSE,"Invalid constant initializer element %c for vector, must be numeric\n", NAME); \
+ if (token == '+') \
+ compile_calc_s = '+'; \
+ if (token == '-' && !compile_calc_s) \
+ compile_calc_s = '-'; \
+ while (isdigit(token) || token == '.' || token == '+' || token == '-') { \
+ *compile_eval++ = token; \
+ token = lex_token(file); \
+ if (token == '.' && compile_calc_d) { \
+ error(file, ERROR_PARSE, "Invalid constant initializer element %c for vector, must be numeric.\n", NAME); \
+ token = lex_token(file); \
+ } \
+ if ((token == '-' || token == '+') && compile_calc_s) { \
+ error(file, ERROR_PARSE, "Invalid constant initializer sign for vector element %c\n", NAME); \
+ token = lex_token(file); \
+ } \
+ else if (token == '.' && !compile_calc_d) \
+ compile_calc_d = 1; \
+ else if (token == '-' && !compile_calc_s) \
+ compile_calc_s = '-'; \
+ else if (token == '+' && !compile_calc_s) \
+ compile_calc_s = '+'; \
+ } \
+ if (token == ' ') \
+ token = lex_token(file); \
+ if (NAME != 'z') { \
+ if (token != ',' && token != ' ') \
+ error(file, ERROR_PARSE, "invalid constant initializer element %c for vector (missing spaces, or comma delimited list?)\n", NAME); \
+ } else if (token != '}') { \
+ error(file, ERROR_PARSE, "Expected `}` on end of constant initialization for vector\n"); \
+ } \
+ compile_calc_##BIT = atof(compile_data); \
+ compile_calc_d = 0; \
+ compile_calc_s = 0; \
+ compile_eval = &compile_data[0]; \
+ memset(compile_data, 0, sizeof(compile_data))
+
+ /*
+ * Parse all elements using the macro above.
+ * We must undef the macro afterwards.
+ */
+ PARSE_VEC_ELEMENT('x', x);
+ PARSE_VEC_ELEMENT('y', y);
+ PARSE_VEC_ELEMENT('z', z);
+ #undef PARSE_VEC_ELEMENT
+
+ /* Check for the semi-colon... */
+ token = lex_token(file);
+ if (token == ' ')
+ token = lex_token(file);
+ if (token != ';')
+ 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
+ });
+ break;
+ }
+
+ case TOKEN_ENTITY:
+ 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
+ });
+ break;
+ }
+ } else if (token == '(') {
+ printf("FUNCTION ??\n");
+ }
+ mem_d(name);
+ }
+
+ /*
+ * From here down is all language punctuation: There is no
+ * need to actual create tokens from these because they're already
+ * tokenized as these individual tokens (which are in a special area
+ * of the ascii table which doesn't conflict with our other tokens
+ * which are higer than the ascii table.)
+ */
+ case '#':
+ token = lex_token(file); /* skip '#' */
+ if (token == ' ')
+ token = lex_token(file);
+ /*
+ * If we make it here we found a directive, the supported
+ * directives so far are #include.
+ */
+ if (strncmp(file->lastok, "include", sizeof("include")) == 0) {
+ /*
+ * We only suport include " ", not <> like in C (why?)
+ * because the latter is silly.
+ */
+ while (*file->lastok != '"' && token != '\n')
+ token = lex_token(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);
+ struct lex_file *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
+ });
+ parse_gen(next);
+ mem_d (copy);
+ lex_close(next);
+ }
+ /* skip all tokens to end of directive */
+ while (token != '\n')
+ token = lex_token(file);
+ break;
+
+ case LEX_IDENT:
+ token = lex_token(file);
+ break;
+ }
+ }
+ compile_constant_debug();
+ lex_reset(file);
+ return 1;
+}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
static typedef_node *typedef_table[1024];
void typedef_init() {
- int i;
- for(i = 0; i < sizeof(typedef_table)/sizeof(*typedef_table); i++)
- typedef_table[i] = NULL;
+ int i;
+ for(i = 0; i < sizeof(typedef_table)/sizeof(*typedef_table); i++)
+ typedef_table[i] = NULL;
}
unsigned int typedef_hash(const char *s) {
- unsigned int hash = 0;
- unsigned int size = strlen(s);
- unsigned int iter;
-
- for (iter = 0; iter < size; iter++) {
- hash += s[iter];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash % 1024;
+ unsigned int hash = 0;
+ unsigned int size = strlen(s);
+ unsigned int iter;
+
+ for (iter = 0; iter < size; iter++) {
+ hash += s[iter];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash % 1024;
}
typedef_node *typedef_find(const char *s) {
- unsigned int hash = typedef_hash(s);
- typedef_node *find = typedef_table[hash];
- return find;
+ unsigned int hash = typedef_hash(s);
+ typedef_node *find = typedef_table[hash];
+ return find;
}
void typedef_clear() {
- int i;
- for(i = 1024; i > 0; i--) {
- if(typedef_table[i]) {
- mem_d(typedef_table[i]->name);
- mem_d(typedef_table[i]);
- }
- }
+ int i;
+ for(i = 1024; i > 0; i--) {
+ if(typedef_table[i]) {
+ mem_d(typedef_table[i]->name);
+ mem_d(typedef_table[i]);
+ }
+ }
}
int typedef_add(struct lex_file *file, const char *from, const char *to) {
- unsigned int hash = typedef_hash(to);
- typedef_node *find = typedef_table[hash];
-
- if (find)
- return error(file, ERROR_PARSE, "typedef for %s already exists or conflicts\n", to);
-
- /* check if the type exists first */
- if (strncmp(from, "float", sizeof("float")) == 0 ||
- strncmp(from, "vector", sizeof("vector")) == 0 ||
- strncmp(from, "string", sizeof("string")) == 0 ||
- strncmp(from, "entity", sizeof("entity")) == 0 ||
- strncmp(from, "void", sizeof("void")) == 0) {
-
- typedef_table[hash] = mem_a(sizeof(typedef_node));
- typedef_table[hash]->name = util_strdup(from);
- return -100;
- } else {
- /* search the typedefs for it (typedef-a-typedef?) */
- typedef_node *find = typedef_table[typedef_hash(from)];
- if (find) {
- typedef_table[hash] = mem_a(sizeof(typedef_node));
- typedef_table[hash]->name = util_strdup(find->name);
- return -100;
- }
- }
- return error(file, ERROR_PARSE, "cannot typedef `%s` (not a type)\n", from);
+ unsigned int hash = typedef_hash(to);
+ typedef_node *find = typedef_table[hash];
+
+ if (find)
+ return error(file, ERROR_PARSE, "typedef for %s already exists or conflicts\n", to);
+
+ /* check if the type exists first */
+ if (strncmp(from, "float", sizeof("float")) == 0 ||
+ strncmp(from, "vector", sizeof("vector")) == 0 ||
+ strncmp(from, "string", sizeof("string")) == 0 ||
+ strncmp(from, "entity", sizeof("entity")) == 0 ||
+ strncmp(from, "void", sizeof("void")) == 0) {
+
+ typedef_table[hash] = mem_a(sizeof(typedef_node));
+ typedef_table[hash]->name = util_strdup(from);
+ return -100;
+ } else {
+ /* search the typedefs for it (typedef-a-typedef?) */
+ typedef_node *find = typedef_table[typedef_hash(from)];
+ if (find) {
+ typedef_table[hash] = mem_a(sizeof(typedef_node));
+ typedef_table[hash]->name = util_strdup(find->name);
+ return -100;
+ }
+ }
+ return error(file, ERROR_PARSE, "cannot typedef `%s` (not a type)\n", from);
}
/*
* Copyright (C) 2012
- * Dale Weiler
+ * Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
#include "gmqcc.h"
struct memblock_t {
- const char *file;
- unsigned int line;
- unsigned int byte;
+ const char *file;
+ unsigned int line;
+ unsigned int byte;
};
void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
- struct memblock_t *data = malloc(sizeof(struct memblock_t) + byte);
- if (!data) return NULL;
- data->line = line;
- data->byte = byte;
- data->file = file;
-
- util_debug("MEM", "allocation: %08u (bytes) at %s:%u\n", byte, file, line);
- return (void*)((uintptr_t)data+sizeof(struct memblock_t));
+ struct memblock_t *data = malloc(sizeof(struct memblock_t) + byte);
+ if (!data) return NULL;
+ data->line = line;
+ data->byte = byte;
+ data->file = file;
+
+ util_debug("MEM", "allocation: %08u (bytes) at %s:%u\n", byte, file, line);
+ return (void*)((uintptr_t)data+sizeof(struct memblock_t));
}
void util_memory_d(void *ptrn, unsigned int line, const char *file) {
- if (!ptrn) return;
- void *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
- struct memblock_t *info = (struct memblock_t*)data;
-
- util_debug("MEM", "released: %08u (bytes) at %s:%u\n", info->byte, file, line);
- free(data);
+ if (!ptrn) return;
+ void *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
+ struct memblock_t *info = (struct memblock_t*)data;
+
+ util_debug("MEM", "released: %08u (bytes) at %s:%u\n", info->byte, file, line);
+ free(data);
}
#ifndef mem_d
* to track all memory (without replacing malloc).
*/
char *util_strdup(const char *s) {
- size_t len;
- char *ptr;
-
- if (!s)
- return NULL;
-
- len = strlen(s);
- ptr = mem_a (len+1);
-
- if (ptr && len) {
- memcpy(ptr, s, len);
- ptr[len] = '\0';
- }
-
- return ptr;
+ size_t len;
+ char *ptr;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s);
+ ptr = mem_a (len+1);
+
+ if (ptr && len) {
+ memcpy(ptr, s, len);
+ ptr[len] = '\0';
+ }
+
+ return ptr;
}
/*
* char array that is later freed (it uses pointer arith)
*/
char *util_strrq(char *s) {
- char *dst = s;
- char *src = s;
- char chr;
- while ((chr = *src++) != '\0') {
- if (chr == '\\') {
- *dst++ = chr;
- if ((chr = *src++) == '\0')
- break;
- *dst++ = chr;
- } else if (chr != '"')
- *dst++ = chr;
- }
- *dst = '\0';
- return dst;
+ char *dst = s;
+ char *src = s;
+ char chr;
+ while ((chr = *src++) != '\0') {
+ if (chr == '\\') {
+ *dst++ = chr;
+ if ((chr = *src++) == '\0')
+ break;
+ *dst++ = chr;
+ } else if (chr != '"')
+ *dst++ = chr;
+ }
+ *dst = '\0';
+ return dst;
}
/*
* access.
*/
char *util_strrnl(char *src) {
- if (!src) return NULL;
- char *cpy = src;
- while (*cpy && *cpy != '\n')
- cpy++;
-
- *cpy = '\0';
- return src;
+ if (!src) return NULL;
+ char *cpy = src;
+ while (*cpy && *cpy != '\n')
+ cpy++;
+
+ *cpy = '\0';
+ return src;
}
void util_debug(const char *area, const char *ms, ...) {
- va_list va;
- va_start(va, ms);
- fprintf (stdout, "DEBUG: ");
- fputc ('[', stdout);
- fprintf (stdout, area);
- fputs ("] ", stdout);
- vfprintf(stdout, ms, va);
- va_end (va);
+ va_list va;
+ va_start(va, ms);
+ fprintf (stdout, "DEBUG: ");
+ fputc ('[', stdout);
+ fprintf (stdout, area);
+ fputs ("] ", stdout);
+ vfprintf(stdout, ms, va);
+ va_end (va);
}
/*
* assmed all. This works the same as getline().
*/
int util_getline(char **lineptr, size_t *n, FILE *stream) {
- int chr;
- int ret;
- char *pos;
+ int chr;
+ int ret;
+ char *pos;
- if (!lineptr || !n || !stream)
- return -1;
- if (!*lineptr) {
- if (!(*lineptr = mem_a((*n = 64))))
- return -1;
- }
+ if (!lineptr || !n || !stream)
+ return -1;
+ if (!*lineptr) {
+ if (!(*lineptr = mem_a((*n = 64))))
+ return -1;
+ }
- chr = *n;
- pos = *lineptr;
+ chr = *n;
+ pos = *lineptr;
- for (;;) {
- int c = getc(stream);
-
- if (chr < 2) {
- char *tmp = mem_a((*n+=(*n>16)?*n:64));
- if (!tmp)
- return -1;
-
- chr = *n + *lineptr - pos;
- strcpy(tmp,*lineptr);
-
- if (!(*lineptr = tmp))
- return -1;
-
- pos = *n - chr + *lineptr;
- }
+ for (;;) {
+ int c = getc(stream);
+
+ if (chr < 2) {
+ char *tmp = mem_a((*n+=(*n>16)?*n:64));
+ if (!tmp)
+ return -1;
+
+ chr = *n + *lineptr - pos;
+ strcpy(tmp,*lineptr);
+
+ if (!(*lineptr = tmp))
+ return -1;
+
+ pos = *n - chr + *lineptr;
+ }
- if (ferror(stream))
- return -1;
- if (c == EOF) {
- if (pos == *lineptr)
- return -1;
- else
- break;
- }
+ if (ferror(stream))
+ return -1;
+ if (c == EOF) {
+ if (pos == *lineptr)
+ return -1;
+ else
+ break;
+ }
- *pos++ = c;
- chr--;
- if (c == '\n')
- break;
- }
- *pos = '\0';
- return (ret = pos - *lineptr);
+ *pos++ = c;
+ chr--;
+ if (c == '\n')
+ break;
+ }
+ *pos = '\0';
+ return (ret = pos - *lineptr);
}