--- /dev/null
+/*\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, ¶m->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, ¶m->type.specifier, structs, scope))\r
+ return 0;\r
+ if (!parse_identifier (I, ¶m->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