]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
More library stuff (the codebase is a mess I know, but we're getting there)
authorDale Weiler <killfieldengine@gmail.com>
Sun, 28 Apr 2013 18:42:21 +0000 (18:42 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Sun, 28 Apr 2013 18:42:21 +0000 (18:42 +0000)
base.h
code.c
ftepp.c
gmqcc.h
ir.c
ir.h
main.c
parser.c
util.c

diff --git a/base.h b/base.h
index 88f659135dfe1a4f718753184d5ab2326248b672..66cb15ccb962d1bddc09027db19d89c1a2507f0f 100644 (file)
--- a/base.h
+++ b/base.h
@@ -327,6 +327,8 @@ char       *util_strcat   (char *dest, const char *src);
 char       *util_strncpy  (char *dest, const char *src, size_t num);
 const char *util_strerror (int num);
 
+const char *gmqcc_global_error(const char *text);
+
 
 /*
  * A flexible vector implementation: all vector pointers contain some
@@ -697,7 +699,7 @@ enum {
 typedef float   qcfloat;
 typedef int32_t qcint;
 
-typedef struct {
+typedef struct gmqcc_code_s {
     prog_section_statement *statements;
     int                    *linenums;
     prog_section_def       *defs;
@@ -709,7 +711,7 @@ typedef struct {
     uint32_t                entfields;
     ht                      string_cache;
     qcint                   string_cached_empty;
-} code_t;
+} gmqcc_code_t;
 
 /*
  * code_write          -- writes out the compiled file
@@ -719,12 +721,12 @@ typedef struct {
  * code_push_statement -- keeps statements and linenumbers together
  * code_pop_statement  -- keeps statements and linenumbers together 
  */
-bool      code_write         (code_t *, const char *filename, const char *lno);
-code_t   *code_init          (void);
-uint32_t  code_genstring     (code_t *, const char *string);
-qcint     code_alloc_field   (code_t *, size_t qcsize);
-void      code_push_statement(code_t *, prog_section_statement *stmt, int linenum);
-void      code_pop_statement (code_t *);
+bool           code_write         (gmqcc_code_t *, const char *filename, const char *lno);
+gmqcc_code_t  *code_init          (void);
+uint32_t       code_genstring     (gmqcc_code_t *, const char *string);
+qcint          code_alloc_field   (gmqcc_code_t *, size_t qcsize);
+void           code_push_statement(gmqcc_code_t *, prog_section_statement *stmt, int linenum);
+void           code_pop_statement (gmqcc_code_t *);
 
 /*
  * A shallow copy of a lex_file to remember where which ast node
diff --git a/code.c b/code.c
index 4e404e991da55607da0d6e68dc1bc1eacad0dddc..24a53d592616bdba1bc3fbdbe94679826015e5cc 100644 (file)
--- a/code.c
+++ b/code.c
 #define QCINT_TO_HASH_ENTRY(q) ((void*)(uintptr_t)(q))
 #define HASH_ENTRY_TO_QCINT(h) ((qcint)(uintptr_t)(h))
 
-void code_push_statement(code_t *code, prog_section_statement *stmt, int linenum)
+void code_push_statement(gmqcc_code_t *code, prog_section_statement *stmt, int linenum)
 {
     vec_push(code->statements, *stmt);
     vec_push(code->linenums,   linenum);
 }
 
-void code_pop_statement(code_t *code)
+void code_pop_statement(gmqcc_code_t *code)
 {
     vec_pop(code->statements);
     vec_pop(code->linenums);
 }
 
-code_t *code_init() {
+gmqcc_code_t *code_init() {
     static prog_section_function  empty_function  = {0,0,0,0,0,0,0,{0,0,0,0,0,0,0,0}};
     static prog_section_statement empty_statement = {0,{0},{0},{0}};
     static prog_section_def       empty_def       = {0, 0, 0};
 
-    code_t *code       = (code_t*)mem_a(sizeof(code_t));
+    gmqcc_code_t *code       = (gmqcc_code_t*)mem_a(sizeof(gmqcc_code_t));
     int     i          = 0;
 
-    memset(code, 0, sizeof(code_t));
+    memset(code, 0, sizeof(gmqcc_code_t));
     code->entfields    = 0;
     code->string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024);
 
@@ -72,7 +72,7 @@ code_t *code_init() {
 
 void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin);
 
-uint32_t code_genstring(code_t *code, const char *str)
+uint32_t code_genstring(gmqcc_code_t *code, const char *str)
 {
     uint32_t off;
     size_t   hash;
@@ -107,14 +107,14 @@ uint32_t code_genstring(code_t *code, const char *str)
     return off;
 }
 
-qcint code_alloc_field (code_t *code, size_t qcsize)
+qcint code_alloc_field (gmqcc_code_t *code, size_t qcsize)
 {
     qcint pos = (qcint)code->entfields;
     code->entfields += qcsize;
     return pos;
 }
 
-static void code_create_header(code_t *code, prog_header *code_header) {
+static void code_create_header(gmqcc_code_t *code, prog_header *code_header) {
     code_header->statements.offset = sizeof(prog_header);
     code_header->statements.length = vec_size(code->statements);
     code_header->defs.offset       = code_header->statements.offset + (sizeof(prog_section_statement) * vec_size(code->statements));
@@ -168,7 +168,7 @@ static void code_create_header(code_t *code, prog_header *code_header) {
  * directly out to allocated memory. Which is actually very useful for the future library support
  * we're going to add.
  */   
-bool code_write_memory(code_t *code, uint8_t **datmem, size_t *sizedat, uint8_t **lnomem, size_t *sizelno) {
+bool code_write_memory(gmqcc_code_t *code, uint8_t **datmem, size_t *sizedat, uint8_t **lnomem, size_t *sizelno) {
     prog_header code_header;
     uint32_t    offset  = 0;
 
@@ -248,7 +248,7 @@ bool code_write_memory(code_t *code, uint8_t **datmem, size_t *sizedat, uint8_t
     return true;
 }
 
-bool code_write(code_t *code, const char *filename, const char *lnofile) {
+bool code_write(gmqcc_code_t *code, const char *filename, const char *lnofile) {
     prog_header  code_header;
     FILE        *fp = NULL;
 
diff --git a/ftepp.c b/ftepp.c
index cada764d984654f4484a92d67b54b647ce05610c..79906595501fdf8c6990b4354cdb7ac79f062aaf 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -1834,8 +1834,10 @@ ftepp_t *gmqcc_preprocess_create(void)
     char major[32];
 
     ftepp = ftepp_new();
-    if (!ftepp)
+    if (!ftepp) {
+        gmqcc_global_error("Failed to construct a new preprocessor context");
         return NULL;
+    }
 
     memset(minor, 0, sizeof(minor));
     memset(major, 0, sizeof(major));
diff --git a/gmqcc.h b/gmqcc.h
index 2a62778c95b26335849f1cd2b8940226d210830d..d0ee78ca70211caaf774ba523591b0c5ae3c6437 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -32,6 +32,7 @@ extern "C" {
  * that the user shouldn't have information of.
  */
 struct gmqcc_preprocess_s;
+struct gmqcc_compiler_s;
 
 /*
  * Function: gmqcc_global_setmemory
@@ -56,6 +57,19 @@ bool gmqcc_global_setmemory (
     void  (*free_impl)   (void *)
 );
 
+/*
+ * Funciton: gmqcc_global_geterror
+ *  Get a const string-literal of the last error which occured.
+ *
+ * Returns:
+ *  A string-literal describing the error which occured last.
+ *
+ * Remarks:     
+ *  This should be called to get better diagnostic when a function
+ *  doesn't return successfully.
+ */ 
+const char *gmqcc_global_geterror(void);
+
 /*
  * Function: gmqcc_preprocess_create
  *  Creates a preprocessor context
@@ -165,6 +179,86 @@ void gmqcc_preprocess_destroy(
     struct gmqcc_preprocess_s *pp
 );
 
+
+/*
+ * Enumeration: gmqcc_compiler_context_t
+ *  List of bindable contexts for a compiler context
+ *
+ *  GMQCC_CONTEXT_PREPROCESSOR - A preprocessor context
+ *  GMQCC_CONTEXT_PARSER       - A parser context
+ *  GMQCC_CONTEXT_CODE         - A code generator context 
+ */  
+typedef enum {
+    GMQCC_CONTEXT_PREPROCESSOR,
+    GMQCC_CONTEXT_PARSER,
+    GMQCC_CONTEXT_CODE
+} gmqcc_compiler_context_t;
+
+/*
+ * Macro: GMQCC_CONTEXT_CAST
+ *  A macro for casting a bindable context, used primarly for context
+ *  manipulation where the functions are abstract and require a cast.
+ *
+ * See Also:
+ *  <gmqcc_compiler_attachcontext>   
+ */   
+#define GMQCC_CONTEXT_CAST(X) ((void*)(X))
+
+/*
+ * Function: gmqcc_compiler_create
+ *  Creates a compiler which will require attachments to
+ *  function.
+ *
+ * Returns:
+ *  A new compiler context
+ *
+ * Remarks:
+ *  Inorder to use the compiler context you'll require
+ *  at minimal a code and parser context.
+ *
+ * See Also:
+ *  <gmqcc_compiler_attachcontext>
+ */
+struct gmqcc_compiler_s *gmqcc_compiler_create(void);
+
+/*
+ * Function: gmqcc_compiler_attachcontext
+ *  Used to attach a context to a compiler context.
+ *
+ * Parameters:
+ *  compiler - Compiler context
+ *  base     - Base pointer to attachment context
+ *  context  - The type of context (see <gmqcc_compiler_context_t> et. all)
+ *
+ * Returns:
+ *  true on success, false otherwise.
+ *
+ * Remarks:
+ *  A parser context is mandatory, other contexts are optional.
+ *  Contexts can be swaped around, i.e you can detach a parser context,
+ *  back it up somewhere apply a new parser context and run with that.
+ */   
+bool gmqcc_compiler_attachcontext(
+    struct gmqcc_compiler_s  *compiler,
+    void                     *base,
+    gmqcc_compiler_context_t  context
+);
+
+/*
+ * Function: gmqcc_compiler_destroy
+ *  Destroys a compiler context.
+ *
+ * Parameters:
+ *  compiler - Compiler context
+ *
+ * Remarks:
+ *  This function doesn't destory any associated contexts with
+ *  the compiler context itself.
+ */
+void gmqcc_compiler_destroy(
+    struct gmqcc_compiler_s *compiler
+);
+
 #ifdef __cplusplus
 }
 #endif /*! __cplusplus */
diff --git a/ir.c b/ir.c
index 07eb6799b8b3235d4fb76396c2e705e080805df7..0bc0001ef25f2c15bc9f6ab2fb2f9778f573facc 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -212,7 +212,7 @@ const uint16_t type_not_instr[TYPE_COUNT] = {
 
 /* protos */
 static ir_value* ir_gen_extparam_proto(ir_builder *ir);
-static void      ir_gen_extparam      (code_t *, ir_builder *ir);
+static void      ir_gen_extparam      (gmqcc_code_t *, ir_builder *ir);
 
 /* error functions */
 
@@ -2618,9 +2618,9 @@ bool ir_function_calculate_liferanges(ir_function *self)
  *
  * Breaking conventions is annoying...
  */
-static bool ir_builder_gen_global(code_t *, ir_builder *self, ir_value *global, bool islocal);
+static bool ir_builder_gen_global(gmqcc_code_t *, ir_builder *self, ir_value *global, bool islocal);
 
-static bool gen_global_field(code_t *code, ir_value *global)
+static bool gen_global_field(gmqcc_code_t *code, ir_value *global)
 {
     if (global->hasvalue)
     {
@@ -2652,7 +2652,7 @@ static bool gen_global_field(code_t *code, ir_value *global)
     return true;
 }
 
-static bool gen_global_pointer(code_t *code, ir_value *global)
+static bool gen_global_pointer(gmqcc_code_t *code, ir_value *global)
 {
     if (global->hasvalue)
     {
@@ -2691,7 +2691,7 @@ static bool gen_global_pointer(code_t *code, ir_value *global)
     return true;
 }
 
-static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *block)
+static bool gen_blocks_recursive(gmqcc_code_t *code, ir_function *func, ir_block *block)
 {
     prog_section_statement stmt;
     ir_instr *instr;
@@ -2951,7 +2951,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
     return true;
 }
 
-static bool gen_function_code(code_t *code, ir_function *self)
+static bool gen_function_code(gmqcc_code_t *code, ir_function *self)
 {
     ir_block *block;
     prog_section_statement stmt, *retst;
@@ -2992,7 +2992,7 @@ static bool gen_function_code(code_t *code, ir_function *self)
     return true;
 }
 
-static qcint ir_builder_filestring(code_t *code, ir_builder *ir, const char *filename)
+static qcint ir_builder_filestring(gmqcc_code_t *code, ir_builder *ir, const char *filename)
 {
     /* NOTE: filename pointers are copied, we never strdup them,
      * thus we can use pointer-comparison to find the string.
@@ -3011,7 +3011,7 @@ static qcint ir_builder_filestring(code_t *code, ir_builder *ir, const char *fil
     return str;
 }
 
-static bool gen_global_function(code_t *code, ir_builder *ir, ir_value *global)
+static bool gen_global_function(gmqcc_code_t *code, ir_builder *ir, ir_value *global)
 {
     prog_section_function fun;
     ir_function          *irfun;
@@ -3066,7 +3066,7 @@ static ir_value* ir_gen_extparam_proto(ir_builder *ir)
     return global;
 }
 
-static void ir_gen_extparam(code_t *code, ir_builder *ir)
+static void ir_gen_extparam(gmqcc_code_t *code, ir_builder *ir)
 {
     prog_section_def def;
     ir_value        *global;
@@ -3091,7 +3091,7 @@ static void ir_gen_extparam(code_t *code, ir_builder *ir)
     vec_push(ir->extparams, global);
 }
 
-static bool gen_function_extparam_copy(code_t *code, ir_function *self)
+static bool gen_function_extparam_copy(gmqcc_code_t *code, ir_function *self)
 {
     size_t i, ext, numparams;
 
@@ -3126,7 +3126,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self)
     return true;
 }
 
-static bool gen_function_varargs_copy(code_t *code, ir_function *self)
+static bool gen_function_varargs_copy(gmqcc_code_t *code, ir_function *self)
 {
     size_t i, ext, numparams, maxparams;
 
@@ -3162,7 +3162,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
     return true;
 }
 
-static bool gen_function_locals(code_t *code, ir_builder *ir, ir_value *global)
+static bool gen_function_locals(gmqcc_code_t *code, ir_builder *ir, ir_value *global)
 {
     prog_section_function *def;
     ir_function           *irfun;
@@ -3211,7 +3211,7 @@ static bool gen_function_locals(code_t *code, ir_builder *ir, ir_value *global)
     return true;
 }
 
-static bool gen_global_function_code(code_t *code, ir_builder *ir, ir_value *global)
+static bool gen_global_function_code(gmqcc_code_t *code, ir_builder *ir, ir_value *global)
 {
     prog_section_function *fundef;
     ir_function           *irfun;
@@ -3257,7 +3257,7 @@ static bool gen_global_function_code(code_t *code, ir_builder *ir, ir_value *glo
     return true;
 }
 
-static void gen_vector_defs(code_t *code, prog_section_def def, const char *name)
+static void gen_vector_defs(gmqcc_code_t *code, prog_section_def def, const char *name)
 {
     char  *component;
     size_t len, i;
@@ -3287,7 +3287,7 @@ static void gen_vector_defs(code_t *code, prog_section_def def, const char *name
     mem_d(component);
 }
 
-static void gen_vector_fields(code_t *code, prog_section_field fld, const char *name)
+static void gen_vector_fields(gmqcc_code_t *code, prog_section_field fld, const char *name)
 {
     char  *component;
     size_t len, i;
@@ -3317,7 +3317,7 @@ static void gen_vector_fields(code_t *code, prog_section_field fld, const char *
     mem_d(component);
 }
 
-static bool ir_builder_gen_global(code_t *code, ir_builder *self, ir_value *global, bool islocal)
+static bool ir_builder_gen_global(gmqcc_code_t *code, ir_builder *self, ir_value *global, bool islocal)
 {
     size_t           i;
     int32_t         *iptr;
@@ -3488,12 +3488,12 @@ static bool ir_builder_gen_global(code_t *code, ir_builder *self, ir_value *glob
     }
 }
 
-static GMQCC_INLINE void ir_builder_prepare_field(code_t *code, ir_value *field)
+static GMQCC_INLINE void ir_builder_prepare_field(gmqcc_code_t *code, ir_value *field)
 {
     field->code.fieldaddr = code_alloc_field(code, type_sizeof_[field->fieldtype]);
 }
 
-static bool ir_builder_gen_field(code_t *code, ir_builder *self, ir_value *field)
+static bool ir_builder_gen_field(gmqcc_code_t *code, ir_builder *self, ir_value *field)
 {
     prog_section_def def;
     prog_section_field fld;
@@ -3563,7 +3563,7 @@ static bool ir_builder_gen_field(code_t *code, ir_builder *self, ir_value *field
     return field->code.globaladdr >= 0;
 }
 
-bool ir_builder_generate(code_t *code, ir_builder *self, const char *filename)
+bool ir_builder_generate(gmqcc_code_t *code, ir_builder *self, const char *filename)
 {
     prog_section_statement stmt;
     size_t i;
diff --git a/ir.h b/ir.h
index 85d759fe7e5cc6841ac7c276deb94d4657a336ce..89eea914b425126f067aa424e1daf60685bdf380 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -349,7 +349,7 @@ ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
 
 ir_value* ir_builder_get_va_count(ir_builder*);
 
-bool ir_builder_generate(code_t *, ir_builder *self, const char *filename);
+bool ir_builder_generate(gmqcc_code_t *, ir_builder *self, const char *filename);
 
 void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));
 
diff --git a/main.c b/main.c
index 9ea723a1c7d9f0997705f978603462d6d5449ae3..00f7236aad1acbbb308e9305f0ce6e679f166b7c 100644 (file)
--- a/main.c
+++ b/main.c
@@ -549,9 +549,13 @@ int main(int argc, char **argv) {
     bool            operators_free   = false;
     bool            progs_src        = false;
     FILE            *outfile         = NULL;
-    struct parser_s *parser          = NULL;
 
-    struct gmqcc_preprocess_s  *ftepp           = NULL;
+    struct parser_s            *parser   = NULL;
+    struct gmqcc_preprocess_s  *ftepp    = NULL;
+    struct gmqcc_code_s        *code     = code_init();
+    struct gmqcc_compiler_s    *compiler = gmqcc_compiler_create();
+
+    gmqcc_compiler_attachcontext(compiler, GMQCC_CONTEXT_CAST(code), GMQCC_CONTEXT_CODE);
 
     app_name = argv[0];
     con_init ();
@@ -560,6 +564,7 @@ int main(int argc, char **argv) {
     util_seed(time(0));
 
     if (!options_parse(argc, argv)) {
+        gmqcc_compiler_destroy(compiler);
         return usage();
     }
 
@@ -631,6 +636,7 @@ int main(int argc, char **argv) {
             retval = 1;
             goto cleanup;
         }
+        gmqcc_compiler_attachcontext(compiler, GMQCC_CONTEXT_CAST(parser), GMQCC_CONTEXT_PARSER);
     }
 
     if (OPTS_OPTION_BOOL(OPTION_PP_ONLY) || OPTS_FLAG(FTEPP)) {
@@ -639,6 +645,7 @@ int main(int argc, char **argv) {
             retval = 1;
             goto cleanup;
         }
+        gmqcc_compiler_attachcontext(compiler, GMQCC_CONTEXT_CAST(ftepp), GMQCC_CONTEXT_PREPROCESSOR);
     }
 
     /* add macros */
index 3bbe68bfbf33d794ddc4eaec81517212598b5b51..61884ac63d3e34cf1ee6b5ab3544b40b2b352bdc 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -28,6 +28,7 @@
 #include "base.h"
 #include "lexer.h"
 #include "ast.h"
+#include "gmqcc.h"
 
 /* beginning of locals */
 #define PARSER_HT_LOCALS  2
 
 typedef struct parser_s {
     lex_file *lex;
-    int      tok;
+    int       tok;
 
     ast_expression **globals;
     ast_expression **fields;
-    ast_function **functions;
-    ast_value    **imm_float;
-    ast_value    **imm_string;
-    ast_value    **imm_vector;
-    size_t         translated;
+    ast_function   **functions;
+    ast_value      **imm_float;
+    ast_value      **imm_string;
+    ast_value      **imm_vector;
+    size_t           translated;
 
     ht ht_imm_string;
 
@@ -104,17 +105,77 @@ typedef struct parser_s {
     /* collected information */
     size_t     max_param_count;
 
-    /* code generator */
-    code_t     *code;
+    gmqcc_code_t *code;
 } parser_t;
 
+/* WORK IN PROGRESS */
+typedef struct gmqcc_compiler_s {
+    struct parser_s           *ctx_parser;
+    struct gmqcc_preprocess_s *ctx_preprocess;
+    struct gmqcc_code_s       *ctx_code;
+} gmqcc_compiler_t;
+
+gmqcc_compiler_t *gmqcc_compiler_create(void) {
+    gmqcc_compiler_t *compiler = (gmqcc_compiler_t*)mem_a(sizeof(*compiler));
+    memset(compiler, 0, sizeof(*compiler));
+    return compiler;
+}
+
+void gmqcc_compiler_destroy(gmqcc_compiler_t *compiler) {
+    /* Doen't free members yet */
+    mem_d(compiler);
+}
+
+bool gmqcc_compiler_attachcontext(gmqcc_compiler_t *c, void *base, gmqcc_compiler_context_t type) {
+    if (!base) {
+        gmqcc_global_error("NULL attachment supplied for gmqcc_compiler_attachcontext");
+        return false;
+    }
+
+    switch (type) {
+        case GMQCC_CONTEXT_CODE:
+            c->ctx_code = (struct gmqcc_code_s*)base;
+            /*
+             * Update the parsers code context copy
+             * if the code context has changed.
+             */  
+            if (c->ctx_parser)
+                c->ctx_parser->code = c->ctx_code;
+            break;
+
+        case GMQCC_CONTEXT_PARSER:
+            /* Free memory */
+            if (c->ctx_parser)
+                parser_cleanup(c->ctx_parser);
+            if (!c->ctx_code) {
+                gmqcc_global_error("A code context must be created before a parser context");
+                return false;
+            }
+
+            c->ctx_parser       = (struct parser_s*)base;
+            c->ctx_parser->code = c->ctx_code; 
+            break;
+
+        case GMQCC_CONTEXT_PREPROCESSOR:
+            if (c->ctx_preprocess)
+                gmqcc_preprocess_destroy(c->ctx_preprocess);
+            c->ctx_preprocess = (struct gmqcc_preprocess_s*)base;
+            break;
+
+        default:
+            gmqcc_global_error("Invalid context attachment");
+            return false;
+    }
+    return true;
+}
+
 static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
 
 static void parser_enterblock(parser_t *parser);
 static bool parser_leaveblock(parser_t *parser);
-static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
-static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
-static bool parse_typedef(parser_t *parser);
+static void parser_addlocal  (parser_t *parser, const char *name, ast_expression *e);
+static void parser_addglobal (parser_t *parser, const char *name, ast_expression *e);
+static bool parse_typedef    (parser_t *parser);
 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
 static ast_block* parse_block(parser_t *parser);
 static bool parse_block_into(parser_t *parser, ast_block *block);
@@ -6012,12 +6073,6 @@ parser_t *parser_create()
 
     memset(parser, 0, sizeof(*parser));
 
-    if (!(parser->code = code_init())) {
-        mem_d(parser);
-        return NULL;
-    }
-    
-
     for (i = 0; i < operator_count; ++i) {
         if (operators[i].id == opid1('=')) {
             parser->assign_op = operators+i;
diff --git a/util.c b/util.c
index f74688cdb88d73dab3e8fabee00129beb084550d..ca5eb812c33260c808043566f63b13beffd8c3a3 100644 (file)
--- a/util.c
+++ b/util.c
@@ -62,6 +62,24 @@ void util_mem_f(void *ptr) {
     if (mem_provided) mem_free(ptr);
     else              free    (ptr);
 }
+
+/*
+ * Protect with mutex some day for thread safety reasons
+ * otherwise weird things may happen with error reporting
+ * when multiple-threads are introduced.
+ */   
+const char *gmqcc_global_error(const char *text) {
+    static char *error = NULL;
+    if (text) {
+        if (error) mem_d(error);
+        error = util_strdup(text);
+    }
+    return error;
+}
+
+const char *gmqcc_global_geterror(void) {
+    return gmqcc_global_error(NULL);
+}
     
 
 /*