From 639fc8a32b35174fc4c2347fd38f76147093d6f4 Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Tue, 10 Apr 2012 05:02:58 -0400 Subject: [PATCH] Cleanups --- Makefile | 2 +- README | 6 +- alloc.c | 54 ------------- gmqcc.h | 224 ++++++++++++++++++++++++++---------------------------- lex.c | 2 +- parse.c | 43 +++++------ typedef.c | 3 +- 7 files changed, 134 insertions(+), 200 deletions(-) delete mode 100644 alloc.c diff --git a/Makefile b/Makefile index b1b4863..da9d0e6 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ OBJ = main.o \ error.o \ parse.o \ typedef.o \ - alloc.o + util.o %.o: %.c $(CC) -c $< -o $@ $(CFLAGS) diff --git a/README b/README index 79b57cf..48955ae 100644 --- a/README +++ b/README @@ -30,9 +30,9 @@ typedef.c complicated than it sounds. This handles all typedefs, and even recrusive typedefs. -alloc.c - This is just an allocator for the compiler, it's used for debugging reasons - only. +util.c + These are utilities for the compiler, some things in here include a + allocator used for debugging, and some string functions. README This is the file you're currently reading diff --git a/alloc.c b/alloc.c deleted file mode 100644 index ca6504a..0000000 --- a/alloc.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 - * 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 - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include "gmqcc.h" - -/* - * The compiler has it's own memory tracker / allocator for debugging - * reasons. It will help find things like buggy CSE or OOMs (if this - * compiler ever grows to that point.) - */ -struct memblock_t { - const char *file; - unsigned int line; - unsigned int byte; -}; - -void *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; - printf("[MEM] allocation: %08u (bytes) at %s:%u\n", byte, file, line); - return (void*)((uintptr_t)data+sizeof(struct memblock_t)); -} - -void 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; - printf("[MEM] released: %08u (bytes) at %s:%u\n", info->byte, file, line); - free(data); -} diff --git a/gmqcc.h b/gmqcc.h index 8219d9d..68c7367 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -24,7 +24,109 @@ #define GMQCC_HDR #include -/* The types supported by the language */ +//=================================================================== +//============================ lex.c ================================ +//=================================================================== +struct lex_file { + FILE *file; + char peek [5]; + char lastok[8192]; + + int last; + int current; + int length; + int size; +}; + +/* + * It's important that this table never exceed 32 keywords, the ascii + * table starts at 33 (and we don't want conflicts) + */ +#define TOKEN_DO 0 +#define TOKEN_ELSE 1 +#define TOKEN_IF 2 +#define TOKEN_WHILE 3 +#define TOKEN_BREAK 4 +#define TOKEN_CONTINUE 5 +#define TOKEN_RETURN 6 +#define TOKEN_GOTO 7 +#define TOKEN_FOR 8 // extension +#define TOKEN_TYPEDEF 9 // extension + +// ensure the token types are out of the +// bounds of anyothers that may conflict. +#define TOKEN_FLOAT 110 +#define TOKEN_VECTOR 111 +#define TOKEN_STRING 112 +#define TOKEN_ENTITY 113 +#define TOKEN_VOID 114 + +/* + * Lexer state constants, these are numbers for where exactly in + * the lexing the lexer is at. Or where it decided to stop if a lexer + * error occurs. These numbers must be > where the ascii-table ends + * and > the last type token which is TOKEN_VOID + */ +#define LEX_COMMENT 1128 +#define LEX_CHRLIT 1129 +#define LEX_STRLIT 1130 +#define LEX_IDENT 1131 + +int lex_token(struct lex_file *); +void lex_reset(struct lex_file *); +void lex_close(struct lex_file *); +struct lex_file *lex_open (FILE *); + +//=================================================================== +//========================== error.c ================================ +//=================================================================== +#define ERROR_LEX (SHRT_MAX+0) +#define ERROR_PARSE (SHRT_MAX+1) +#define ERROR_INTERNAL (SHRT_MAX+2) +#define ERROR_COMPILER (SHRT_MAX+3) +#define ERROR_PREPRO (SHRT_MAX+4) +int error(int, const char *, ...); + +//=================================================================== +//========================== parse.c ================================ +//=================================================================== +int parse_tree(struct lex_file *); +struct parsenode { + struct parsenode *next; + int type; /* some token */ +}; + +//=================================================================== +//========================== typedef.c ============================== +//=================================================================== +typedef struct typedef_node_t { + char *name; +} typedef_node; + +void typedef_init(); +void typedef_clear(); +typedef_node *typedef_find(const char *); +int typedef_add (const char *, const char *); + + +//=================================================================== +//=========================== util.c ================================ +//=================================================================== +void *util_memory_a(unsigned int, unsigned int, const char *); +void util_memory_d(void *, unsigned int, const char *); +char *util_strdup (const char *); + +#ifdef NOTRACK +# 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__) +#endif + +//=================================================================== +//=========================== code.c ================================ +//=================================================================== #define TYPE_VOID 0 #define TYPE_STRING 1 #define TYPE_FLOAT 2 @@ -34,33 +136,17 @@ #define TYPE_FUNCTION 6 #define TYPE_POINTER 7 -/* - * there are 3 accessible memory zones - - * globals - * array of 32bit ints/floats, mixed, LE, - * entities - * structure is up to the engine but the fields are a linear array - * of mixed ints/floats, there are globals referring to the offsets - * of these in the entity struct so there are ADDRESS and STOREP and - * LOAD instructions that use globals containing field offsets. - * strings - * a static array in the progs.dat, with file parsing creating - * additional constants, and some engine fields are mapped by - * address as well to unique string offsets - */ - /* * Instructions * These are the external instructions supported by the interperter - * this is what things compile to (from the C code). This is not internal - * instructions for support like int, and such (which are translated) + * this is what things compile to (from the C code). */ #define INSTR_DONE 0 // math -#define INSTR_MUL_F 1 /* multiplication float */ -#define INSTR_MUL_V 2 /* multiplication vector */ -#define INSTR_MUL_FV 3 /* multiplication float->vector */ -#define INSTR_MUL_VF 4 /* multiplication vector->float */ +#define INSTR_MUL_F 1 +#define INSTR_MUL_V 2 +#define INSTR_MUL_FV 3 +#define INSTR_MUL_VF 4 #define INSTR_DIV_F 5 #define INSTR_ADD_F 6 #define INSTR_ADD_V 7 @@ -120,98 +206,4 @@ #define INSTR_OR 57 #define INSTR_BITAND 59 #define INSTR_BITOR 60 - -/* - * This is the smallest lexer I've ever wrote: and I must say, it's quite - * more nicer than those large bulky complex parsers that most people write - * which has some sort of a complex state. - */ -struct lex_file { - /* - * This is a simple state for lexing, no need to be complex for qc - * code. It's trivial stuff. - */ - FILE *file; - char peek[5]; /* extend for depthier peeks */ - int last; - int current; - int length; - int size; - char lastok[8192]; /* No token shall ever be bigger than this! */ -}; - -/* - * It's important that this table never exceed 32 keywords, the ascii - * table starts at 33 (and we don't want conflicts) - */ -#define TOKEN_DO 0 -#define TOKEN_ELSE 1 -#define TOKEN_IF 2 -#define TOKEN_WHILE 3 -#define TOKEN_BREAK 4 -#define TOKEN_CONTINUE 5 -#define TOKEN_RETURN 6 -#define TOKEN_GOTO 7 -#define TOKEN_FOR 8 // extension -#define TOKEN_TYPEDEF 9 // extension - -// ensure the token types are out of the -// bounds of anyothers that may conflict. -#define TOKEN_FLOAT 110 -#define TOKEN_VECTOR 111 -#define TOKEN_STRING 112 -#define TOKEN_ENTITY 113 -#define TOKEN_VOID 114 - -/* - * Lexer state constants, these are numbers for where exactly in - * the lexing the lexer is at. Or where it decided to stop if a lexer - * error occurs. These numbers must be > where the ascii-table ends - * and > the last type token which is TOKEN_VOID - */ -#define LEX_COMMENT 1128 -#define LEX_CHRLIT 1129 -#define LEX_STRLIT 1130 -#define LEX_IDENT 1131 - -int lex_token(struct lex_file *); -void lex_reset(struct lex_file *); -void lex_close(struct lex_file *); -struct lex_file *lex_open (FILE *); - -/* errors */ -#define ERROR_LEX (SHRT_MAX+0) -#define ERROR_PARSE (SHRT_MAX+1) -#define ERROR_INTERNAL (SHRT_MAX+2) -#define ERROR_COMPILER (SHRT_MAX+3) -#define ERROR_PREPRO (SHRT_MAX+4) -int error(int, const char *, ...); - -/* parse.c */ -int parse_tree(struct lex_file *); -struct parsenode { - struct parsenode *next; - int type; /* some token */ -}; - -/* typedef.c */ -typedef struct typedef_node_t { - char *name; /* name of actual type */ -} typedef_node; - -void typedef_init(); -void typedef_clear(); -typedef_node *typedef_find(const char *); -int typedef_add (const char *, const char *); - -/* alloc.c */ -void *memory_a(unsigned int, unsigned int, const char *); -void memory_d(void *, unsigned int, const char *); -#ifdef NOTRACK -# define mem_a(x) malloc(x) -# define mem_d(x) free (x) -#else -# define mem_a(x) memory_a((x), __LINE__, __FILE__) -# define mem_d(x) memory_d((x), __LINE__, __FILE__) -#endif #endif diff --git a/lex.c b/lex.c index ae73dc1..3be0045 100644 --- a/lex.c +++ b/lex.c @@ -293,7 +293,7 @@ int lex_token(struct lex_file *file) { if (!strncmp(X, "entity", sizeof("entity"))) \ return TOKEN_ENTITY; \ if (!strncmp(X, "void" , sizeof("void"))) \ - return TOKEN_VOID; \ + return TOKEN_VOID; \ } while(0) TEST_TYPE(file->lastok); diff --git a/parse.c b/parse.c index 0e1c6a5..72d2fd2 100644 --- a/parse.c +++ b/parse.c @@ -83,7 +83,7 @@ } while (0) /* - * These are all the punctuation handled in the parser, these don't + * This is all the punctuation handled in the parser, these don't * need tokens, they're already tokens. */ #if 0 @@ -158,13 +158,13 @@ void parse_debug(struct parsenode *tree) { * and everything will fail. */ #define PARSE_PERFORM(X,C) { \ - token = lex_token(file); \ - { C } \ - while (token != '\n') { \ - token = lex_token(file); \ - } \ - PARSE_TREE_ADD(X); \ - break; \ + token = lex_token(file); \ + { C } \ + while (token != '\n') { \ + token = lex_token(file); \ + } \ + PARSE_TREE_ADD(X); \ + break; \ } void parse_clear(struct parsenode *tree) { @@ -230,17 +230,17 @@ int parse_tree(struct lex_file *file) { * the tokens accordingly here. */ case TOKEN_TYPEDEF: { - char *f = NULL; - char *t = NULL; + char *f,*t; + token = lex_token(file); - token = lex_token(file); f = strdup(file->lastok); + token = lex_token(file); f = util_strdup(file->lastok); token = lex_token(file); - token = lex_token(file); t = strdup(file->lastok); + token = lex_token(file); t = util_strdup(file->lastok); typedef_add(f, t); - free(f); - free(t); + mem_d(f); + mem_d(t); while (token != '\n') token = lex_token(file); @@ -254,8 +254,6 @@ int parse_tree(struct lex_file *file) { case TOKEN_RETURN: PARSE_TREE_ADD(PARSE_TYPE_RETURN); break; - //PARSE_PERFORM(PARSE_TYPE_RETURN, {}); - case TOKEN_DO: PARSE_PERFORM(PARSE_TYPE_DO, {}); case TOKEN_WHILE: PARSE_PERFORM(PARSE_TYPE_WHILE, {}); @@ -293,7 +291,6 @@ int parse_tree(struct lex_file *file) { token = lex_token(file); PARSE_TREE_ADD(PARSE_TYPE_DOT); break; - case '(': token = lex_token(file); PARSE_TREE_ADD(PARSE_TYPE_LPARTH); @@ -303,7 +300,7 @@ int parse_tree(struct lex_file *file) { PARSE_TREE_ADD(PARSE_TYPE_RPARTH); break; - case '&': /* & */ + case '&': /* & */ token = lex_token(file); if (token == '&') { /* && */ token = lex_token(file); @@ -312,7 +309,7 @@ int parse_tree(struct lex_file *file) { } PARSE_TREE_ADD(PARSE_TYPE_BAND); break; - case '|': /* | */ + case '|': /* | */ token = lex_token(file); if (token == '|') { /* || */ token = lex_token(file); @@ -321,7 +318,7 @@ int parse_tree(struct lex_file *file) { } PARSE_TREE_ADD(PARSE_TYPE_BOR); break; - case '!': + case '!': /* ! */ token = lex_token(file); if (token == '=') { /* != */ token = lex_token(file); @@ -330,7 +327,7 @@ int parse_tree(struct lex_file *file) { } PARSE_TREE_ADD(PARSE_TYPE_LNOT); break; - case '<': /* < */ + case '<': /* < */ token = lex_token(file); if (token == '=') { /* <= */ token = lex_token(file); @@ -339,7 +336,7 @@ int parse_tree(struct lex_file *file) { } PARSE_TREE_ADD(PARSE_TYPE_LT); break; - case '>': /* > */ + case '>': /* > */ token = lex_token(file); if (token == '=') { /* >= */ token = lex_token(file); @@ -348,7 +345,7 @@ int parse_tree(struct lex_file *file) { } PARSE_TREE_ADD(PARSE_TYPE_GT); break; - case '=': + case '=': /* = */ token = lex_token(file); if (token == '=') { /* == */ token = lex_token(file); diff --git a/typedef.c b/typedef.c index 4ee7348..e84300a 100644 --- a/typedef.c +++ b/typedef.c @@ -25,7 +25,6 @@ #include #include "gmqcc.h" static typedef_node *typedef_table[1024]; - void typedef_init() { int i; for(i = 0; i < sizeof(typedef_table)/sizeof(*typedef_table); i++) @@ -66,7 +65,7 @@ int typedef_add(const char *from, const char *to) { unsigned int hash = typedef_hash(to); typedef_node *find = typedef_table[hash]; if (find) - return error(ERROR_PARSE, "typedef for %s already exists\n", to); + return error(ERROR_PARSE, "typedef for %s already exists or conflicts\n", to); /* check if the type exists first */ if (strncmp(from, "float", sizeof("float")) == 0 || -- 2.39.2