simple front-end compiler
authorMichal Krol <mjkrol@gmail.org>
Wed, 13 Apr 2005 14:04:41 +0000 (14:04 +0000)
committerMichal Krol <mjkrol@gmail.org>
Wed, 13 Apr 2005 14:04:41 +0000 (14:04 +0000)
src/mesa/shader/slang/slang_compile.c [new file with mode: 0644]
src/mesa/shader/slang/slang_compile.h [new file with mode: 0644]

diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c
new file mode 100644 (file)
index 0000000..e32613c
--- /dev/null
@@ -0,0 +1,1826 @@
+/*\r
+ * Mesa 3-D graphics library\r
+ * Version:  6.3\r
+ *\r
+ * Copyright (C) 2005  Brian Paul   All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a\r
+ * copy of this software and associated documentation files (the "Software"),\r
+ * to deal in the Software without restriction, including without limitation\r
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+ * and/or sell copies of the Software, and to permit persons to whom the\r
+ * Software is furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included\r
+ * in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ */\r
+\r
+/**\r
+ * \file slang_compile.c\r
+ * slang front-end compiler\r
+ * \author Michal Krol\r
+ */\r
+\r
+#include "imports.h" \r
+#include "slang_compile.h"\r
+#include "grammar_mesa.h"\r
+\r
+/*\r
+       This is a straightforward implementation of the slang front-end compiler.\r
+       Lots of error-checking functionality is missing but every well-formed shader source should\r
+       compile successfully and execute as expected. However, some semantically ill-formed shaders\r
+       may be accepted resulting in undefined behaviour.\r
+*/\r
+\r
+void slang_alloc_free (void *ptr)\r
+{\r
+       _mesa_free (ptr);\r
+}\r
+\r
+void *slang_alloc_malloc (unsigned int size)\r
+{\r
+       return _mesa_malloc (size);\r
+}\r
+\r
+void *slang_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)\r
+{\r
+       return _mesa_realloc (ptr, old_size, size);\r
+}\r
+\r
+int slang_string_compare (const char *str1, const char *str2)\r
+{\r
+       return _mesa_strcmp (str1, str2);\r
+}\r
+\r
+char *slang_string_copy (char *dst, const char *src)\r
+{\r
+       return _mesa_strcpy (dst, src);\r
+}\r
+\r
+char *slang_string_concat (char *dst, const char *src)\r
+{\r
+       return _mesa_strcpy (dst + _mesa_strlen (dst), src);\r
+}\r
+\r
+char *slang_string_duplicate (const char *src)\r
+{\r
+       return _mesa_strdup (src);\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
+static void slang_struct_destruct (slang_struct *);\r
+static int slang_struct_copy (slang_struct *, const slang_struct *);\r
+static int slang_struct_equal (const slang_struct *, const slang_struct *);\r
+static void slang_variable_destruct (slang_variable *);\r
+\r
+/* slang_type_specifier */\r
+\r
+static void slang_type_specifier_construct (slang_type_specifier *spec)\r
+{\r
+       spec->type = slang_spec_void;\r
+       spec->_struct = NULL;\r
+       spec->_array = NULL;\r
+}\r
+\r
+static void slang_type_specifier_destruct (slang_type_specifier *spec)\r
+{\r
+       if (spec->_struct != NULL)\r
+       {\r
+               slang_struct_destruct (spec->_struct);\r
+               slang_alloc_free (spec->_struct);\r
+       }\r
+       if (spec->_array != NULL)\r
+       {\r
+               slang_type_specifier_destruct (spec->_array);\r
+               slang_alloc_free (spec->_array);\r
+       }\r
+}\r
+\r
+static int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y)\r
+{\r
+       slang_type_specifier_destruct (x);\r
+       slang_type_specifier_construct (x);\r
+       x->type = y->type;\r
+       if (x->type == slang_spec_struct)\r
+       {\r
+               x->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
+               slang_struct_construct (x->_struct);\r
+               return slang_struct_copy (x->_struct, y->_struct);\r
+       }\r
+       if (x->type == slang_spec_array)\r
+       {\r
+               x->_array = (slang_type_specifier *) slang_alloc_malloc (sizeof (slang_type_specifier));\r
+               slang_type_specifier_construct (x->_array);\r
+               return slang_type_specifier_copy (x->_array, y->_array);\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y)\r
+{\r
+       if (x->type != y->type)\r
+               return 0;\r
+       if (x->type == slang_spec_struct)\r
+               return slang_struct_equal (x->_struct, y->_struct);\r
+       if (x->type == slang_spec_array)\r
+               return slang_type_specifier_equal (x->_array, y->_array);\r
+       return 1;\r
+}\r
+\r
+/* slang_fully_specified_type */\r
+\r
+static void slang_fully_specified_type_construct (slang_fully_specified_type *type)\r
+{\r
+       type->qualifier = slang_qual_none;\r
+       slang_type_specifier_construct (&type->specifier);\r
+}\r
+\r
+static void slang_fully_specified_type_destruct (slang_fully_specified_type *type)\r
+{\r
+       slang_type_specifier_destruct (&type->specifier);\r
+}\r
+\r
+static int slang_fully_specified_type_copy (slang_fully_specified_type *x,\r
+       const slang_fully_specified_type *y)\r
+{\r
+       slang_fully_specified_type_construct (x);\r
+       slang_fully_specified_type_destruct (x);\r
+       x->qualifier = y->qualifier;\r
+       return slang_type_specifier_copy (&x->specifier, &y->specifier);\r
+}\r
+\r
+/* slang_variable_scope */\r
+\r
+static void slang_variable_scope_construct (slang_variable_scope *scope)\r
+{\r
+       scope->variables = NULL;\r
+       scope->num_variables = 0;\r
+       scope->outer_scope = NULL;\r
+}\r
+\r
+static void slang_variable_scope_destruct (slang_variable_scope *scope)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < scope->num_variables; i++)\r
+               slang_variable_destruct (scope->variables + i);\r
+       slang_alloc_free (scope->variables);\r
+}\r
+\r
+static int slang_variable_scope_copy (slang_variable_scope *x, const slang_variable_scope *y)\r
+{\r
+       unsigned int i;\r
+       slang_variable_scope_destruct (x);\r
+       slang_variable_scope_construct (x);\r
+       x->variables = (slang_variable *) slang_alloc_malloc (y->num_variables * sizeof (\r
+               slang_variable));\r
+       if (x->variables == NULL)\r
+               return 0;\r
+       x->num_variables = y->num_variables;\r
+       for (i = 0; i < x->num_variables; i++)\r
+               slang_variable_construct (x->variables + i);\r
+       for (i = 0; i < x->num_variables; i++)\r
+               if (!slang_variable_copy (x->variables + i, y->variables + i))\r
+                       return 0;\r
+       x->outer_scope = y->outer_scope;\r
+       return 1;\r
+}\r
+\r
+/* slang_operation */\r
+/* XXX mem! */\r
+static void slang_operation_construct (slang_operation *oper)\r
+{\r
+       oper->type = slang_oper_none;\r
+       oper->children = NULL;\r
+       oper->num_children = 0;\r
+       oper->literal = (float) 0;\r
+       oper->identifier = NULL;\r
+       oper->locals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));\r
+       slang_variable_scope_construct (oper->locals);\r
+}\r
+\r
+static void slang_operation_destruct (slang_operation *oper)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < oper->num_children; i++)\r
+               slang_operation_destruct (oper->children + i);\r
+       slang_alloc_free (oper->children);\r
+       slang_alloc_free (oper->identifier);\r
+       slang_variable_scope_destruct (oper->locals);\r
+       slang_alloc_free (oper->locals);\r
+}\r
+\r
+static int slang_operation_copy (slang_operation *x, const slang_operation *y)\r
+{\r
+       unsigned int i;\r
+       slang_operation_destruct (x);\r
+       slang_operation_construct (x);\r
+       x->type = y->type;\r
+       x->children = (slang_operation *) slang_alloc_malloc (y->num_children * sizeof (\r
+               slang_operation));\r
+       if (x->children == NULL)\r
+               return 0;\r
+       x->num_children = y->num_children;\r
+       for (i = 0; i < x->num_children; i++)\r
+               slang_operation_construct (x->children + i);\r
+       for (i = 0; i < x->num_children; i++)\r
+               if (!slang_operation_copy (x->children + i, y->children + i))\r
+                       return 0;\r
+       x->literal = y->literal;\r
+       if (y->identifier != NULL)\r
+       {\r
+               x->identifier = slang_string_duplicate (y->identifier);\r
+               if (x->identifier == NULL)\r
+                       return 0;\r
+       }\r
+       if (!slang_variable_scope_copy (x->locals, y->locals))\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+/* slang_variable */\r
+\r
+static void slang_variable_construct (slang_variable *var)\r
+{\r
+       slang_fully_specified_type_construct (&var->type);\r
+       var->name = NULL;\r
+       var->array_size = NULL;\r
+       var->initializer = NULL;\r
+}\r
+\r
+static void slang_variable_destruct (slang_variable *var)\r
+{\r
+       slang_fully_specified_type_destruct (&var->type);\r
+       slang_alloc_free (var->name);\r
+       if (var->array_size != NULL)\r
+       {\r
+               slang_operation_destruct (var->array_size);\r
+               slang_alloc_free (var->array_size);\r
+       }\r
+       if (var->initializer != NULL)\r
+       {\r
+               slang_operation_destruct (var->initializer);\r
+               slang_alloc_free (var->initializer);\r
+       }\r
+}\r
+\r
+static int slang_variable_copy (slang_variable *x, const slang_variable *y)\r
+{\r
+       slang_variable_destruct (x);\r
+       slang_variable_construct (x);\r
+       if (!slang_fully_specified_type_copy (&x->type, &y->type))\r
+               return 0;\r
+       if (y->name != NULL)\r
+       {\r
+               x->name = slang_string_duplicate (y->name);\r
+               if (x->name == NULL)\r
+                       return 0;\r
+       }\r
+       if (y->array_size != NULL)\r
+               if (!slang_operation_copy (x->array_size, y->array_size))\r
+                       return 0;\r
+       if (y->initializer != NULL)\r
+               if (!slang_operation_copy (x->initializer, y->initializer))\r
+                       return 0;\r
+       return 1;\r
+}\r
+\r
+/* slang_struct_scope */\r
+\r
+static void slang_struct_scope_construct (slang_struct_scope *scope)\r
+{\r
+       scope->structs = NULL;\r
+       scope->num_structs = 0;\r
+       scope->outer_scope = NULL;\r
+}\r
+\r
+static void slang_struct_scope_destruct (slang_struct_scope *scope)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < scope->num_structs; i++)\r
+               slang_struct_destruct (scope->structs + i);\r
+       slang_alloc_free (scope->structs);\r
+}\r
+\r
+static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_scope *y)\r
+{\r
+       unsigned int i;\r
+       slang_struct_scope_destruct (x);\r
+       slang_struct_scope_construct (x);\r
+       x->structs = (slang_struct *) slang_alloc_malloc (y->num_structs * sizeof (slang_struct));\r
+       if (x->structs == NULL)\r
+               return 0;\r
+       x->num_structs = y->num_structs;\r
+       for (i = 0; i < x->num_structs; i++)\r
+               slang_struct_construct (x->structs + i);\r
+       for (i = 0; i < x->num_structs; i++)\r
+               if (!slang_struct_copy (x->structs + i, y->structs + i))\r
+                       return 0;\r
+       x->outer_scope = y->outer_scope;\r
+       return 1;\r
+}\r
+\r
+static slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *name,\r
+       int all_scopes)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < stru->num_structs; i++)\r
+               if (slang_string_compare (name, stru->structs[i].name) == 0)\r
+                       return stru->structs + i;\r
+       if (all_scopes && stru->outer_scope != NULL)\r
+               return slang_struct_scope_find (stru->outer_scope, name, 1);\r
+       return NULL;\r
+}\r
+\r
+/* slang_struct */\r
+/* XXX mem! */\r
+static void slang_struct_construct (slang_struct *stru)\r
+{\r
+       stru->name = NULL;\r
+       stru->fields = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));\r
+       slang_variable_scope_construct (stru->fields);\r
+       stru->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope));\r
+       slang_struct_scope_construct (stru->structs);\r
+}\r
+\r
+static void slang_struct_destruct (slang_struct *stru)\r
+{\r
+       slang_alloc_free (stru->name);\r
+       slang_variable_scope_destruct (stru->fields);\r
+       slang_alloc_free (stru->fields);\r
+       slang_struct_scope_destruct (stru->structs);\r
+       slang_alloc_free (stru->structs);\r
+}\r
+\r
+static int slang_struct_copy (slang_struct *x, const slang_struct *y)\r
+{\r
+       slang_struct_destruct (x);\r
+       slang_struct_construct (x);\r
+       if (y->name != NULL)\r
+       {\r
+               x->name = slang_string_duplicate (y->name);\r
+               if (x->name == NULL)\r
+                       return 0;\r
+       }\r
+       if (!slang_variable_scope_copy (x->fields, y->fields))\r
+               return 0;\r
+       if (!slang_struct_scope_copy (x->structs, y->structs))\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+static int slang_struct_equal (const slang_struct *x, const slang_struct *y)\r
+{\r
+       unsigned int i;\r
+       if (x->fields->num_variables != y->fields->num_variables)\r
+               return 0;\r
+       for (i = 0; i < x->fields->num_variables; i++)\r
+       {\r
+               slang_variable *varx = x->fields->variables + i;\r
+               slang_variable *vary = y->fields->variables + i;\r
+               if (slang_string_compare (varx->name, vary->name) != 0)\r
+                       return 0;\r
+               if (!slang_type_specifier_equal (&varx->type.specifier, &vary->type.specifier))\r
+                       return 0;\r
+               if (varx->type.specifier.type == slang_spec_array)\r
+               {\r
+                       /* TODO compare array sizes */\r
+               }\r
+       }\r
+       return 1;\r
+}\r
+\r
+/* slang_function */\r
+/* XXX mem! */\r
+static void slang_function_construct (slang_function *func)\r
+{\r
+       func->kind = slang_func_ordinary;\r
+       slang_variable_construct (&func->header);\r
+       func->parameters = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));\r
+       slang_variable_scope_construct (func->parameters);\r
+       func->body = NULL;\r
+}\r
+\r
+static void slang_function_destruct (slang_function *func)\r
+{\r
+       slang_variable_destruct (&func->header);\r
+       slang_variable_scope_destruct (func->parameters);\r
+       slang_alloc_free (func->parameters);\r
+       if (func->body != NULL)\r
+       {\r
+               slang_operation_destruct (func->body);\r
+               slang_alloc_free (func->body);\r
+       }\r
+}\r
+\r
+/* slang_function_scope */\r
+\r
+static void slang_function_scope_construct (slang_function_scope *scope)\r
+{\r
+       scope->functions = NULL;\r
+       scope->num_functions = 0;\r
+       scope->outer_scope = NULL;\r
+}\r
+\r
+static void slang_function_scope_destruct (slang_function_scope *scope)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < scope->num_functions; i++)\r
+               slang_function_destruct (scope->functions + i);\r
+       slang_alloc_free (scope->functions);\r
+}\r
+\r
+static slang_function *slang_function_scope_find (slang_function_scope *funcs, slang_function *fun,\r
+       int all_scopes)\r
+{\r
+       unsigned int i;\r
+       for (i = 0; i < funcs->num_functions; i++)\r
+       {\r
+               slang_function *f = funcs->functions + i;\r
+               unsigned int j;\r
+               if (slang_string_compare (fun->header.name, f->header.name) != 0)\r
+                       continue;\r
+               if (fun->param_count != f->param_count)\r
+                       continue;\r
+               for (j = 0; j < fun->param_count; j++)\r
+               {\r
+                       if (!slang_type_specifier_equal (&fun->parameters->variables[j].type.specifier,\r
+                               &f->parameters->variables[j].type.specifier))\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+               if (j == fun->param_count)\r
+                       return f;\r
+       }\r
+       if (all_scopes && funcs->outer_scope != NULL)\r
+               return slang_function_scope_find (funcs->outer_scope, fun, 1);\r
+       return NULL;\r
+}\r
+\r
+/* slang_translation_unit */\r
+/* XXX mem! */\r
+static void slang_translation_unit_construct (slang_translation_unit *unit)\r
+{\r
+       unit->globals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));\r
+       slang_variable_scope_construct (unit->globals);\r
+       slang_function_scope_construct (&unit->functions);\r
+       unit->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope));\r
+       slang_struct_scope_construct (unit->structs);\r
+}\r
+\r
+static void slang_translation_unit_destruct (slang_translation_unit *unit)\r
+{\r
+       slang_variable_scope_destruct (unit->globals);\r
+       slang_alloc_free (unit->globals);\r
+       slang_function_scope_destruct (&unit->functions);\r
+       slang_struct_scope_destruct (unit->structs);\r
+       slang_alloc_free (unit->structs);\r
+}\r
+\r
+static int parse_identifier (const byte **I, char **id)\r
+{\r
+       *id = slang_string_duplicate ((const char *) *I);\r
+       if (*id == NULL)\r
+               return 0;\r
+       *I += strlen ((const char *) *I) + 1;\r
+       return 1;\r
+}\r
+\r
+static int parse_number (const byte **I, int *number)\r
+{\r
+       const int radix = (int) (*(*I)++);\r
+       *number = 0;\r
+       while (**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
+               else\r
+                       digit = (int) (**I - 'a') + 10;\r
+               *number = *number * radix + digit;\r
+               (*I)++;\r
+       }\r
+       (*I)++;\r
+       return 1;\r
+}\r
+\r
+static int parse_float (const byte **I, 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
+               return 0;\r
+\r
+       if (!parse_identifier (I, &fractional))\r
+       {\r
+               slang_alloc_free (integral);\r
+               return 0;\r
+       }\r
+\r
+       if (!parse_identifier (I, &exponent))\r
+       {\r
+               slang_alloc_free (fractional);\r
+               slang_alloc_free (integral);\r
+               return 0;\r
+       }\r
+\r
+       whole = (char *) (slang_alloc_malloc ((strlen (integral) + strlen (fractional) + strlen (\r
+               exponent) + 3) * sizeof (char)));\r
+       if (whole == NULL)\r
+       {\r
+               slang_alloc_free (exponent);\r
+               slang_alloc_free (fractional);\r
+               slang_alloc_free (integral);\r
+               return 0;\r
+       }\r
+\r
+       slang_string_copy (whole, integral);\r
+       slang_string_concat (whole, ".");\r
+       slang_string_concat (whole, fractional);\r
+       slang_string_concat (whole, "E");\r
+       slang_string_concat (whole, exponent);\r
+\r
+       *number = (float) (atof (whole));\r
+\r
+       slang_alloc_free (whole);\r
+       slang_alloc_free (exponent);\r
+       slang_alloc_free (fractional);\r
+       slang_alloc_free (integral);\r
+       return 1;\r
+}\r
+\r
+/* revision number - increment after each change affecting emitted output */\r
+#define REVISION 2\r
+\r
+static int check_revision (const byte **I)\r
+{\r
+       if (**I != REVISION)\r
+               return 0;\r
+       (*I)++;\r
+       return 1;\r
+}\r
+\r
+static int parse_statement (const byte **, slang_operation *, slang_variable_scope *,\r
+       slang_struct_scope *);\r
+static int parse_expression (const byte **, slang_operation *, slang_variable_scope *,\r
+       slang_struct_scope *);\r
+\r
+/* type qualifier */\r
+#define TYPE_QUALIFIER_NONE 0\r
+#define TYPE_QUALIFIER_CONST 1\r
+#define TYPE_QUALIFIER_ATTRIBUTE 2\r
+#define TYPE_QUALIFIER_VARYING 3\r
+#define TYPE_QUALIFIER_UNIFORM 4\r
+#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
+{\r
+       switch (*(*I)++)\r
+       {\r
+       case TYPE_QUALIFIER_NONE:\r
+               *qual = slang_qual_none;\r
+               break;\r
+       case TYPE_QUALIFIER_CONST:\r
+               *qual = slang_qual_const;\r
+               break;\r
+       case TYPE_QUALIFIER_ATTRIBUTE:\r
+               *qual = slang_qual_attribute;\r
+               break;\r
+       case TYPE_QUALIFIER_VARYING:\r
+               *qual = slang_qual_varying;\r
+               break;\r
+       case TYPE_QUALIFIER_UNIFORM:\r
+               *qual = slang_qual_uniform;\r
+               break;\r
+       case TYPE_QUALIFIER_FIXEDOUTPUT:\r
+               *qual = slang_qual_fixedoutput;\r
+               break;\r
+       case TYPE_QUALIFIER_FIXEDINPUT:\r
+               *qual = slang_qual_fixedinput;\r
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+/* type specifier */\r
+#define TYPE_SPECIFIER_VOID 0\r
+#define TYPE_SPECIFIER_BOOL 1\r
+#define TYPE_SPECIFIER_BVEC2 2\r
+#define TYPE_SPECIFIER_BVEC3 3\r
+#define TYPE_SPECIFIER_BVEC4 4\r
+#define TYPE_SPECIFIER_INT 5\r
+#define TYPE_SPECIFIER_IVEC2 6\r
+#define TYPE_SPECIFIER_IVEC3 7\r
+#define TYPE_SPECIFIER_IVEC4 8\r
+#define TYPE_SPECIFIER_FLOAT 9\r
+#define TYPE_SPECIFIER_VEC2 10\r
+#define TYPE_SPECIFIER_VEC3 11\r
+#define TYPE_SPECIFIER_VEC4 12\r
+#define TYPE_SPECIFIER_MAT2 13\r
+#define TYPE_SPECIFIER_MAT3 14\r
+#define TYPE_SPECIFIER_MAT4 15\r
+#define TYPE_SPECIFIER_SAMPLER1D 16\r
+#define TYPE_SPECIFIER_SAMPLER2D 17\r
+#define TYPE_SPECIFIER_SAMPLER3D 18\r
+#define TYPE_SPECIFIER_SAMPLERCUBE 19\r
+#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20\r
+#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21\r
+#define TYPE_SPECIFIER_STRUCT 22\r
+#define TYPE_SPECIFIER_TYPENAME 23\r
+\r
+/* structure field */\r
+#define FIELD_NONE 0\r
+#define FIELD_NEXT 1\r
+#define FIELD_ARRAY 2\r
+\r
+static int parse_type_specifier (const byte **I, slang_type_specifier *spec,\r
+       slang_struct_scope *structs, slang_variable_scope *scope)\r
+{\r
+       switch (*(*I)++)\r
+       {\r
+       case TYPE_SPECIFIER_VOID:\r
+               spec->type = slang_spec_void;\r
+               break;\r
+       case TYPE_SPECIFIER_BOOL:\r
+               spec->type = slang_spec_bool;\r
+               break;\r
+       case TYPE_SPECIFIER_BVEC2:\r
+               spec->type = slang_spec_bvec2;\r
+               break;\r
+       case TYPE_SPECIFIER_BVEC3:\r
+               spec->type = slang_spec_bvec3;\r
+               break;\r
+       case TYPE_SPECIFIER_BVEC4:\r
+               spec->type = slang_spec_bvec4;\r
+               break;\r
+       case TYPE_SPECIFIER_INT:\r
+               spec->type = slang_spec_int;\r
+               break;\r
+       case TYPE_SPECIFIER_IVEC2:\r
+               spec->type = slang_spec_ivec2;\r
+               break;\r
+       case TYPE_SPECIFIER_IVEC3:\r
+               spec->type = slang_spec_ivec3;\r
+               break;\r
+       case TYPE_SPECIFIER_IVEC4:\r
+               spec->type = slang_spec_ivec4;\r
+               break;\r
+       case TYPE_SPECIFIER_FLOAT:\r
+               spec->type = slang_spec_float;\r
+               break;\r
+       case TYPE_SPECIFIER_VEC2:\r
+               spec->type = slang_spec_vec2;\r
+               break;\r
+       case TYPE_SPECIFIER_VEC3:\r
+               spec->type = slang_spec_vec3;\r
+               break;\r
+       case TYPE_SPECIFIER_VEC4:\r
+               spec->type = slang_spec_vec4;\r
+               break;\r
+       case TYPE_SPECIFIER_MAT2:\r
+               spec->type = slang_spec_mat2;\r
+               break;\r
+       case TYPE_SPECIFIER_MAT3:\r
+               spec->type = slang_spec_mat3;\r
+               break;\r
+       case TYPE_SPECIFIER_MAT4:\r
+               spec->type = slang_spec_mat4;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLER1D:\r
+               spec->type = slang_spec_sampler1D;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLER2D:\r
+               spec->type = slang_spec_sampler2D;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLER3D:\r
+               spec->type = slang_spec_sampler3D;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLERCUBE:\r
+               spec->type = slang_spec_samplerCube;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLER1DSHADOW:\r
+               spec->type = slang_spec_sampler1DShadow;\r
+               break;\r
+       case TYPE_SPECIFIER_SAMPLER2DSHADOW:\r
+               spec->type = slang_spec_sampler2DShadow;\r
+               break;\r
+       case TYPE_SPECIFIER_STRUCT:\r
+               spec->type = slang_spec_struct;\r
+               {\r
+                       char *name;\r
+                       if (!parse_identifier (I, &name))\r
+                               return 0;\r
+                       if (*name != '\0' && slang_struct_scope_find (structs, name, 0) != NULL)\r
+                       {\r
+                               slang_alloc_free (name);\r
+                               return 0;               /* error: duplicate names */\r
+                       }\r
+                       spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
+                       if (spec->_struct == NULL)\r
+                       {\r
+                               slang_alloc_free (name);\r
+                               return 0;\r
+                       }\r
+                       slang_struct_construct (spec->_struct);\r
+                       spec->_struct->name = name;\r
+                       spec->_struct->structs->outer_scope = structs;\r
+               }\r
+               do\r
+               {\r
+                       slang_type_specifier sp;\r
+                       slang_type_specifier_construct (&sp);\r
+                       if (!parse_type_specifier (I, &sp, spec->_struct->structs, scope))\r
+                       {\r
+                               slang_type_specifier_destruct (&sp);\r
+                               return 0;\r
+                       }\r
+                       do\r
+                       {\r
+                               slang_variable *var;\r
+                               spec->_struct->fields->variables = (slang_variable *) slang_alloc_realloc (\r
+                                       spec->_struct->fields->variables,\r
+                                       spec->_struct->fields->num_variables * sizeof (slang_variable),\r
+                                       (spec->_struct->fields->num_variables + 1) * sizeof (slang_variable));\r
+                               if (spec->_struct->fields->variables == NULL)\r
+                               {\r
+                                       slang_type_specifier_destruct (&sp);\r
+                                       return 0;\r
+                               }\r
+                               var = spec->_struct->fields->variables + spec->_struct->fields->num_variables;\r
+                               spec->_struct->fields->num_variables++;\r
+                               slang_variable_construct (var);\r
+                               if (!slang_type_specifier_copy (&var->type.specifier, &sp))\r
+                               {\r
+                                       slang_type_specifier_destruct (&sp);\r
+                                       return 0;\r
+                               }\r
+                               if (!parse_identifier (I, &var->name))\r
+                               {\r
+                                       slang_type_specifier_destruct (&sp);\r
+                                       return 0;\r
+                               }\r
+                               switch (*(*I)++)\r
+                               {\r
+                               case FIELD_NONE:\r
+                                       break;\r
+                               case FIELD_ARRAY:\r
+                                       var->array_size = (slang_operation *) slang_alloc_malloc (sizeof (\r
+                                               slang_operation));\r
+                                       if (var->array_size == NULL)\r
+                                       {\r
+                                               slang_type_specifier_destruct (&sp);\r
+                                               return 0;\r
+                                       }\r
+                                       slang_operation_construct (var->array_size);\r
+                                       if (!parse_expression (I, 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
+               }\r
+               while (*(*I)++ != FIELD_NONE);\r
+               if (*spec->_struct->name != '\0')\r
+               {\r
+                       slang_struct *s;\r
+                       structs->structs = (slang_struct *) slang_alloc_realloc (structs->structs,\r
+                               structs->num_structs * sizeof (slang_struct),\r
+                               (structs->num_structs + 1) * sizeof (slang_struct));\r
+                       if (structs->structs == NULL)\r
+                               return 0;\r
+                       s = structs->structs + structs->num_structs;\r
+                       structs->num_structs++;\r
+                       slang_struct_construct (s);\r
+                       if (!slang_struct_copy (s, spec->_struct))\r
+                               return 0;\r
+               }\r
+               break;\r
+       case TYPE_SPECIFIER_TYPENAME:\r
+               spec->type = slang_spec_struct;\r
+               {\r
+                       char *name;\r
+                       slang_struct *stru;\r
+                       if (!parse_identifier (I, &name))\r
+                               return 0;\r
+                       stru = slang_struct_scope_find (structs, name, 1);\r
+                       slang_alloc_free (name);\r
+                       if (stru == NULL)\r
+                               return 0;\r
+                       spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));\r
+                       if (spec->_struct == NULL)\r
+                               return 0;\r
+                       slang_struct_construct (spec->_struct);\r
+                       if (!slang_struct_copy (spec->_struct, stru))\r
+                               return 0;\r
+               }\r
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int parse_fully_specified_type (const byte **I, slang_fully_specified_type *type,\r
+       slang_struct_scope *structs, slang_variable_scope *scope)\r
+{\r
+       if (!parse_type_qualifier (I, &type->qualifier))\r
+               return 0;\r
+       return parse_type_specifier (I, &type->specifier, structs, scope);\r
+}\r
+\r
+/* operation */\r
+#define OP_END 0\r
+#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1\r
+#define OP_BLOCK_BEGIN_NEW_SCOPE 2\r
+#define OP_DECLARE 3\r
+#define OP_ASM 4\r
+#define OP_BREAK 5\r
+#define OP_CONTINUE 6\r
+#define OP_DISCARD 7\r
+#define OP_RETURN 8\r
+#define OP_EXPRESSION 9\r
+#define OP_IF 10\r
+#define OP_WHILE 11\r
+#define OP_DO 12\r
+#define OP_FOR 13\r
+#define OP_PUSH_VOID 14\r
+#define OP_PUSH_BOOL 15\r
+#define OP_PUSH_INT 16\r
+#define OP_PUSH_FLOAT 17\r
+#define OP_PUSH_IDENTIFIER 18\r
+#define OP_SEQUENCE 19\r
+#define OP_ASSIGN 20\r
+#define OP_ADDASSIGN 21\r
+#define OP_SUBASSIGN 22\r
+#define OP_MULASSIGN 23\r
+#define OP_DIVASSIGN 24\r
+/*#define OP_MODASSIGN 25*/\r
+/*#define OP_LSHASSIGN 26*/\r
+/*#define OP_RSHASSIGN 27*/\r
+/*#define OP_ORASSIGN 28*/\r
+/*#define OP_XORASSIGN 29*/\r
+/*#define OP_ANDASSIGN 30*/\r
+#define OP_SELECT 31\r
+#define OP_LOGICALOR 32\r
+#define OP_LOGICALXOR 33\r
+#define OP_LOGICALAND 34\r
+/*#define OP_BITOR 35*/\r
+/*#define OP_BITXOR 36*/\r
+/*#define OP_BITAND 37*/\r
+#define OP_EQUAL 38\r
+#define OP_NOTEQUAL 39\r
+#define OP_LESS 40\r
+#define OP_GREATER 41\r
+#define OP_LESSEQUAL 42\r
+#define OP_GREATEREQUAL 43\r
+/*#define OP_LSHIFT 44*/\r
+/*#define OP_RSHIFT 45*/\r
+#define OP_ADD 46\r
+#define OP_SUBTRACT 47\r
+#define OP_MULTIPLY 48\r
+#define OP_DIVIDE 49\r
+/*#define OP_MODULUS 50*/\r
+#define OP_PREINCREMENT 51\r
+#define OP_PREDECREMENT 52\r
+#define OP_PLUS 53\r
+#define OP_MINUS 54\r
+/*#define OP_COMPLEMENT 55*/\r
+#define OP_NOT 56\r
+#define OP_SUBSCRIPT 57\r
+#define OP_CALL 58\r
+#define OP_FIELD 59\r
+#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
+       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
+               return 0;\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
+}\r
+\r
+static int parse_declaration (const byte **, 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
+       slang_struct_scope *structs)\r
+{\r
+       oper->locals->outer_scope = scope;\r
+       switch (*(*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
+                               return 0;\r
+               (*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
+                               return 0;\r
+               (*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
+                               return 0;\r
+                       if (first_var < scope->num_variables)\r
+                       {\r
+                               const unsigned int num_vars = scope->num_variables - first_var;\r
+                               unsigned int i;\r
+                               oper->children = (slang_operation *) slang_alloc_malloc (num_vars * sizeof (\r
+                                       slang_operation));\r
+                               if (oper->children == NULL)\r
+                                       return 0;\r
+                               for (i = 0; i < num_vars; i++)\r
+                                       slang_operation_construct (oper->children + i);\r
+                               oper->num_children = num_vars;\r
+                               for (i = first_var; i < scope->num_variables; i++)\r
+                               {\r
+                                       slang_operation *o = oper->children + i - first_var;\r
+                                       o->type = slang_oper_identifier;\r
+                                       o->locals->outer_scope = scope;\r
+                                       o->identifier = slang_string_duplicate (scope->variables[i].name);\r
+                                       if (o->identifier == NULL)\r
+                                               return 0;\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       case OP_ASM:\r
+               oper->type = slang_oper_asm;\r
+               if (!parse_identifier (I, &oper->identifier))\r
+                       return 0;\r
+               while (**I != OP_END)\r
+                       if (!parse_child_operation (I, oper, 0, scope, structs))\r
+                               return 0;\r
+               (*I)++;\r
+               break;\r
+       case OP_BREAK:\r
+               oper->type = slang_oper_break;\r
+               break;\r
+       case OP_CONTINUE:\r
+               oper->type = slang_oper_continue;\r
+               break;\r
+       case OP_DISCARD:\r
+               oper->type = slang_oper_discard;\r
+               break;\r
+       case OP_RETURN:\r
+               oper->type = slang_oper_return;\r
+               if (!parse_child_operation (I, 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
+                       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
+                       return 0;\r
+               if (!parse_child_operation (I, oper, 1, scope, structs))\r
+                       return 0;\r
+               if (!parse_child_operation (I, 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
+                       return 0;\r
+               if (!parse_child_operation (I, 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
+                       return 0;\r
+               if (!parse_child_operation (I, 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
+                       return 0;\r
+               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+                       return 0;\r
+               if (!parse_child_operation (I, oper, 0, oper->locals, structs))\r
+                       return 0;\r
+               if (!parse_child_operation (I, oper, 1, oper->locals, structs))\r
+                       return 0;\r
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int handle_trinary_expression (slang_operation *op, slang_operation **ops,\r
+       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
+               return 0;\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
+       (*ops)[*num_ops - 4] = (*ops)[*num_ops - 1];\r
+       *num_ops -= 3;\r
+       *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 3) * sizeof (slang_operation),\r
+               *num_ops * sizeof (slang_operation));\r
+       if (*ops == NULL)\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+static int handle_binary_expression (slang_operation *op, slang_operation **ops,\r
+       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
+               return 0;\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
+       *num_ops -= 2;\r
+       *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 2) * sizeof (slang_operation),\r
+               *num_ops * sizeof (slang_operation));\r
+       if (*ops == NULL)\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+static int handle_unary_expression (slang_operation *op, slang_operation **ops, \r
+       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
+               return 0;\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
+               return 0;\r
+       return 1;\r
+}\r
+\r
+static int parse_expression (const byte **I, 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
+       {\r
+               slang_operation *op;\r
+               const unsigned int op_code = *(*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
+                       return 0;\r
+               op = ops + num_ops;\r
+               num_ops++;\r
+               slang_operation_construct (op);\r
+               op->locals->outer_scope = scope;\r
+               switch (op_code)\r
+               {\r
+               case OP_PUSH_VOID:\r
+                       op->type = slang_oper_void;\r
+                       break;\r
+               case OP_PUSH_BOOL:\r
+                       op->type = slang_oper_literal_bool;\r
+                       if (!parse_number (I, &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
+                               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
+                               return 0;\r
+                       break;\r
+               case OP_PUSH_IDENTIFIER:\r
+                       op->type = slang_oper_identifier;\r
+                       if (!parse_identifier (I, &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
+                               return 0;\r
+                       break;\r
+               case OP_ASSIGN:\r
+                       op->type = slang_oper_assign;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_SUBASSIGN:\r
+                       op->type = slang_oper_subassign;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_DIVASSIGN:\r
+                       op->type = slang_oper_divassign;\r
+                       if (!handle_binary_expression (op, &ops, &num_ops))\r
+                               return 0;\r
+                       break;\r
+               /*case OP_MODASSIGN:*/\r
+               /*case OP_LSHASSIGN:*/\r
+               /*case OP_RSHASSIGN:*/\r
+               /*case OP_ORASSIGN:*/\r
+               /*case OP_XORASSIGN:*/\r
+               /*case OP_ANDASSIGN:*/\r
+               case OP_SELECT:\r
+                       op->type = slang_oper_select;\r
+                       if (!handle_trinary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_LOGICALXOR:\r
+                       op->type = slang_oper_logicalxor;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               /*case OP_BITOR:*/\r
+               /*case OP_BITXOR:*/\r
+               /*case OP_BITAND:*/\r
+               case OP_EQUAL:\r
+                       op->type = slang_oper_equal;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_LESS:\r
+                       op->type = slang_oper_less;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_LESSEQUAL:\r
+                       op->type = slang_oper_lessequal;\r
+                       if (!handle_binary_expression (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
+                               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
+                               return 0;\r
+                       break;\r
+               case OP_SUBTRACT:\r
+                       op->type = slang_oper_subtract;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_DIVIDE:\r
+                       op->type = slang_oper_divide;\r
+                       if (!handle_binary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_PREDECREMENT:\r
+                       op->type = slang_oper_predecrement;\r
+                       if (!handle_unary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_MINUS:\r
+                       op->type = slang_oper_minus;\r
+                       if (!handle_unary_expression (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
+                               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
+                               return 0;\r
+                       break;\r
+               case OP_CALL:\r
+                       op->type = slang_oper_call;\r
+                       if (!parse_identifier (I, &op->identifier))\r
+                               return 0;\r
+                       while (**I != OP_END)\r
+                               if (!parse_child_operation (I, op, 0, scope, structs))\r
+                                       return 0;\r
+                       (*I)++;\r
+                       break;\r
+               case OP_FIELD:\r
+                       op->type = slang_oper_field;\r
+                       if (!parse_identifier (I, &op->identifier))\r
+                               return 0;\r
+                       if (!handle_unary_expression (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
+                               return 0;\r
+                       break;\r
+               case OP_POSTDECREMENT:\r
+                       op->type = slang_oper_postdecrement;\r
+                       if (!handle_unary_expression (op, &ops, &num_ops))\r
+                               return 0;\r
+                       break;\r
+               default:\r
+                       return 0;\r
+               }\r
+       }\r
+       (*I)++;\r
+       *oper = *ops;\r
+       slang_alloc_free (ops);\r
+       return 1;\r
+}\r
+\r
+/* parameter qualifier */\r
+#define PARAM_QUALIFIER_IN 0\r
+#define PARAM_QUALIFIER_OUT 1\r
+#define PARAM_QUALIFIER_INOUT 2\r
+\r
+/* function parameter array presence */\r
+#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
+       slang_struct_scope *structs, slang_variable_scope *scope)\r
+{\r
+       if (!parse_type_qualifier (I, &param->type.qualifier))\r
+               return 0;\r
+       switch (*(*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
+               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
+               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
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       if (!parse_type_specifier (I, &param->type.specifier, structs, scope))\r
+               return 0;\r
+       if (!parse_identifier (I, &param->name))\r
+               return 0;\r
+       if (*(*I)++ == PARAMETER_ARRAY_PRESENT)\r
+       {\r
+               param->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+               slang_operation_construct (param->array_size);\r
+               if (!parse_expression (I, param->array_size, scope, structs))\r
+                       return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+/* function type */\r
+#define FUNCTION_ORDINARY 0\r
+#define FUNCTION_CONSTRUCTOR 1\r
+#define FUNCTION_OPERATOR 2\r
+\r
+/* function parameter */\r
+#define PARAMETER_NONE 0\r
+#define PARAMETER_NEXT 1\r
+\r
+/* operator type */\r
+#define OPERATOR_ASSIGN 1\r
+#define OPERATOR_ADDASSIGN 2\r
+#define OPERATOR_SUBASSIGN 3\r
+#define OPERATOR_MULASSIGN 4\r
+#define OPERATOR_DIVASSIGN 5\r
+/*#define OPERATOR_MODASSIGN 6*/\r
+/*#define OPERATOR_LSHASSIGN 7*/\r
+/*#define OPERATOR_RSHASSIGN 8*/\r
+/*#define OPERATOR_ANDASSIGN 9*/\r
+/*#define OPERATOR_XORASSIGN 10*/\r
+/*#define OPERATOR_ORASSIGN 11*/\r
+#define OPERATOR_LOGICALXOR 12\r
+/*#define OPERATOR_BITOR 13*/\r
+/*#define OPERATOR_BITXOR 14*/\r
+/*#define OPERATOR_BITAND 15*/\r
+#define OPERATOR_EQUAL 16\r
+#define OPERATOR_NOTEQUAL 17\r
+#define OPERATOR_LESS 18\r
+#define OPERATOR_GREATER 19\r
+#define OPERATOR_LESSEQUAL 20\r
+#define OPERATOR_GREATEREQUAL 21\r
+/*#define OPERATOR_LSHIFT 22*/\r
+/*#define OPERATOR_RSHIFT 23*/\r
+#define OPERATOR_MULTIPLY 24\r
+#define OPERATOR_DIVIDE 25\r
+/*#define OPERATOR_MODULUS 26*/\r
+#define OPERATOR_INCREMENT 27\r
+#define OPERATOR_DECREMENT 28\r
+#define OPERATOR_PLUS 29\r
+#define OPERATOR_MINUS 30\r
+/*#define OPERATOR_COMPLEMENT 31*/\r
+#define OPERATOR_NOT 32\r
+\r
+/* these must match with slang_type_specifier_type enum */\r
+static const char *type_specifier_names[] = {\r
+       "void",\r
+       "bool",\r
+       "bvec2",\r
+       "bvec3",\r
+       "bvec4",\r
+       "int",\r
+       "ivec2",\r
+       "ivec3",\r
+       "ivec4",\r
+       "float",\r
+       "vec2",\r
+       "vec3",\r
+       "vec4",\r
+       "mat2",\r
+       "mat3",\r
+       "mat4",\r
+       "sampler1D",\r
+       "sampler2D",\r
+       "sampler3D",\r
+       "samplerCube",\r
+       "sampler1DShadow",\r
+       "sampler2DShadow"\r
+};\r
+\r
+static const struct {\r
+       unsigned int o_code;\r
+       const char *o_name;\r
+} operator_names[] = {\r
+       { OPERATOR_INCREMENT, "++" },\r
+       { OPERATOR_ADDASSIGN, "+=" },\r
+       { OPERATOR_PLUS, "+" },\r
+       { OPERATOR_DECREMENT, "--" },\r
+       { OPERATOR_SUBASSIGN, "-=" },\r
+       { OPERATOR_MINUS, "-" },\r
+       { OPERATOR_NOTEQUAL, "!=" },\r
+       { OPERATOR_NOT, "!" },\r
+       { OPERATOR_MULASSIGN, "*=" },\r
+       { OPERATOR_MULTIPLY, "*" },\r
+       { OPERATOR_DIVASSIGN, "/=" },\r
+       { OPERATOR_DIVIDE, "/" },\r
+       { OPERATOR_LESSEQUAL, "<=" },\r
+       /*{ OPERATOR_LSHASSIGN, "<<=" },*/\r
+       /*{ OPERATOR_LSHIFT, "<<" },*/\r
+       { OPERATOR_LESS, "<" },\r
+       { OPERATOR_GREATEREQUAL, ">=" },\r
+       /*{ OPERATOR_RSHASSIGN, ">>=" },*/\r
+       /*{ OPERATOR_RSHIFT, ">>" },*/\r
+       { OPERATOR_GREATER, ">" },\r
+       { OPERATOR_EQUAL, "==" },\r
+       { OPERATOR_ASSIGN, "=" },\r
+       /*{ OPERATOR_MODASSIGN, "%=" },*/\r
+       /*{ OPERATOR_MODULUS, "%" },*/\r
+       /*{ OPERATOR_ANDASSIGN, "&=" },*/\r
+       /*{ OPERATOR_BITAND, "&" },*/\r
+       /*{ OPERATOR_ORASSIGN, "|=" },*/\r
+       /*{ OPERATOR_BITOR, "|" },*/\r
+       /*{ OPERATOR_COMPLEMENT, "~" },*/\r
+       /*{ OPERATOR_XORASSIGN, "^=" },*/\r
+       { OPERATOR_LOGICALXOR, "^^" }/*,*/\r
+       /*{ OPERATOR_BITXOR, "^" }*/\r
+};\r
+\r
+static int parse_operator_name (const byte **I, 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
+               {\r
+                       *pname = slang_string_duplicate (operator_names[i].o_name);\r
+                       if (*pname == NULL)\r
+                               return 0;\r
+                       (*I)++;\r
+                       return 1;\r
+               }\r
+       return 0;\r
+}\r
+\r
+static int parse_function_prototype (const byte **I, 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
+               return 0;\r
+       switch (*(*I)++)\r
+       {\r
+       case FUNCTION_ORDINARY:\r
+               func->kind = slang_func_ordinary;\r
+               if (!parse_identifier (I, &func->header.name))\r
+                       return 0;\r
+               break;\r
+       case FUNCTION_CONSTRUCTOR:\r
+               func->kind = slang_func_constructor;\r
+               if (func->header.type.specifier.type == slang_spec_struct)\r
+                       return 0;\r
+               func->header.name = slang_string_duplicate (\r
+                       type_specifier_names[func->header.type.specifier.type]);\r
+               if (func->header.name == NULL)\r
+                       return 0;\r
+               break;\r
+       case FUNCTION_OPERATOR:\r
+               func->kind = slang_func_operator;\r
+               if (!parse_operator_name (I, &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
+       {\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
+                       return 0;\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
+                       func->parameters->num_variables - 1, structs, scope))\r
+                       return 0;\r
+       }\r
+       func->param_count = func->parameters->num_variables;\r
+       return 1;\r
+}\r
+\r
+static int parse_function_definition (const byte **I, slang_function *func,\r
+       slang_struct_scope *structs, slang_variable_scope *scope)\r
+{\r
+       if (!parse_function_prototype (I, func, structs, scope))\r
+               return 0;\r
+       func->body = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+       if (func->body == NULL)\r
+               return 0;\r
+       slang_operation_construct (func->body);\r
+       if (!parse_statement (I, func->body, func->parameters, structs))\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+/* init declarator list */\r
+#define DECLARATOR_NONE 0\r
+#define DECLARATOR_NEXT 1\r
+\r
+/* variable declaration */\r
+#define VARIABLE_NONE 0\r
+#define VARIABLE_IDENTIFIER 1\r
+#define VARIABLE_INITIALIZER 2\r
+#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
+       slang_variable_scope *vars, slang_struct_scope *structs)\r
+{\r
+       slang_variable *var;\r
+\r
+       if (*(*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
+               return 0;\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
+               return 0;\r
+       switch (*(*I)++)\r
+       {\r
+       case VARIABLE_NONE:\r
+               if (!slang_type_specifier_copy (&var->type.specifier, &type->specifier))\r
+                       return 0;\r
+               break;\r
+       case VARIABLE_INITIALIZER:\r
+               if (!slang_type_specifier_copy (&var->type.specifier, &type->specifier))\r
+                       return 0;\r
+               var->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));\r
+               if (var->initializer == NULL)\r
+                       return 0;\r
+               slang_operation_construct (var->initializer);\r
+               if (!parse_expression (I, var->initializer, vars, structs))\r
+                       return 0;\r
+               break;\r
+       case VARIABLE_ARRAY_UNKNOWN:\r
+               var->type.specifier.type = slang_spec_array;\r
+               var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof (\r
+                       slang_type_specifier));\r
+               if (var->type.specifier._array == NULL)\r
+                       return 0;\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
+               break;\r
+       case VARIABLE_ARRAY_EXPLICIT:\r
+               var->type.specifier.type = slang_spec_array;\r
+               var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof (\r
+                       slang_type_specifier));\r
+               if (var->type.specifier._array == NULL)\r
+                       return 0;\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
+                       return 0;\r
+               slang_operation_construct (var->array_size);\r
+               if (!parse_expression (I, var->array_size, vars, structs))\r
+                       return 0;\r
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int parse_init_declarator_list (const byte **I, 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
+       {\r
+               slang_fully_specified_type_destruct (&type);\r
+               return 0;\r
+       }\r
+       do\r
+       {\r
+               if (!parse_init_declarator (I, &type, vars, structs))\r
+               {\r
+                       slang_fully_specified_type_destruct (&type);\r
+                       return 0;\r
+               }\r
+       }\r
+       while (*(*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
+       slang_function_scope *funcs, slang_variable_scope *scope)\r
+{\r
+       slang_function parsed_func, *found_func;\r
+\r
+       slang_function_construct (&parsed_func);\r
+       if (definition)\r
+       {\r
+               if (!parse_function_definition (I, &parsed_func, structs, scope))\r
+               {\r
+                       slang_function_destruct (&parsed_func);\r
+                       return 0;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (!parse_function_prototype (I, &parsed_func, structs, scope))\r
+               {\r
+                       slang_function_destruct (&parsed_func);\r
+                       return 0;\r
+               }\r
+       }\r
+       found_func = slang_function_scope_find (funcs, &parsed_func, 0);\r
+       if (found_func == NULL)\r
+       {\r
+               funcs->functions = (slang_function *) slang_alloc_realloc (funcs->functions,\r
+                       funcs->num_functions * sizeof (slang_function), (funcs->num_functions + 1) * sizeof (\r
+                       slang_function));\r
+               if (funcs->functions == NULL)\r
+               {\r
+                       slang_function_destruct (&parsed_func);\r
+                       return 0;\r
+               }\r
+               funcs->functions[funcs->num_functions] = parsed_func;\r
+               funcs->num_functions++;\r
+       }\r
+       else\r
+       {\r
+               /* TODO check function return type qualifiers and specifiers */\r
+               if (definition)\r
+               {\r
+                       if (found_func->body != NULL)\r
+                       {\r
+                               slang_function_destruct (&parsed_func);\r
+                               return 0;               /* error: second definition */\r
+                       }\r
+                       slang_function_destruct (found_func);\r
+                       *found_func = parsed_func;\r
+               }\r
+               else\r
+               {\r
+                       slang_function_destruct (&parsed_func);\r
+               }\r
+       }\r
+       return 1;\r
+}\r
+\r
+/* declaration */\r
+#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
+       slang_struct_scope *structs, slang_function_scope *funcs)\r
+{\r
+       switch (*(*I)++)\r
+       {\r
+       case DECLARATION_INIT_DECLARATOR_LIST:\r
+               if (!parse_init_declarator_list (I, scope, structs))\r
+                       return 0;\r
+               break;\r
+       case DECLARATION_FUNCTION_PROTOTYPE:\r
+               if (!parse_function (I, 0, structs, funcs, scope))\r
+                       return 0;\r
+               break;\r
+       default:\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
+\r
+/* external declaration */\r
+#define EXTERNAL_NULL 0\r
+#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
+{\r
+       while (**I != EXTERNAL_NULL)\r
+       {\r
+               switch (*(*I)++)\r
+               {\r
+               case EXTERNAL_FUNCTION_DEFINITION:\r
+                       if (!parse_function (I, 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
+                               return 0;\r
+                       break;\r
+               default:\r
+                       return 0;\r
+               }\r
+       }\r
+       (*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
+{\r
+       byte *prod, *I;\r
+       unsigned int size;\r
+\r
+       slang_translation_unit_construct (unit);\r
+       unit->type = type;\r
+       if (!grammar_fast_check (id, (const byte *) source, &prod, &size, 65536))\r
+               return 0;\r
+       I = prod;\r
+       if (!check_revision (&I))\r
+       {\r
+               grammar_alloc_free (prod);\r
+               return 0;\r
+       }\r
+       if (!parse_translation_unit (&I, unit))\r
+       {\r
+               slang_translation_unit_destruct (unit);\r
+               grammar_alloc_free (prod);\r
+               return 0;\r
+       }\r
+       grammar_alloc_free (prod);\r
+       return 1;\r
+}\r
+\r
+static const char *slang_shader_syn =\r
+#include "library/slang_shader_syn.h"\r
+;\r
+\r
+int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit_type type)\r
+{\r
+       grammar id;\r
+\r
+       id = grammar_load_from_text ((const byte *) slang_shader_syn);\r
+       if (id == 0)\r
+               return 0;\r
+\r
+       grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1);\r
+       if (type == slang_unit_fragment_shader)\r
+               grammar_set_reg8 (id, (const byte *) "shader_type", 1);\r
+       else\r
+               grammar_set_reg8 (id, (const byte *) "shader_type", 2);\r
+\r
+       if (!compile_with_grammar (id, source, unit, type))\r
+       {\r
+               grammar_destroy (id);\r
+               return 0;\r
+       }\r
+\r
+       grammar_destroy (id);\r
+       return 1;\r
+}\r
+\r
diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h
new file mode 100644 (file)
index 0000000..0f49df7
--- /dev/null
@@ -0,0 +1,235 @@
+/*\r
+ * Mesa 3-D graphics library\r
+ * Version:  6.3\r
+ *\r
+ * Copyright (C) 2005  Brian Paul   All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a\r
+ * copy of this software and associated documentation files (the "Software"),\r
+ * to deal in the Software without restriction, including without limitation\r
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+ * and/or sell copies of the Software, and to permit persons to whom the\r
+ * Software is furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included\r
+ * in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ */\r
+\r
+#if !defined SLANG_COMPILE_H\r
+#define SLANG_COMPILE_H\r
+\r
+#if defined __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef enum slang_type_qualifier_\r
+{\r
+       slang_qual_none,\r
+       slang_qual_const,\r
+       slang_qual_attribute,\r
+       slang_qual_varying,\r
+       slang_qual_uniform,\r
+       slang_qual_out,\r
+       slang_qual_inout,\r
+       slang_qual_fixedoutput, /* internal */\r
+       slang_qual_fixedinput   /* internal */\r
+} slang_type_qualifier;\r
+\r
+typedef enum slang_type_specifier_type_\r
+{\r
+       slang_spec_void,\r
+       slang_spec_bool,\r
+       slang_spec_bvec2,\r
+       slang_spec_bvec3,\r
+       slang_spec_bvec4,\r
+       slang_spec_int,\r
+       slang_spec_ivec2,\r
+       slang_spec_ivec3,\r
+       slang_spec_ivec4,\r
+       slang_spec_float,\r
+       slang_spec_vec2,\r
+       slang_spec_vec3,\r
+       slang_spec_vec4,\r
+       slang_spec_mat2,\r
+       slang_spec_mat3,\r
+       slang_spec_mat4,\r
+       slang_spec_sampler1D,\r
+       slang_spec_sampler2D,\r
+       slang_spec_sampler3D,\r
+       slang_spec_samplerCube,\r
+       slang_spec_sampler1DShadow,\r
+       slang_spec_sampler2DShadow,\r
+       slang_spec_struct,\r
+       slang_spec_array\r
+} slang_type_specifier_type;\r
+\r
+typedef struct slang_type_specifier_\r
+{\r
+       slang_type_specifier_type type;\r
+       struct slang_struct_ *_struct;          /* spec_struct */\r
+       struct slang_type_specifier_ *_array;   /* spec_array */\r
+} slang_type_specifier;\r
+\r
+typedef struct slang_fully_specified_type_\r
+{\r
+       slang_type_qualifier qualifier;\r
+       slang_type_specifier specifier;\r
+} slang_fully_specified_type;\r
+\r
+typedef struct slang_variable_scope_\r
+{\r
+       struct slang_variable_ *variables;\r
+       unsigned int num_variables;\r
+       struct slang_variable_scope_ *outer_scope;\r
+} slang_variable_scope;\r
+\r
+typedef enum slang_operation_type_\r
+{\r
+       slang_oper_none,\r
+       slang_oper_block_no_new_scope,\r
+       slang_oper_block_new_scope,\r
+       slang_oper_variable_decl,\r
+       slang_oper_asm,\r
+       slang_oper_break,\r
+       slang_oper_continue,\r
+       slang_oper_discard,\r
+       slang_oper_return,\r
+       slang_oper_expression,\r
+       slang_oper_if,\r
+       slang_oper_while,\r
+       slang_oper_do,\r
+       slang_oper_for,\r
+       slang_oper_void,\r
+       slang_oper_literal_bool,\r
+       slang_oper_literal_int,\r
+       slang_oper_literal_float,\r
+       slang_oper_identifier,\r
+       slang_oper_sequence,\r
+       slang_oper_assign,\r
+       slang_oper_addassign,\r
+       slang_oper_subassign,\r
+       slang_oper_mulassign,\r
+       slang_oper_divassign,\r
+       /*slang_oper_modassign,*/\r
+       /*slang_oper_lshassign,*/\r
+       /*slang_oper_rshassign,*/\r
+       /*slang_oper_orassign,*/\r
+       /*slang_oper_xorassign,*/\r
+       /*slang_oper_andassign,*/\r
+       slang_oper_select,\r
+       slang_oper_logicalor,\r
+       slang_oper_logicalxor,\r
+       slang_oper_logicaland,\r
+       /*slang_oper_bitor,*/\r
+       /*slang_oper_bitxor,*/\r
+       /*slang_oper_bitand,*/\r
+       slang_oper_equal,\r
+       slang_oper_notequal,\r
+       slang_oper_less,\r
+       slang_oper_greater,\r
+       slang_oper_lessequal,\r
+       slang_oper_greaterequal,\r
+       /*slang_oper_lshift,*/\r
+       /*slang_oper_rshift,*/\r
+       slang_oper_add,\r
+       slang_oper_subtract,\r
+       slang_oper_multiply,\r
+       slang_oper_divide,\r
+       /*slang_oper_modulus,*/\r
+       slang_oper_preincrement,\r
+       slang_oper_predecrement,\r
+       slang_oper_plus,\r
+       slang_oper_minus,\r
+       /*slang_oper_complement,*/\r
+       slang_oper_not,\r
+       slang_oper_subscript,\r
+       slang_oper_call,\r
+       slang_oper_field,\r
+       slang_oper_postincrement,\r
+       slang_oper_postdecrement\r
+} slang_operation_type;\r
+\r
+typedef struct slang_operation_\r
+{\r
+       slang_operation_type type;\r
+       struct slang_operation_ *children;\r
+       unsigned int num_children;\r
+       float literal;          /* bool, literal_int, literal_float */\r
+       char *identifier;       /* asm, identifier, call, field */\r
+       slang_variable_scope *locals;\r
+} slang_operation;\r
+\r
+typedef struct slang_variable_\r
+{\r
+       slang_fully_specified_type type;\r
+       char *name;\r
+       slang_operation *array_size;    /* spec_array */\r
+       slang_operation *initializer;\r
+} slang_variable;\r
+\r
+typedef struct slang_struct_scope_\r
+{\r
+       struct slang_struct_ *structs;\r
+       unsigned int num_structs;\r
+       struct slang_struct_scope_ *outer_scope;\r
+} slang_struct_scope;\r
+\r
+typedef struct slang_struct_\r
+{\r
+       char *name;\r
+       slang_variable_scope *fields;\r
+       slang_struct_scope *structs;\r
+} slang_struct;\r
+\r
+typedef enum slang_function_kind_\r
+{\r
+       slang_func_ordinary,\r
+       slang_func_constructor,\r
+       slang_func_operator\r
+} slang_function_kind;\r
+\r
+typedef struct slang_function_\r
+{\r
+       slang_function_kind kind;\r
+       slang_variable header;\r
+       slang_variable_scope *parameters;\r
+       unsigned int param_count;\r
+       slang_operation *body;\r
+} slang_function;\r
+\r
+typedef struct slang_function_scope_\r
+{\r
+       slang_function *functions;\r
+       unsigned int num_functions;\r
+       struct slang_function_scope_ *outer_scope;\r
+} slang_function_scope;\r
+\r
+typedef enum slang_unit_type_\r
+{\r
+       slang_unit_fragment_shader,\r
+       slang_unit_vertex_shader\r
+} slang_unit_type;\r
+       \r
+typedef struct slang_translation_unit_\r
+{\r
+       slang_variable_scope *globals;\r
+       slang_function_scope functions;\r
+       slang_struct_scope *structs;\r
+       slang_unit_type type;\r
+} slang_translation_unit;\r
+\r
+int _slang_compile (const char *, slang_translation_unit *, slang_unit_type type);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r