implement info log; parse #version directive
authorMichal Krol <mjkrol@gmail.org>
Fri, 15 Apr 2005 10:23:10 +0000 (10:23 +0000)
committerMichal Krol <mjkrol@gmail.org>
Fri, 15 Apr 2005 10:23:10 +0000 (10:23 +0000)
src/mesa/shader/shaderobjects_3dlabs.c
src/mesa/shader/slang/slang_compile.c
src/mesa/shader/slang/slang_compile.h

index e223977..709563d 100755 (executable)
@@ -550,6 +550,7 @@ _shader_Compile (struct gl2_shader_intf **intf)
 #else\r
        slang_translation_unit unit;\r
        slang_unit_type type;\r
+       slang_info_log info_log;\r
 #endif\r
 \r
        impl->_obj.compile_status = GL_FALSE;\r
@@ -625,14 +626,16 @@ _shader_Compile (struct gl2_shader_intf **intf)
                type = slang_unit_fragment_shader;\r
        else\r
                type = slang_unit_vertex_shader;\r
-       if (_slang_compile (impl->_obj.source, &unit, type))\r
+       slang_info_log_construct (&info_log);\r
+       if (_slang_compile (impl->_obj.source, &unit, type, &info_log))\r
        {\r
                impl->_obj.compile_status = GL_TRUE;\r
        }\r
        else\r
        {\r
-               impl->_obj._generic.info_log = _mesa_strdup ("error: invalid translation unit");\r
+               impl->_obj._generic.info_log = _mesa_strdup (info_log.text);\r
        }\r
+       slang_info_log_destruct (&info_log);\r
 #endif\r
 }\r
 \r
index e32613c..70e84ca 100644 (file)
@@ -31,6 +31,7 @@
 #include "imports.h" \r
 #include "slang_compile.h"\r
 #include "grammar_mesa.h"\r
+#include "slang_preprocess.h"\r
 \r
 /*\r
        This is a straightforward implementation of the slang front-end compiler.\r
@@ -74,6 +75,11 @@ char *slang_string_duplicate (const char *src)
        return _mesa_strdup (src);\r
 }\r
 \r
+unsigned int slang_string_length (const char *str)\r
+{\r
+       return _mesa_strlen (str);\r
+}\r
+\r
 static void slang_variable_construct (slang_variable *);\r
 static int slang_variable_copy (slang_variable *, const slang_variable *);\r
 static void slang_struct_construct (slang_struct *);\r
@@ -285,11 +291,23 @@ static int slang_variable_copy (slang_variable *x, const slang_variable *y)
                        return 0;\r
        }\r
        if (y->array_size != NULL)\r
+       {\r
+               x->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+               if (x->array_size == NULL)\r
+                       return 0;\r
+               slang_operation_construct (x->array_size);\r
                if (!slang_operation_copy (x->array_size, y->array_size))\r
                        return 0;\r
+       }\r
        if (y->initializer != NULL)\r
+       {\r
+               x->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+               if (x->initializer == NULL)\r
+                       return 0;\r
+               slang_operation_construct (x->initializer);\r
                if (!slang_operation_copy (x->initializer, y->initializer))\r
                        return 0;\r
+       }\r
        return 1;\r
 }\r
 \r
@@ -486,52 +504,134 @@ static void slang_translation_unit_destruct (slang_translation_unit *unit)
        slang_alloc_free (unit->structs);\r
 }\r
 \r
-static int parse_identifier (const byte **I, char **id)\r
+/* slang_info_log */\r
+\r
+static char *out_of_memory = "error: out of memory\n";\r
+\r
+void slang_info_log_construct (slang_info_log *log)\r
+{\r
+       log->text = NULL;\r
+       log->dont_free_text = 0;\r
+}\r
+\r
+void slang_info_log_destruct (slang_info_log *log)\r
+{\r
+       if (!log->dont_free_text)\r
+               slang_alloc_free (log->text);\r
+}\r
+\r
+static int slang_info_log_message (slang_info_log *log, const char *prefix, const char *msg)\r
+{\r
+       unsigned int new_size;\r
+       if (log->dont_free_text)\r
+               return 0;\r
+       new_size = slang_string_length (prefix) + 3 + slang_string_length (msg);\r
+       if (log->text != NULL)\r
+       {\r
+               log->text = (char *) slang_alloc_realloc (log->text, slang_string_length (log->text) + 1,\r
+                       new_size + slang_string_length (log->text) + 1);\r
+       }\r
+       else\r
+       {\r
+               log->text = (char *) slang_alloc_malloc (new_size + 1);\r
+               if (log->text != NULL)\r
+                       *log->text = '\0';\r
+       }\r
+       if (log->text == NULL)\r
+               return 0;\r
+       slang_string_concat (log->text, prefix);\r
+       slang_string_concat (log->text, ": ");\r
+       slang_string_concat (log->text, msg);\r
+       slang_string_concat (log->text, "\n");\r
+       return 1;\r
+}\r
+\r
+int slang_info_log_error (slang_info_log *log, const char *msg, ...)\r
+{\r
+       if (slang_info_log_message (log, "error", msg))\r
+               return 1;\r
+       slang_info_log_memory (log);\r
+       return 0;\r
+}\r
+\r
+int slang_info_log_warning (slang_info_log *log, const char *msg, ...)\r
+{\r
+       if (slang_info_log_message (log, "warning", msg))\r
+               return 1;\r
+       slang_info_log_memory (log);\r
+       return 0;\r
+}\r
+\r
+void slang_info_log_memory (slang_info_log *log)\r
+{\r
+       if (!slang_info_log_message (log, "error", "out of memory"))\r
+       {\r
+               log->dont_free_text = 1;\r
+               log->text = out_of_memory;\r
+       }\r
+}\r
+\r
+/* slang_parse_ctx */\r
+\r
+typedef struct slang_parse_ctx_\r
+{\r
+       const byte *I;\r
+       slang_info_log *L;\r
+} slang_parse_ctx;\r
+\r
+/* --- */\r
+\r
+static int parse_identifier (slang_parse_ctx *C, char **id)\r
 {\r
-       *id = slang_string_duplicate ((const char *) *I);\r
+       *id = slang_string_duplicate ((const char *) C->I);\r
        if (*id == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
-       *I += strlen ((const char *) *I) + 1;\r
+       }\r
+       C->I += strlen ((const char *) C->I) + 1;\r
        return 1;\r
 }\r
 \r
