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