From: Dale Weiler Date: Tue, 17 Apr 2012 20:24:22 +0000 (-0400) Subject: tabulators->four spaces X-Git-Tag: 0.1-rc1~652 X-Git-Url: http://de.git.xonotic.org/?a=commitdiff_plain;h=477e80f1fb79c5d74a97ad5ed756f03cc21445f4;p=xonotic%2Fgmqcc.git tabulators->four spaces --- diff --git a/assembler.c b/assembler.c index 14255ff..9111e2b 100644 --- a/assembler.c +++ b/assembler.c @@ -1,6 +1,6 @@ /* * 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 @@ -27,76 +27,76 @@ * 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 } }; /* @@ -104,23 +104,23 @@ static const struct { * 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' @@ -130,199 +130,199 @@ static char *const asm_getline(size_t *byte, FILE *fp) { } 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 ++; + } } diff --git a/code.c b/code.c index f6b64ad..e391292 100644 --- a/code.c +++ b/code.c @@ -1,6 +1,6 @@ /* * 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 @@ -23,20 +23,20 @@ #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; /* @@ -81,91 +81,91 @@ VECTOR_MAKE(int, code_globals ); 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\ @@ -175,22 +175,22 @@ void code_write() { 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); } diff --git a/error.c b/error.c index c0df207..2f96caf 100644 --- a/error.c +++ b/error.c @@ -1,6 +1,6 @@ /* * 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 @@ -29,62 +29,62 @@ * 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; } diff --git a/gmqcc.h b/gmqcc.h index d9e3a9c..14a4022 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -1,6 +1,6 @@ /* * 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 @@ -33,30 +33,30 @@ * 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]; @@ -73,16 +73,16 @@ typedef char uintptr_size_is_correct[sizeof(uintptr_t)== sizeof(int*)?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? */ }; /* @@ -144,7 +144,7 @@ int parse_gen(struct lex_file *); //========================== typedef.c ============================== //=================================================================== typedef struct typedef_node_t { - char *name; + char *name; } typedef_node; void typedef_init(); @@ -165,11 +165,11 @@ void util_debug (const char *, const char *, ...); 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) \ @@ -211,75 +211,75 @@ int util_getline (char **, size_t *, FILE *); * 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; /* @@ -288,72 +288,72 @@ typedef struct { * 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 }; /* diff --git a/lex.c b/lex.c index 5673701..48f58d8 100644 --- a/lex.c +++ b/lex.c @@ -1,6 +1,6 @@ /* * 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 @@ -27,43 +27,43 @@ * 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; } /* @@ -72,15 +72,15 @@ static inline void lex_clear(struct lex_file *file) { * 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 ++; } /* @@ -88,249 +88,249 @@ static void lex_unget(int ch, struct lex_file *file) { * 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)); } /* @@ -339,17 +339,17 @@ void lex_reset(struct lex_file *file) { * 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); } diff --git a/main.c b/main.c index d087c4e..b8117f0 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ /* * 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 @@ -22,16 +22,16 @@ */ #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; } diff --git a/parse.c b/parse.c index e763e56..6423f5d 100644 --- a/parse.c +++ b/parse.c @@ -1,6 +1,6 @@ /* * 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 @@ -24,272 +24,272 @@ /* 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; +} diff --git a/typedef.c b/typedef.c index 0118861..0259f35 100644 --- a/typedef.c +++ b/typedef.c @@ -1,6 +1,6 @@ /* * 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 @@ -24,69 +24,69 @@ 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); } diff --git a/util.c b/util.c index 44b1108..e431fb2 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* * 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 @@ -25,29 +25,29 @@ #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 @@ -62,21 +62,21 @@ void util_memory_d(void *ptrn, unsigned int line, const char *file) { * 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; } /* @@ -85,20 +85,20 @@ char *util_strdup(const char *s) { * 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; } /* @@ -107,24 +107,24 @@ char *util_strrq(char *s) { * 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); } /* @@ -132,51 +132,51 @@ void util_debug(const char *area, const char *ms, ...) { * 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); }