-static int parse_number (const byte **I, int *number)\r
+static int parse_number (slang_parse_ctx *C, int *number)\r
 {\r
-       const int radix = (int) (*(*I)++);\r
+       const int radix = (int) (*C->I++);\r
        *number = 0;\r
-       while (**I != '\0')\r
+       while (*C->I != '\0')\r
        {\r
                int digit;\r
-               if (**I >= '0' && **I <= '9')\r
-                       digit = (int) (**I - '0');\r
-               else if (**I >= 'A' && **I <= 'Z')\r
-                       digit = (int) (**I - 'A') + 10;\r
+               if (*C->I >= '0' && *C->I <= '9')\r
+                       digit = (int) (*C->I - '0');\r
+               else if (*C->I >= 'A' && *C->I <= 'Z')\r
+                       digit = (int) (*C->I - 'A') + 10;\r
                else\r
-                       digit = (int) (**I - 'a') + 10;\r
+                       digit = (int) (*C->I - 'a') + 10;\r
                *number = *number * radix + digit;\r
-               (*I)++;\r
+               C->I++;\r
        }\r
-       (*I)++;\r
+       C->I++;\r
+       if (*number > 65535)\r
+               slang_info_log_warning (C->L, "%d: literal integer overflow", *number);\r
        return 1;\r
 }\r
 \r
-static int parse_float (const byte **I, float *number)\r
+static int parse_float (slang_parse_ctx *C, float *number)\r
 {\r
        char *integral = NULL;\r
        char *fractional = NULL;\r
        char *exponent = NULL;\r
        char *whole = NULL;\r
 \r
-       if (!parse_identifier (I, &integral))\r
+       if (!parse_identifier (C, &integral))\r
                return 0;\r
 \r
-       if (!parse_identifier (I, &fractional))\r
+       if (!parse_identifier (C, &fractional))\r
        {\r
                slang_alloc_free (integral);\r
                return 0;\r
        }\r
 \r
-       if (!parse_identifier (I, &exponent))\r
+       if (!parse_identifier (C, &exponent))\r
        {\r
                slang_alloc_free (fractional);\r
                slang_alloc_free (integral);\r
@@ -545,6 +645,7 @@ static int parse_float (const byte **I, float *number)
                slang_alloc_free (exponent);\r
                slang_alloc_free (fractional);\r
                slang_alloc_free (integral);\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
        }\r
 \r
@@ -566,17 +667,20 @@ static int parse_float (const byte **I, float *number)
 /* revision number - increment after each change affecting emitted output */\r
 #define REVISION 2\r
 \r
-static int check_revision (const byte **I)\r
+static int check_revision (slang_parse_ctx *C)\r
 {\r
-       if (**I != REVISION)\r
+       if (*C->I != REVISION)\r
+       {\r
+               slang_info_log_error (C->L, "internal compiler error");\r
                return 0;\r
-       (*I)++;\r
+       }\r
+       C->I++;\r
        return 1;\r
 }\r
 \r
-static int parse_statement (const byte **, slang_operation *, slang_variable_scope *,\r
+static int parse_statement (slang_parse_ctx *, slang_operation *, slang_variable_scope *,\r
        slang_struct_scope *);\r
-static int parse_expression (const byte **, slang_operation *, slang_variable_scope *,\r
+static int parse_expression (slang_parse_ctx *, slang_operation *, slang_variable_scope *,\r
        slang_struct_scope *);\r
 \r
 /* type qualifier */\r
@@ -588,9 +692,9 @@ static int parse_expression (const byte **, slang_operation *, slang_variable_sc
 #define TYPE_QUALIFIER_FIXEDOUTPUT 5\r
 #define TYPE_QUALIFIER_FIXEDINPUT 6\r
 \r
-static int parse_type_qualifier (const byte **I, slang_type_qualifier *qual)\r
+static int parse_type_qualifier (slang_parse_ctx *C, slang_type_qualifier *qual)\r
 {\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case TYPE_QUALIFIER_NONE:\r
                *qual = slang_qual_none;\r
@@ -650,10 +754,10 @@ static int parse_type_qualifier (const byte **I, slang_type_qualifier *qual)
 #define FIELD_NEXT 1\r
 #define FIELD_ARRAY 2\r
 \r
-static int parse_type_specifier (const byte **I, slang_type_specifier *spec,\r
+static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,\r
        slang_struct_scope *structs, slang_variable_scope *scope)\r
 {\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case TYPE_SPECIFIER_VOID:\r
                spec->type = slang_spec_void;\r
@@ -725,17 +829,19 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                spec->type = slang_spec_struct;\r
                {\r
                        char *name;\r
-                       if (!parse_identifier (I, &name))\r
+                       if (!parse_identifier (C, &name))\r
                                return 0;\r
                        if (*name != '\0' && slang_struct_scope_find (structs, name, 0) != NULL)\r
                        {\r
+                               slang_info_log_error (C->L, "%s: duplicate type name", name);\r
                                slang_alloc_free (name);\r
-                               return 0;               /* error: duplicate names */\r
+                               return 0;\r
                        }\r
                        spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
                        if (spec->_struct == NULL)\r
                        {\r
                                slang_alloc_free (name);\r
+                               slang_info_log_memory (C->L);\r
                                return 0;\r
                        }\r
                        slang_struct_construct (spec->_struct);\r
@@ -746,7 +852,7 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                {\r
                        slang_type_specifier sp;\r
                        slang_type_specifier_construct (&sp);\r
-                       if (!parse_type_specifier (I, &sp, spec->_struct->structs, scope))\r
+                       if (!parse_type_specifier (C, &sp, spec->_struct->structs, scope))\r
                        {\r
                                slang_type_specifier_destruct (&sp);\r
                                return 0;\r
@@ -761,6 +867,7 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                                if (spec->_struct->fields->variables == NULL)\r
                                {\r
                                        slang_type_specifier_destruct (&sp);\r
+                                       slang_info_log_memory (C->L);\r
                                        return 0;\r
                                }\r
                                var = spec->_struct->fields->variables + spec->_struct->fields->num_variables;\r
@@ -771,12 +878,12 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                                        slang_type_specifier_destruct (&sp);\r
                                        return 0;\r
                                }\r
-                               if (!parse_identifier (I, &var->name))\r
+                               if (!parse_identifier (C, &var->name))\r
                                {\r
                                        slang_type_specifier_destruct (&sp);\r
                                        return 0;\r
                                }\r
-                               switch (*(*I)++)\r
+                               switch (*C->I++)\r
                                {\r
                                case FIELD_NONE:\r
                                        break;\r
@@ -786,23 +893,23 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                                        if (var->array_size == NULL)\r
                                        {\r
                                                slang_type_specifier_destruct (&sp);\r
+                                               slang_info_log_memory (C->L);\r
                                                return 0;\r
                                        }\r
                                        slang_operation_construct (var->array_size);\r
-                                       if (!parse_expression (I, var->array_size, scope, structs))\r
+                                       if (!parse_expression (C, var->array_size, scope, structs))\r
                                        {\r
                                                slang_type_specifier_destruct (&sp);\r
                                                return 0;\r
                                        }\r
                                        break;\r
                                default:\r
-                                       slang_type_specifier_destruct (&sp);\r
                                        return 0;\r
                                }\r
                        }\r
-                       while (*(*I)++ != FIELD_NONE);\r
+                       while (*C->I++ != FIELD_NONE);\r
                }\r
-               while (*(*I)++ != FIELD_NONE);\r
+               while (*C->I++ != FIELD_NONE);\r
                if (*spec->_struct->name != '\0')\r
                {\r
                        slang_struct *s;\r
@@ -810,7 +917,10 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                                structs->num_structs * sizeof (slang_struct),\r
                                (structs->num_structs + 1) * sizeof (slang_struct));\r
                        if (structs->structs == NULL)\r
+                       {\r
+                               slang_info_log_memory (C->L);\r
                                return 0;\r
+                       }\r
                        s = structs->structs + structs->num_structs;\r
                        structs->num_structs++;\r
                        slang_struct_construct (s);\r
@@ -823,15 +933,22 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
                {\r
                        char *name;\r
                        slang_struct *stru;\r
-                       if (!parse_identifier (I, &name))\r
+                       if (!parse_identifier (C, &name))\r
                                return 0;\r
                        stru = slang_struct_scope_find (structs, name, 1);\r
-                       slang_alloc_free (name);\r
                        if (stru == NULL)\r
+                       {\r
+                               slang_info_log_error (C->L, "%s: undeclared type name", name);\r
+                               slang_alloc_free (name);\r
                                return 0;\r
+                       }\r
+                       slang_alloc_free (name);\r
                        spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
                        if (spec->_struct == NULL)\r
+                       {\r
+                               slang_info_log_memory (C->L);\r
                                return 0;\r
+                       }\r
                        slang_struct_construct (spec->_struct);\r
                        if (!slang_struct_copy (spec->_struct, stru))\r
                                return 0;\r
@@ -843,12 +960,12 @@ static int parse_type_specifier (const byte **I, slang_type_specifier *spec,
        return 1;\r
 }\r
 \r
-static int parse_fully_specified_type (const byte **I, slang_fully_specified_type *type,\r
+static int parse_fully_specified_type (slang_parse_ctx *C, slang_fully_specified_type *type,\r
        slang_struct_scope *structs, slang_variable_scope *scope)\r
 {\r
-       if (!parse_type_qualifier (I, &type->qualifier))\r
+       if (!parse_type_qualifier (C, &type->qualifier))\r
                return 0;\r
-       return parse_type_specifier (I, &type->specifier, structs, scope);\r
+       return parse_type_specifier (C, &type->specifier, structs, scope);\r
 }\r
 \r
 /* operation */\r
@@ -915,49 +1032,52 @@ static int parse_fully_specified_type (const byte **I, slang_fully_specified_typ
 #define OP_POSTINCREMENT 60\r
 #define OP_POSTDECREMENT 61\r
 \r
-static int parse_child_operation (const byte **I, slang_operation *oper, int statement,\r
+static int parse_child_operation (slang_parse_ctx *C, slang_operation *oper, int statement,\r
        slang_variable_scope *scope, slang_struct_scope *structs)\r
 {\r
        oper->children = (slang_operation *) slang_alloc_realloc (oper->children,\r
                oper->num_children * sizeof (slang_operation),\r
                (oper->num_children + 1) * sizeof (slang_operation));\r
        if (oper->children == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        slang_operation_construct (oper->children + oper->num_children);\r
        oper->num_children++;\r
        if (statement)\r
-               return parse_statement (I, oper->children + oper->num_children - 1, scope, structs);\r
-       return parse_expression (I, oper->children + oper->num_children - 1, scope, structs);\r
+               return parse_statement (C, oper->children + oper->num_children - 1, scope, structs);\r
+       return parse_expression (C, oper->children + oper->num_children - 1, scope, structs);\r
 }\r
 \r
-static int parse_declaration (const byte **, slang_variable_scope *, slang_struct_scope *,\r
+static int parse_declaration (slang_parse_ctx *C, slang_variable_scope *, slang_struct_scope *,\r
        slang_function_scope *);\r
 \r
-static int parse_statement (const byte **I, slang_operation *oper, slang_variable_scope *scope,\r
+static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_variable_scope *scope,\r
        slang_struct_scope *structs)\r
 {\r
        oper->locals->outer_scope = scope;\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case OP_BLOCK_BEGIN_NO_NEW_SCOPE:\r
                oper->type = slang_oper_block_no_new_scope;\r
-               while (**I != OP_END)\r
-                       if (!parse_child_operation (I, oper, 1, scope, structs))\r
+               while (*C->I != OP_END)\r
+                       if (!parse_child_operation (C, oper, 1, scope, structs))\r
                                return 0;\r
-               (*I)++;\r
+               C->I++;\r
                break;\r
        case OP_BLOCK_BEGIN_NEW_SCOPE:\r
                oper->type = slang_oper_block_new_scope;\r
-               while (**I != OP_END)\r
-                       if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               while (*C->I != OP_END)\r
+                       if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                                return 0;\r
-               (*I)++;\r
+               C->I++;\r
                break;\r
        case OP_DECLARE:\r
                oper->type = slang_oper_variable_decl;\r
                {\r
                        const unsigned int first_var = scope->num_variables;\r
-                       if (!parse_declaration (I, scope, structs, NULL))\r
+                       if (!parse_declaration (C, scope, structs, NULL))\r
                                return 0;\r
                        if (first_var < scope->num_variables)\r
                        {\r
@@ -966,7 +1086,10 @@ static int parse_statement (const byte **I, slang_operation *oper, slang_variabl
                                oper->children = (slang_operation *) slang_alloc_malloc (num_vars * sizeof (\r
                                        slang_operation));\r
                                if (oper->children == NULL)\r
+                               {\r
+                                       slang_info_log_memory (C->L);\r
                                        return 0;\r
+                               }\r
                                for (i = 0; i < num_vars; i++)\r
                                        slang_operation_construct (oper->children + i);\r
                                oper->num_children = num_vars;\r
@@ -977,19 +1100,22 @@ static int parse_statement (const byte **I, slang_operation *oper, slang_variabl
                                        o->locals->outer_scope = scope;\r
                                        o->identifier = slang_string_duplicate (scope->variables[i].name);\r
                                        if (o->identifier == NULL)\r
+                                       {\r
+                                               slang_info_log_memory (C->L);\r
                                                return 0;\r
+                                       }\r
                                }\r
                        }\r
                }\r
                break;\r
        case OP_ASM:\r
                oper->type = slang_oper_asm;\r
-               if (!parse_identifier (I, &oper->identifier))\r
+               if (!parse_identifier (C, &oper->identifier))\r
                        return 0;\r
-               while (**I != OP_END)\r
-                       if (!parse_child_operation (I, oper, 0, scope, structs))\r
+               while (*C->I != OP_END)\r
+                       if (!parse_child_operation (C, oper, 0, scope, structs))\r
                                return 0;\r
-               (*I)++;\r
+               C->I++;\r
                break;\r
        case OP_BREAK:\r
                oper->type = slang_oper_break;\r
@@ -1002,46 +1128,46 @@ static int parse_statement (const byte **I, slang_operation *oper, slang_variabl
                break;\r
        case OP_RETURN:\r
                oper->type = slang_oper_return;\r
-               if (!parse_child_operation (I, oper, 0, scope, structs))\r
+               if (!parse_child_operation (C, oper, 0, scope, structs))\r
                        return 0;\r
                break;\r
        case OP_EXPRESSION:\r
                oper->type = slang_oper_expression;\r
-               if (!parse_child_operation (I, oper, 0, scope, structs))\r
+               if (!parse_child_operation (C, oper, 0, scope, structs))\r
                        return 0;\r
                break;\r
        case OP_IF:\r
                oper->type = slang_oper_if;\r
-               if (!parse_child_operation (I, oper, 0, scope, structs))\r
+               if (!parse_child_operation (C, oper, 0, scope, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 1, scope, structs))\r
+               if (!parse_child_operation (C, oper, 1, scope, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 1, scope, structs))\r
+               if (!parse_child_operation (C, oper, 1, scope, structs))\r
                        return 0;\r
                break;\r
        case OP_WHILE:\r
                oper->type = slang_oper_while;\r
-               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                        return 0;\r
                break;\r
        case OP_DO:\r
                oper->type = slang_oper_do;\r
-               if (!parse_child_operation (I, oper, 1, scope, structs))\r
+               if (!parse_child_operation (C, oper, 1, scope, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 0, scope, structs))\r
+               if (!parse_child_operation (C, oper, 0, scope, structs))\r
                        return 0;\r
                break;\r
        case OP_FOR:\r
                oper->type = slang_oper_for;\r
-               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 0, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 0, oper->locals, structs))\r
                        return 0;\r
-               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+               if (!parse_child_operation (C, oper, 1, oper->locals, structs))\r
                        return 0;\r
                break;\r
        default:\r
@@ -1050,13 +1176,16 @@ static int parse_statement (const byte **I, slang_operation *oper, slang_variabl
        return 1;\r
 }\r
 \r
-static int handle_trinary_expression (slang_operation *op, slang_operation **ops,\r
-       unsigned int *num_ops)\r
+static int handle_trinary_expression (slang_parse_ctx *C, slang_operation *op,\r
+       slang_operation **ops, unsigned int *num_ops)\r
 {\r
        op->num_children = 3;\r
        op->children = (slang_operation *) slang_alloc_malloc (3 * sizeof (slang_operation));\r
        if (op->children == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        op->children[0] = (*ops)[*num_ops - 4];\r
        op->children[1] = (*ops)[*num_ops - 3];\r
        op->children[2] = (*ops)[*num_ops - 2];\r
@@ -1065,17 +1194,23 @@ static int handle_trinary_expression (slang_operation *op, slang_operation **ops
        *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 3) * sizeof (slang_operation),\r
                *num_ops * sizeof (slang_operation));\r
        if (*ops == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        return 1;\r
 }\r
 \r
-static int handle_binary_expression (slang_operation *op, slang_operation **ops,\r
-       unsigned int *num_ops)\r
+static int handle_binary_expression (slang_parse_ctx *C, slang_operation *op,\r
+       slang_operation **ops, unsigned int *num_ops)\r
 {\r
        op->num_children = 2;\r
        op->children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation));\r
        if (op->children == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        op->children[0] = (*ops)[*num_ops - 3];\r
        op->children[1] = (*ops)[*num_ops - 2];\r
        (*ops)[*num_ops - 3] = (*ops)[*num_ops - 1];\r
@@ -1083,42 +1218,54 @@ static int handle_binary_expression (slang_operation *op, slang_operation **ops,
        *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 2) * sizeof (slang_operation),\r
                *num_ops * sizeof (slang_operation));\r
        if (*ops == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        return 1;\r
 }\r
 \r
-static int handle_unary_expression (slang_operation *op, slang_operation **ops, \r
-       unsigned int *num_ops)\r
+static int handle_unary_expression (slang_parse_ctx *C, slang_operation *op,\r
+       slang_operation **ops, unsigned int *num_ops)\r
 {\r
        op->num_children = 1;\r
        op->children = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
        if (op->children == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        op->children[0] = (*ops)[*num_ops - 2];\r
        (*ops)[*num_ops - 2] = (*ops)[*num_ops - 1];\r
        (*num_ops)--;\r
        *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 1) * sizeof (slang_operation),\r
                *num_ops * sizeof (slang_operation));\r
        if (*ops == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        return 1;\r
 }\r
 \r
-static int parse_expression (const byte **I, slang_operation *oper, slang_variable_scope *scope,\r
+static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_variable_scope *scope,\r
        slang_struct_scope *structs)\r
 {\r
        slang_operation *ops = NULL;\r
        unsigned int num_ops = 0;\r
        int number;\r
 \r
-       while (**I != OP_END)\r
+       while (*C->I != OP_END)\r
        {\r
                slang_operation *op;\r
-               const unsigned int op_code = *(*I)++;\r
+               const unsigned int op_code = *C->I++;\r
                ops = (slang_operation *) slang_alloc_realloc (ops,\r
                        num_ops * sizeof (slang_operation), (num_ops + 1) * sizeof (slang_operation));\r
                if (ops == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                op = ops + num_ops;\r
                num_ops++;\r
                slang_operation_construct (op);\r
@@ -1130,54 +1277,54 @@ static int parse_expression (const byte **I, slang_operation *oper, slang_variab
                        break;\r
                case OP_PUSH_BOOL:\r
                        op->type = slang_oper_literal_bool;\r
-                       if (!parse_number (I, &number))\r
+                       if (!parse_number (C, &number))\r
                                return 0;\r
                        op->literal = (float) number;\r
                        break;\r
                case OP_PUSH_INT:\r
                        op->type = slang_oper_literal_int;\r
-                       if (!parse_number (I, &number))\r
+                       if (!parse_number (C, &number))\r
                                return 0;\r
                        op->literal = (float) number;\r
                        break;\r
                case OP_PUSH_FLOAT:\r
                        op->type = slang_oper_literal_float;\r
-                       if (!parse_float (I, &op->literal))\r
+                       if (!parse_float (C, &op->literal))\r
                                return 0;\r
                        break;\r
                case OP_PUSH_IDENTIFIER:\r
                        op->type = slang_oper_identifier;\r
-                       if (!parse_identifier (I, &op->identifier))\r
+                       if (!parse_identifier (C, &op->identifier))\r
                                return 0;\r
                        break;\r
                case OP_SEQUENCE:\r
                        op->type = slang_oper_sequence;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_ASSIGN:\r
                        op->type = slang_oper_assign;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_ADDASSIGN:\r
                        op->type = slang_oper_addassign;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_SUBASSIGN:\r
                        op->type = slang_oper_subassign;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_MULASSIGN:\r
                        op->type = slang_oper_mulassign;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_DIVASSIGN:\r
                        op->type = slang_oper_divassign;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                /*case OP_MODASSIGN:*/\r
@@ -1188,22 +1335,22 @@ static int parse_expression (const byte **I, slang_operation *oper, slang_variab
                /*case OP_ANDASSIGN:*/\r
                case OP_SELECT:\r
                        op->type = slang_oper_select;\r
-                       if (!handle_trinary_expression (op, &ops, &num_ops))\r
+                       if (!handle_trinary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_LOGICALOR:\r
                        op->type = slang_oper_logicalor;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_LOGICALXOR:\r
                        op->type = slang_oper_logicalxor;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_LOGICALAND:\r
                        op->type = slang_oper_logicaland;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                /*case OP_BITOR:*/\r
@@ -1211,119 +1358,119 @@ static int parse_expression (const byte **I, slang_operation *oper, slang_variab
                /*case OP_BITAND:*/\r
                case OP_EQUAL:\r
                        op->type = slang_oper_equal;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_NOTEQUAL:\r
                        op->type = slang_oper_notequal;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_LESS:\r
                        op->type = slang_oper_less;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_GREATER:\r
                        op->type = slang_oper_greater;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_LESSEQUAL:\r
                        op->type = slang_oper_lessequal;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_GREATEREQUAL:\r
                        op->type = slang_oper_greaterequal;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                /*case OP_LSHIFT:*/\r
                /*case OP_RSHIFT:*/\r
                case OP_ADD:\r
                        op->type = slang_oper_add;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_SUBTRACT:\r
                        op->type = slang_oper_subtract;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_MULTIPLY:\r
                        op->type = slang_oper_multiply;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_DIVIDE:\r
                        op->type = slang_oper_divide;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                /*case OP_MODULUS:*/\r
                case OP_PREINCREMENT:\r
                        op->type = slang_oper_preincrement;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_PREDECREMENT:\r
                        op->type = slang_oper_predecrement;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_PLUS:\r
                        op->type = slang_oper_plus;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_MINUS:\r
                        op->type = slang_oper_minus;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_NOT:\r
                        op->type = slang_oper_not;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                /*case OP_COMPLEMENT:*/\r
                case OP_SUBSCRIPT:\r
                        op->type = slang_oper_subscript;\r
-                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                       if (!handle_binary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_CALL:\r
                        op->type = slang_oper_call;\r
-                       if (!parse_identifier (I, &op->identifier))\r
+                       if (!parse_identifier (C, &op->identifier))\r
                                return 0;\r
-                       while (**I != OP_END)\r
-                               if (!parse_child_operation (I, op, 0, scope, structs))\r
+                       while (*C->I != OP_END)\r
+                               if (!parse_child_operation (C, op, 0, scope, structs))\r
                                        return 0;\r
-                       (*I)++;\r
+                       C->I++;\r
                        break;\r
                case OP_FIELD:\r
                        op->type = slang_oper_field;\r
-                       if (!parse_identifier (I, &op->identifier))\r
+                       if (!parse_identifier (C, &op->identifier))\r
                                return 0;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_POSTINCREMENT:\r
                        op->type = slang_oper_postincrement;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                case OP_POSTDECREMENT:\r
                        op->type = slang_oper_postdecrement;\r
-                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                       if (!handle_unary_expression (C, op, &ops, &num_ops))\r
                                return 0;\r
                        break;\r
                default:\r
                        return 0;\r
                }\r
        }\r
-       (*I)++;\r
+       C->I++;\r
        *oper = *ops;\r
        slang_alloc_free (ops);\r
        return 1;\r
@@ -1338,41 +1485,55 @@ static int parse_expression (const byte **I, slang_operation *oper, slang_variab
 #define PARAMETER_ARRAY_NOT_PRESENT 0\r
 #define PARAMETER_ARRAY_PRESENT 1\r
 \r
-static int parse_parameter_declaration (const byte **I, slang_variable *param,\r
+static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *param,\r
        slang_struct_scope *structs, slang_variable_scope *scope)\r
 {\r
-       if (!parse_type_qualifier (I, &param->type.qualifier))\r
+       if (!parse_type_qualifier (C, &param->type.qualifier))\r
                return 0;\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case PARAM_QUALIFIER_IN:\r
                if (param->type.qualifier != slang_qual_const && param->type.qualifier != slang_qual_none)\r
-                       return 0;       /* error: type qualifier is invalid */\r
+               {\r
+                       slang_info_log_error (C->L, "invalid type qualifier");\r
+                       return 0;\r
+               }\r
                break;\r
        case PARAM_QUALIFIER_OUT:\r
                if (param->type.qualifier == slang_qual_none)\r
                        param->type.qualifier = slang_qual_out;\r
                else\r
-                       return 0;       /* error: type qualifier is invalid */\r
+               {\r
+                       slang_info_log_error (C->L, "invalid type qualifier");\r
+                       return 0;\r
+               }\r
                break;\r
        case PARAM_QUALIFIER_INOUT:\r
                if (param->type.qualifier == slang_qual_none)\r
                        param->type.qualifier = slang_qual_inout;\r
                else\r
-                       return 0;       /* error: type qualifier is invalid */\r
+               {\r
+                       slang_info_log_error (C->L, "invalid type qualifier");\r
+                       return 0;\r
+               }\r
                break;\r
        default:\r
                return 0;\r
        }\r
-       if (!parse_type_specifier (I, &param->type.specifier, structs, scope))\r
+       if (!parse_type_specifier (C, &param->type.specifier, structs, scope))\r
                return 0;\r
-       if (!parse_identifier (I, &param->name))\r
+       if (!parse_identifier (C, &param->name))\r
                return 0;\r
-       if (*(*I)++ == PARAMETER_ARRAY_PRESENT)\r
+       if (*C->I++ == PARAMETER_ARRAY_PRESENT)\r
        {\r
                param->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+               if (param->array_size == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
+                       return 0;\r
+               }\r
                slang_operation_construct (param->array_size);\r
-               if (!parse_expression (I, param->array_size, scope, structs))\r
+               if (!parse_expression (C, param->array_size, scope, structs))\r
                        return 0;\r
        }\r
        return 1;\r
@@ -1485,31 +1646,34 @@ static const struct {
        /*{ OPERATOR_BITXOR, "^" }*/\r
 };\r
 \r
-static int parse_operator_name (const byte **I, char **pname)\r
+static int parse_operator_name (slang_parse_ctx *C, char **pname)\r
 {\r
        unsigned int i;\r
        for (i = 0; i < sizeof (operator_names) / sizeof (*operator_names); i++)\r
-               if (operator_names[i].o_code == (unsigned int) (**I))\r
+               if (operator_names[i].o_code == (unsigned int) (*C->I))\r
                {\r
                        *pname = slang_string_duplicate (operator_names[i].o_name);\r
                        if (*pname == NULL)\r
+                       {\r
+                               slang_info_log_memory (C->L);\r
                                return 0;\r
-                       (*I)++;\r
+                       }\r
+                       C->I++;\r
                        return 1;\r
                }\r
        return 0;\r
 }\r
 \r
-static int parse_function_prototype (const byte **I, slang_function *func,\r
+static int parse_function_prototype (slang_parse_ctx *C, slang_function *func,\r
        slang_struct_scope *structs, slang_variable_scope *scope)\r
 {\r
-       if (!parse_fully_specified_type (I, &func->header.type, structs, scope))\r
+       if (!parse_fully_specified_type (C, &func->header.type, structs, scope))\r
                return 0;\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case FUNCTION_ORDINARY:\r
                func->kind = slang_func_ordinary;\r
-               if (!parse_identifier (I, &func->header.name))\r
+               if (!parse_identifier (C, &func->header.name))\r
                        return 0;\r
                break;\r
        case FUNCTION_CONSTRUCTOR:\r
@@ -1519,28 +1683,34 @@ static int parse_function_prototype (const byte **I, slang_function *func,
                func->header.name = slang_string_duplicate (\r
                        type_specifier_names[func->header.type.specifier.type]);\r
                if (func->header.name == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                break;\r
        case FUNCTION_OPERATOR:\r
                func->kind = slang_func_operator;\r
-               if (!parse_operator_name (I, &func->header.name))\r
+               if (!parse_operator_name (C, &func->header.name))\r
                        return 0;\r
                break;\r
        default:\r
                return 0;\r
        }\r
        func->parameters->outer_scope = scope;\r
-       while (*(*I)++ == PARAMETER_NEXT)\r
+       while (*C->I++ == PARAMETER_NEXT)\r
        {\r
                func->parameters->variables = (slang_variable *) slang_alloc_realloc (\r
                        func->parameters->variables,\r
                        func->parameters->num_variables * sizeof (slang_variable),\r
                        (func->parameters->num_variables + 1) * sizeof (slang_variable));\r
                if (func->parameters->variables == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                slang_variable_construct (func->parameters->variables + func->parameters->num_variables);\r
                func->parameters->num_variables++;\r
-               if (!parse_parameter_declaration (I, func->parameters->variables +\r
+               if (!parse_parameter_declaration (C, func->parameters->variables +\r
                        func->parameters->num_variables - 1, structs, scope))\r
                        return 0;\r
        }\r
@@ -1548,16 +1718,19 @@ static int parse_function_prototype (const byte **I, slang_function *func,
        return 1;\r
 }\r
 \r
-static int parse_function_definition (const byte **I, slang_function *func,\r
+static int parse_function_definition (slang_parse_ctx *C, slang_function *func,\r
        slang_struct_scope *structs, slang_variable_scope *scope)\r
 {\r
-       if (!parse_function_prototype (I, func, structs, scope))\r
+       if (!parse_function_prototype (C, func, structs, scope))\r
                return 0;\r
        func->body = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
        if (func->body == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        slang_operation_construct (func->body);\r
-       if (!parse_statement (I, func->body, func->parameters, structs))\r
+       if (!parse_statement (C, func->body, func->parameters, structs))\r
                return 0;\r
        return 1;\r
 }\r
@@ -1573,25 +1746,28 @@ static int parse_function_definition (const byte **I, slang_function *func,
 #define VARIABLE_ARRAY_EXPLICIT 3\r
 #define VARIABLE_ARRAY_UNKNOWN 4\r
 \r
-static int parse_init_declarator (const byte **I, const slang_fully_specified_type *type,\r
+static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specified_type *type,\r
        slang_variable_scope *vars, slang_struct_scope *structs)\r
 {\r
        slang_variable *var;\r
 \r
-       if (*(*I)++ == VARIABLE_NONE)\r
+       if (*C->I++ == VARIABLE_NONE)\r
                return 1;\r
        vars->variables = (slang_variable *) slang_alloc_realloc (vars->variables,\r
                vars->num_variables * sizeof (slang_variable),\r
                (vars->num_variables + 1) * sizeof (slang_variable));\r
        if (vars->variables == NULL)\r
+       {\r
+               slang_info_log_memory (C->L);\r
                return 0;\r
+       }\r
        var = vars->variables + vars->num_variables;\r
        vars->num_variables++;\r
        slang_variable_construct (var);\r
        var->type.qualifier = type->qualifier;\r
-       if (!parse_identifier (I, &var->name))\r
+       if (!parse_identifier (C, &var->name))\r
                return 0;\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case VARIABLE_NONE:\r
                if (!slang_type_specifier_copy (&var->type.specifier, &type->specifier))\r
@@ -1602,9 +1778,12 @@ static int parse_init_declarator (const byte **I, const slang_fully_specified_ty
                        return 0;\r
                var->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
                if (var->initializer == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                slang_operation_construct (var->initializer);\r
-               if (!parse_expression (I, var->initializer, vars, structs))\r
+               if (!parse_expression (C, var->initializer, vars, structs))\r
                        return 0;\r
                break;\r
        case VARIABLE_ARRAY_UNKNOWN:\r
@@ -1612,7 +1791,10 @@ static int parse_init_declarator (const byte **I, const slang_fully_specified_ty
                var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof (\r
                        slang_type_specifier));\r
                if (var->type.specifier._array == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                slang_type_specifier_construct (var->type.specifier._array);\r
                if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier))\r
                        return 0;\r
@@ -1622,15 +1804,21 @@ static int parse_init_declarator (const byte **I, const slang_fully_specified_ty
                var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof (\r
                        slang_type_specifier));\r
                if (var->type.specifier._array == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                slang_type_specifier_construct (var->type.specifier._array);\r
                if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier))\r
                        return 0;\r
                var->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
                if (var->array_size == NULL)\r
+               {\r
+                       slang_info_log_memory (C->L);\r
                        return 0;\r
+               }\r
                slang_operation_construct (var->array_size);\r
-               if (!parse_expression (I, var->array_size, vars, structs))\r
+               if (!parse_expression (C, var->array_size, vars, structs))\r
                        return 0;\r
                break;\r
        default:\r
@@ -1639,31 +1827,31 @@ static int parse_init_declarator (const byte **I, const slang_fully_specified_ty
        return 1;\r
 }\r
 \r
-static int parse_init_declarator_list (const byte **I, slang_variable_scope *vars,\r
+static int parse_init_declarator_list (slang_parse_ctx *C, slang_variable_scope *vars,\r
        slang_struct_scope *structs)\r
 {\r
        slang_fully_specified_type type;\r
 \r
        slang_fully_specified_type_construct (&type);\r
-       if (!parse_fully_specified_type (I, &type, structs, vars))\r
+       if (!parse_fully_specified_type (C, &type, structs, vars))\r
        {\r
                slang_fully_specified_type_destruct (&type);\r
                return 0;\r
        }\r
        do\r
        {\r
-               if (!parse_init_declarator (I, &type, vars, structs))\r
+               if (!parse_init_declarator (C, &type, vars, structs))\r
                {\r
                        slang_fully_specified_type_destruct (&type);\r
                        return 0;\r
                }\r
        }\r
-       while (*(*I)++ == DECLARATOR_NEXT);\r
+       while (*C->I++ == DECLARATOR_NEXT);\r
        slang_fully_specified_type_destruct (&type);\r
        return 1;\r
 }\r
 \r
-static int parse_function (const byte **I, int definition, slang_struct_scope *structs,\r
+static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scope *structs,\r
        slang_function_scope *funcs, slang_variable_scope *scope)\r
 {\r
        slang_function parsed_func, *found_func;\r
@@ -1671,7 +1859,7 @@ static int parse_function (const byte **I, int definition, slang_struct_scope *s
        slang_function_construct (&parsed_func);\r
        if (definition)\r
        {\r
-               if (!parse_function_definition (I, &parsed_func, structs, scope))\r
+               if (!parse_function_definition (C, &parsed_func, structs, scope))\r
                {\r
                        slang_function_destruct (&parsed_func);\r
                        return 0;\r
@@ -1679,7 +1867,7 @@ static int parse_function (const byte **I, int definition, slang_struct_scope *s
        }\r
        else\r
        {\r
-               if (!parse_function_prototype (I, &parsed_func, structs, scope))\r
+               if (!parse_function_prototype (C, &parsed_func, structs, scope))\r
                {\r
                        slang_function_destruct (&parsed_func);\r
                        return 0;\r
@@ -1693,6 +1881,7 @@ static int parse_function (const byte **I, int definition, slang_struct_scope *s
                        slang_function));\r
                if (funcs->functions == NULL)\r
                {\r
+                       slang_info_log_memory (C->L);\r
                        slang_function_destruct (&parsed_func);\r
                        return 0;\r
                }\r
@@ -1706,8 +1895,10 @@ static int parse_function (const byte **I, int definition, slang_struct_scope *s
                {\r
                        if (found_func->body != NULL)\r
                        {\r
+                               slang_info_log_error (C->L, "%s: function already has a body",\r
+                                       parsed_func.header.name);\r
                                slang_function_destruct (&parsed_func);\r
-                               return 0;               /* error: second definition */\r
+                               return 0;\r
                        }\r
                        slang_function_destruct (found_func);\r
                        *found_func = parsed_func;\r
@@ -1724,17 +1915,17 @@ static int parse_function (const byte **I, int definition, slang_struct_scope *s
 #define DECLARATION_FUNCTION_PROTOTYPE 1\r
 #define DECLARATION_INIT_DECLARATOR_LIST 2\r
 \r
-static int parse_declaration (const byte **I, slang_variable_scope *scope,\r
+static int parse_declaration (slang_parse_ctx *C, slang_variable_scope *scope,\r
        slang_struct_scope *structs, slang_function_scope *funcs)\r
 {\r
-       switch (*(*I)++)\r
+       switch (*C->I++)\r
        {\r
        case DECLARATION_INIT_DECLARATOR_LIST:\r
-               if (!parse_init_declarator_list (I, scope, structs))\r
+               if (!parse_init_declarator_list (C, scope, structs))\r
                        return 0;\r
                break;\r
        case DECLARATION_FUNCTION_PROTOTYPE:\r
-               if (!parse_function (I, 0, structs, funcs, scope))\r
+               if (!parse_function (C, 0, structs, funcs, scope))\r
                        return 0;\r
                break;\r
        default:\r
@@ -1748,45 +1939,57 @@ static int parse_declaration (const byte **I, slang_variable_scope *scope,
 #define EXTERNAL_FUNCTION_DEFINITION 1\r
 #define EXTERNAL_DECLARATION 2\r
 \r
-static int parse_translation_unit (const byte **I, slang_translation_unit *unit)\r
+static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *unit)\r
 {\r
-       while (**I != EXTERNAL_NULL)\r
+       while (*C->I != EXTERNAL_NULL)\r
        {\r
-               switch (*(*I)++)\r
+               switch (*C->I++)\r
                {\r
                case EXTERNAL_FUNCTION_DEFINITION:\r
-                       if (!parse_function (I, 1, unit->structs, &unit->functions, unit->globals))\r
+                       if (!parse_function (C, 1, unit->structs, &unit->functions, unit->globals))\r
                                return 0;\r
                        break;\r
                case EXTERNAL_DECLARATION:\r
-                       if (!parse_declaration (I, unit->globals, unit->structs, &unit->functions))\r
+                       if (!parse_declaration (C, unit->globals, unit->structs, &unit->functions))\r
                                return 0;\r
                        break;\r
                default:\r
                        return 0;\r
                }\r
        }\r
-       (*I)++;\r
+       C->I++;\r
        return 1;\r
 }\r
 \r
 static int compile_with_grammar (grammar id, const char *source, slang_translation_unit *unit,\r
-       slang_unit_type type)\r
+       slang_unit_type type, slang_info_log *log)\r
 {\r
-       byte *prod, *I;\r
-       unsigned int size;\r
+       byte *prod;\r
+       unsigned int size, start, version;\r
+       slang_parse_ctx C;\r
+\r
+       /* retrieve version */\r
+       if (!_slang_preprocess_version (source, &version, &start, log))\r
+               return 0;\r
 \r
        slang_translation_unit_construct (unit);\r
        unit->type = type;\r
-       if (!grammar_fast_check (id, (const byte *) source, &prod, &size, 65536))\r
+       if (!grammar_fast_check (id, (const byte *) source + start, &prod, &size, 65536))\r
+       {\r
+               char buf[1024];\r
+               unsigned int pos;\r
+               grammar_get_last_error (buf, 1024, &pos);\r
+               slang_info_log_error (log, buf);\r
                return 0;\r
-       I = prod;\r
-       if (!check_revision (&I))\r
+       }\r
+       C.I = prod;\r
+       C.L = log;\r
+       if (!check_revision (&C))\r
        {\r
                grammar_alloc_free (prod);\r
                return 0;\r
        }\r
-       if (!parse_translation_unit (&I, unit))\r
+       if (!parse_translation_unit (&C, unit))\r
        {\r
                slang_translation_unit_destruct (unit);\r
                grammar_alloc_free (prod);\r
@@ -1800,13 +2003,20 @@ static const char *slang_shader_syn =
 #include "library/slang_shader_syn.h"\r
 ;\r
 \r
-int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit_type type)\r
+int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit_type type,\r
+       slang_info_log *log)\r
 {\r
        grammar id;\r
 \r
        id = grammar_load_from_text ((const byte *) slang_shader_syn);\r
        if (id == 0)\r
+       {\r
+               char buf[1024];\r
+               unsigned int pos;\r
+               grammar_get_last_error (buf, 1024, &pos);\r
+               slang_info_log_error (log, buf);\r
                return 0;\r
+       }\r
 \r
        grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1);\r
        if (type == slang_unit_fragment_shader)\r
@@ -1814,7 +2024,7 @@ int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit
        else\r
                grammar_set_reg8 (id, (const byte *) "shader_type", 2);\r
 \r
-       if (!compile_with_grammar (id, source, unit, type))\r
+       if (!compile_with_grammar (id, source, unit, type, log))\r
        {\r
                grammar_destroy (id);\r
                return 0;\r
index 0f49df7..59e7ee8 100644 (file)
@@ -225,7 +225,19 @@ typedef struct slang_translation_unit_
        slang_unit_type type;\r
 } slang_translation_unit;\r
 \r
-int _slang_compile (const char *, slang_translation_unit *, slang_unit_type type);\r
+typedef struct slang_info_log_\r
+{\r
+       char *text;\r
+       int dont_free_text;\r
+} slang_info_log;\r
+\r
+void slang_info_log_construct (slang_info_log *);\r
+void slang_info_log_destruct (slang_info_log *);\r
+int slang_info_log_error (slang_info_log *, const char *, ...);\r
+int slang_info_log_warning (slang_info_log *, const char *, ...);\r
+void slang_info_log_memory (slang_info_log *);\r
+\r
+int _slang_compile (const char *, slang_translation_unit *, slang_unit_type type, slang_info_log *);\r
 \r
 #ifdef __cplusplus\r
 }\r