From 08e90bdea1e4828abfdff6fedfe9e669bfee9ff1 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Fri, 13 Nov 2009 03:00:45 +0100 Subject: glsl/cl: Add a hard-coded syntax parser. --- src/glsl/cl/sl_cl_parse.c | 2647 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2647 insertions(+) create mode 100644 src/glsl/cl/sl_cl_parse.c (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c new file mode 100644 index 0000000000..06224b31ec --- /dev/null +++ b/src/glsl/cl/sl_cl_parse.c @@ -0,0 +1,2647 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +#include +#include +#include +#include "../pp/sl_pp_public.h" +#include "sl_cl_parse.h" + + +/* revision number - increment after each change affecting emitted output */ +#define REVISION 5 + +/* external declaration (or precision or invariant stmt) */ +#define EXTERNAL_NULL 0 +#define EXTERNAL_FUNCTION_DEFINITION 1 +#define EXTERNAL_DECLARATION 2 +#define DEFAULT_PRECISION 3 +#define INVARIANT_STMT 4 + +/* precision */ +#define PRECISION_DEFAULT 0 +#define PRECISION_LOW 1 +#define PRECISION_MEDIUM 2 +#define PRECISION_HIGH 3 + +/* declaration */ +#define DECLARATION_FUNCTION_PROTOTYPE 1 +#define DECLARATION_INIT_DECLARATOR_LIST 2 + +/* function type */ +#define FUNCTION_ORDINARY 0 +#define FUNCTION_CONSTRUCTOR 1 +#define FUNCTION_OPERATOR 2 + +/* function call type */ +#define FUNCTION_CALL_NONARRAY 0 +#define FUNCTION_CALL_ARRAY 1 + +/* operator type */ +#define OPERATOR_ADDASSIGN 1 +#define OPERATOR_SUBASSIGN 2 +#define OPERATOR_MULASSIGN 3 +#define OPERATOR_DIVASSIGN 4 +/*#define OPERATOR_MODASSIGN 5*/ +/*#define OPERATOR_LSHASSIGN 6*/ +/*#define OPERATOR_RSHASSIGN 7*/ +/*#define OPERATOR_ORASSIGN 8*/ +/*#define OPERATOR_XORASSIGN 9*/ +/*#define OPERATOR_ANDASSIGN 10*/ +#define OPERATOR_LOGICALXOR 11 +/*#define OPERATOR_BITOR 12*/ +/*#define OPERATOR_BITXOR 13*/ +/*#define OPERATOR_BITAND 14*/ +#define OPERATOR_LESS 15 +#define OPERATOR_GREATER 16 +#define OPERATOR_LESSEQUAL 17 +#define OPERATOR_GREATEREQUAL 18 +/*#define OPERATOR_LSHIFT 19*/ +/*#define OPERATOR_RSHIFT 20*/ +#define OPERATOR_MULTIPLY 21 +#define OPERATOR_DIVIDE 22 +/*#define OPERATOR_MODULUS 23*/ +#define OPERATOR_INCREMENT 24 +#define OPERATOR_DECREMENT 25 +#define OPERATOR_PLUS 26 +#define OPERATOR_MINUS 27 +/*#define OPERATOR_COMPLEMENT 28*/ +#define OPERATOR_NOT 29 + +/* 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 + +/* 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 + +/* invariant qualifier */ +#define TYPE_VARIANT 90 +#define TYPE_INVARIANT 91 + +/* centroid qualifier */ +#define TYPE_CENTER 95 +#define TYPE_CENTROID 96 + +/* 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_SAMPLER2DRECT 22 +#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23 +#define TYPE_SPECIFIER_STRUCT 24 +#define TYPE_SPECIFIER_TYPENAME 25 + +/* OpenGL 2.1 */ +#define TYPE_SPECIFIER_MAT23 26 +#define TYPE_SPECIFIER_MAT32 27 +#define TYPE_SPECIFIER_MAT24 28 +#define TYPE_SPECIFIER_MAT42 29 +#define TYPE_SPECIFIER_MAT34 30 +#define TYPE_SPECIFIER_MAT43 31 + +/* type specifier array */ +#define TYPE_SPECIFIER_NONARRAY 0 +#define TYPE_SPECIFIER_ARRAY 1 + +/* structure field */ +#define FIELD_NONE 0 +#define FIELD_NEXT 1 +#define FIELD_ARRAY 2 + +/* 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 +#define OP_PRECISION 62 +#define OP_METHOD 63 + +/* parameter qualifier */ +#define PARAM_QUALIFIER_IN 0 +#define PARAM_QUALIFIER_OUT 1 +#define PARAM_QUALIFIER_INOUT 2 + +/* function parameter */ +#define PARAMETER_NONE 0 +#define PARAMETER_NEXT 1 + +/* function parameter array presence */ +#define PARAMETER_ARRAY_NOT_PRESENT 0 +#define PARAMETER_ARRAY_PRESENT 1 + + +struct parse_dict { + int _void; + int _float; + int _int; + int _bool; + int vec2; + int vec3; + int vec4; + int bvec2; + int bvec3; + int bvec4; + int ivec2; + int ivec3; + int ivec4; + int mat2; + int mat3; + int mat4; + int mat2x3; + int mat3x2; + int mat2x4; + int mat4x2; + int mat3x4; + int mat4x3; + int sampler1D; + int sampler2D; + int sampler3D; + int samplerCube; + int sampler1DShadow; + int sampler2DShadow; + int sampler2DRect; + int sampler2DRectShadow; + + int invariant; + + int centroid; + + int precision; + int lowp; + int mediump; + int highp; + + int _const; + int attribute; + int varying; + int uniform; + int __fixed_output; + int __fixed_input; + + int in; + int out; + int inout; + + int _struct; + + int __constructor; + int __operator; + int ___asm; + + int _if; + int _else; + int _for; + int _while; + int _do; + + int _continue; + int _break; + int _return; + int discard; + + int _false; + int _true; +}; + + +struct parse_context { + struct sl_pp_context *context; + const struct sl_pp_token_info *input; + + struct parse_dict dict; + + unsigned char *out_buf; + unsigned int out_cap; + + unsigned int shader_type; + unsigned int parsing_builtin; +}; + + +struct parse_state { + unsigned int in; + unsigned int out; +}; + + +static __inline unsigned int +_emit(struct parse_context *ctx, + unsigned int *out, + unsigned char b) +{ + if (*out == ctx->out_cap) { + ctx->out_cap += 4096; + ctx->out_buf = (unsigned char *)realloc(ctx->out_buf, ctx->out_cap * sizeof(unsigned char)); + } + ctx->out_buf[*out] = b; + return (*out)++; +} + + +static void +_update(struct parse_context *ctx, + unsigned int out, + unsigned char b) +{ + ctx->out_buf[out] = b; +} + + +static int +_parse_token(struct parse_context *ctx, + enum sl_pp_token token, + struct parse_state *ps) +{ + if (ctx->input[ps->in].token == token) { + ps->in++; + return 0; + } + return -1; +} + + +static int +_parse_id(struct parse_context *ctx, + int id, + struct parse_state *ps) +{ + if (ctx->input[ps->in].token == SL_PP_IDENTIFIER && + ctx->input[ps->in].data.identifier == id) { + ps->in++; + return 0; + } + return -1; +} + + +static int +_parse_identifier(struct parse_context *ctx, + struct parse_state *ps) +{ + if (ctx->input[ps->in].token == SL_PP_IDENTIFIER) { + const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data.identifier); + + do { + _emit(ctx, &ps->out, *cstr); + } while (*cstr++); + ps->in++; + return 0; + } + return -1; +} + + +static int +_parse_float(struct parse_context *ctx, + struct parse_state *ps) +{ + if (ctx->input[ps->in].token == SL_PP_FLOAT) { + const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._float); + + _emit(ctx, &ps->out, 1); + do { + _emit(ctx, &ps->out, *cstr); + } while (*cstr++); + ps->in++; + return 0; + } + return -1; +} + + +static int +_parse_uint(struct parse_context *ctx, + struct parse_state *ps) +{ + if (ctx->input[ps->in].token == SL_PP_UINT) { + const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._uint); + + _emit(ctx, &ps->out, 1); + do { + _emit(ctx, &ps->out, *cstr); + } while (*cstr++); + ps->in++; + return 0; + } + return -1; +} + + +/**************************************/ + + +static int +_parse_unary_expression(struct parse_context *ctx, + struct parse_state *ps); + +static int +_parse_conditional_expression(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_constant_expression(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_primary_expression(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_statement(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_type_specifier(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_declaration(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_statement_list(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_assignment_expression(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_precision(struct parse_context *ctx, + struct parse_state *ps); + + +static int +_parse_overriden_operator(struct parse_context *ctx, + struct parse_state *ps) +{ + unsigned int op; + + if (_parse_token(ctx, SL_PP_INCREMENT, ps) == 0) { + op = OPERATOR_INCREMENT; + } else if (_parse_token(ctx, SL_PP_ADDASSIGN, ps) == 0) { + op = OPERATOR_ADDASSIGN; + } else if (_parse_token(ctx, SL_PP_PLUS, ps) == 0) { + op = OPERATOR_PLUS; + } else if (_parse_token(ctx, SL_PP_DECREMENT, ps) == 0) { + op = OPERATOR_DECREMENT; + } else if (_parse_token(ctx, SL_PP_SUBASSIGN, ps) == 0) { + op = OPERATOR_SUBASSIGN; + } else if (_parse_token(ctx, SL_PP_MINUS, ps) == 0) { + op = OPERATOR_MINUS; + } else if (_parse_token(ctx, SL_PP_NOT, ps) == 0) { + op = OPERATOR_NOT; + } else if (_parse_token(ctx, SL_PP_MULASSIGN, ps) == 0) { + op = OPERATOR_MULASSIGN; + } else if (_parse_token(ctx, SL_PP_STAR, ps) == 0) { + op = OPERATOR_MULTIPLY; + } else if (_parse_token(ctx, SL_PP_DIVASSIGN, ps) == 0) { + op = OPERATOR_DIVASSIGN; + } else if (_parse_token(ctx, SL_PP_SLASH, ps) == 0) { + op = OPERATOR_DIVIDE; + } else if (_parse_token(ctx, SL_PP_LESSEQUAL, ps) == 0) { + op = OPERATOR_LESSEQUAL; + } else if (_parse_token(ctx, SL_PP_LESS, ps) == 0) { + op = OPERATOR_LESS; + } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, ps) == 0) { + op = OPERATOR_GREATEREQUAL; + } else if (_parse_token(ctx, SL_PP_GREATER, ps) == 0) { + op = OPERATOR_GREATER; + } else if (_parse_token(ctx, SL_PP_XOR, ps) == 0) { + op = OPERATOR_LOGICALXOR; + } else { + return -1; + } + + _emit(ctx, &ps->out, op); + return 0; +} + + +static int +_parse_function_decl_identifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, 0); + + if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__constructor, &p) == 0) { + _update(ctx, e, FUNCTION_CONSTRUCTOR); + *ps = p; + return 0; + } + + if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__operator, &p) == 0) { + _update(ctx, e, FUNCTION_OPERATOR); + if (_parse_overriden_operator(ctx, &p) == 0) { + *ps = p; + return 0; + } + return -1; + } + + if (_parse_identifier(ctx, &p) == 0) { + _update(ctx, e, FUNCTION_ORDINARY); + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_invariant_qualifier(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_id(ctx, ctx->dict.invariant, ps)) { + return -1; + } + _emit(ctx, &ps->out, TYPE_INVARIANT); + return 0; +} + + +static int +_parse_centroid_qualifier(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_id(ctx, ctx->dict.centroid, ps)) { + return -1; + } + _emit(ctx, &ps->out, TYPE_CENTROID); + return 0; +} + + +static int +_parse_type_qualifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, 0); + int id; + + if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + return -1; + } + id = ctx->input[p.in].data.identifier; + + if (id == ctx->dict._const) { + _update(ctx, e, TYPE_QUALIFIER_CONST); + } else if (ctx->shader_type == 2 && id == ctx->dict.attribute) { + _update(ctx, e, TYPE_QUALIFIER_ATTRIBUTE); + } else if (id == ctx->dict.varying) { + _update(ctx, e, TYPE_QUALIFIER_VARYING); + } else if (id == ctx->dict.uniform) { + _update(ctx, e, TYPE_QUALIFIER_UNIFORM); + } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_output) { + _update(ctx, e, TYPE_QUALIFIER_FIXEDOUTPUT); + } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_input) { + _update(ctx, e, TYPE_QUALIFIER_FIXEDINPUT); + } else { + return -1; + } + _parse_token(ctx, SL_PP_IDENTIFIER, &p); + *ps = p; + return 0; +} + + +static int +_parse_struct_declarator(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e; + + if (_parse_identifier(ctx, &p)) { + return -1; + } + e = _emit(ctx, &p.out, FIELD_NONE); + *ps = p; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p)) { + return 0; + } + if (_parse_constant_expression(ctx, &p)) { + return 0; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return 0; + } + _update(ctx, e, FIELD_ARRAY); + *ps = p; + return 0; +} + + +static int +_parse_struct_declarator_list(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_struct_declarator(ctx, &p)) { + return -1; + } + + for (;;) { + *ps = p; + _emit(ctx, &p.out, FIELD_NEXT); + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + return 0; + } + if (_parse_struct_declarator(ctx, &p)) { + return 0; + } + } +} + + +static int +_parse_struct_declaration(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_type_specifier(ctx, &p)) { + return -1; + } + if (_parse_struct_declarator_list(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + _emit(ctx, &p.out, FIELD_NONE); + *ps = p; + return 0; +} + + +static int +_parse_struct_declaration_list(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_struct_declaration(ctx, &p)) { + return -1; + } + + for (;;) { + *ps = p; + _emit(ctx, &p.out, FIELD_NEXT); + if (_parse_struct_declaration(ctx, &p)) { + return 0; + } + } +} + + +static int +_parse_struct_specifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_id(ctx, ctx->dict._struct, &p)) { + return -1; + } + if (_parse_identifier(ctx, &p)) { + _emit(ctx, &p.out, '\0'); + } + if (_parse_token(ctx, SL_PP_LBRACE, &p)) { + return -1; + } + if (_parse_struct_declaration_list(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RBRACE, &p)) { + return -1; + } + _emit(ctx, &p.out, FIELD_NONE); + *ps = p; + return 0; +} + + +static int +_parse_type_specifier_nonarray(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, 0); + int id; + + if (_parse_struct_specifier(ctx, &p) == 0) { + _update(ctx, e, TYPE_SPECIFIER_STRUCT); + *ps = p; + return 0; + } + + if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + return -1; + } + id = ctx->input[p.in].data.identifier; + + if (id == ctx->dict._void) { + _update(ctx, e, TYPE_SPECIFIER_VOID); + } else if (id == ctx->dict._float) { + _update(ctx, e, TYPE_SPECIFIER_FLOAT); + } else if (id == ctx->dict._int) { + _update(ctx, e, TYPE_SPECIFIER_INT); + } else if (id == ctx->dict._bool) { + _update(ctx, e, TYPE_SPECIFIER_BOOL); + } else if (id == ctx->dict.vec2) { + _update(ctx, e, TYPE_SPECIFIER_VEC2); + } else if (id == ctx->dict.vec3) { + _update(ctx, e, TYPE_SPECIFIER_VEC3); + } else if (id == ctx->dict.vec4) { + _update(ctx, e, TYPE_SPECIFIER_VEC4); + } else if (id == ctx->dict.bvec2) { + _update(ctx, e, TYPE_SPECIFIER_BVEC2); + } else if (id == ctx->dict.bvec3) { + _update(ctx, e, TYPE_SPECIFIER_BVEC3); + } else if (id == ctx->dict.bvec4) { + _update(ctx, e, TYPE_SPECIFIER_BVEC4); + } else if (id == ctx->dict.ivec2) { + _update(ctx, e, TYPE_SPECIFIER_IVEC2); + } else if (id == ctx->dict.ivec3) { + _update(ctx, e, TYPE_SPECIFIER_IVEC3); + } else if (id == ctx->dict.ivec4) { + _update(ctx, e, TYPE_SPECIFIER_IVEC4); + } else if (id == ctx->dict.mat2) { + _update(ctx, e, TYPE_SPECIFIER_MAT2); + } else if (id == ctx->dict.mat3) { + _update(ctx, e, TYPE_SPECIFIER_MAT3); + } else if (id == ctx->dict.mat4) { + _update(ctx, e, TYPE_SPECIFIER_MAT4); + } else if (id == ctx->dict.mat2x3) { + _update(ctx, e, TYPE_SPECIFIER_MAT23); + } else if (id == ctx->dict.mat3x2) { + _update(ctx, e, TYPE_SPECIFIER_MAT32); + } else if (id == ctx->dict.mat2x4) { + _update(ctx, e, TYPE_SPECIFIER_MAT24); + } else if (id == ctx->dict.mat4x2) { + _update(ctx, e, TYPE_SPECIFIER_MAT42); + } else if (id == ctx->dict.mat3x4) { + _update(ctx, e, TYPE_SPECIFIER_MAT34); + } else if (id == ctx->dict.mat4x3) { + _update(ctx, e, TYPE_SPECIFIER_MAT43); + } else if (id == ctx->dict.sampler1D) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER1D); + } else if (id == ctx->dict.sampler2D) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER2D); + } else if (id == ctx->dict.sampler3D) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER3D); + } else if (id == ctx->dict.samplerCube) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLERCUBE); + } else if (id == ctx->dict.sampler1DShadow) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER1DSHADOW); + } else if (id == ctx->dict.sampler2DShadow) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DSHADOW); + } else if (id == ctx->dict.sampler2DRect) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECT); + } else if (id == ctx->dict.sampler2DRectShadow) { + _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECTSHADOW); + } else if (_parse_identifier(ctx, &p) == 0) { + _update(ctx, e, TYPE_SPECIFIER_TYPENAME); + *ps = p; + return 0; + } else { + return -1; + } + + _parse_token(ctx, SL_PP_IDENTIFIER, &p); + *ps = p; + return 0; +} + + +static int +_parse_type_specifier_array(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p)) { + return -1; + } + if (_parse_constant_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_type_specifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e; + + if (_parse_type_specifier_nonarray(ctx, &p)) { + return -1; + } + + e = _emit(ctx, &p.out, TYPE_SPECIFIER_ARRAY); + if (_parse_type_specifier_array(ctx, &p)) { + _update(ctx, e, TYPE_SPECIFIER_NONARRAY); + } + *ps = p; + return 0; +} + + +static int +_parse_fully_specified_type(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_invariant_qualifier(ctx, &p)) { + _emit(ctx, &p.out, TYPE_VARIANT); + } + if (_parse_centroid_qualifier(ctx, &p)) { + _emit(ctx, &p.out, TYPE_CENTER); + } + if (_parse_type_qualifier(ctx, &p)) { + _emit(ctx, &p.out, TYPE_QUALIFIER_NONE); + } + if (_parse_precision(ctx, &p)) { + _emit(ctx, &p.out, PRECISION_DEFAULT); + } + if (_parse_type_specifier(ctx, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_function_header(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_fully_specified_type(ctx, &p)) { + return -1; + } + if (_parse_function_decl_identifier(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_parameter_qualifier(struct parse_context *ctx, + struct parse_state *ps) +{ + unsigned int e = _emit(ctx, &ps->out, PARAM_QUALIFIER_IN); + + if (_parse_id(ctx, ctx->dict.out, ps) == 0) { + _update(ctx, e, PARAM_QUALIFIER_OUT); + } else if (_parse_id(ctx, ctx->dict.inout, ps) == 0) { + _update(ctx, e, PARAM_QUALIFIER_INOUT); + } else { + _parse_id(ctx, ctx->dict.in, ps); + } + return 0; +} + + +static int +_parse_function_identifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + unsigned int e; + + if (_parse_identifier(ctx, ps)) { + return -1; + } + e = _emit(ctx, &ps->out, FUNCTION_CALL_NONARRAY); + + p = *ps; + if (_parse_token(ctx, SL_PP_LBRACKET, &p)) { + return 0; + } + if (_parse_constant_expression(ctx, &p)) { + return 0; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return 0; + } + _update(ctx, e, FUNCTION_CALL_ARRAY); + *ps = p; + return 0; +} + + +static int +_parse_function_call_header(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_identifier(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_assign_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int op; + + if (_parse_unary_expression(ctx, &p)) { + return -1; + } + + if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) { + op = OP_ASSIGN; + } else if (_parse_token(ctx, SL_PP_MULASSIGN, &p) == 0) { + op = OP_MULASSIGN; + } else if (_parse_token(ctx, SL_PP_DIVASSIGN, &p) == 0) { + op = OP_DIVASSIGN; + } else if (_parse_token(ctx, SL_PP_ADDASSIGN, &p) == 0) { + op = OP_ADDASSIGN; + } else if (_parse_token(ctx, SL_PP_SUBASSIGN, &p) == 0) { + op = OP_SUBASSIGN; + } else { + return -1; + } + + if (_parse_assignment_expression(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, op); + + *ps = p; + return 0; +} + + +static int +_parse_assignment_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_assign_expression(ctx, ps) == 0) { + return 0; + } + + if (_parse_conditional_expression(ctx, ps) == 0) { + return 0; + } + + return -1; +} + + +static int +_parse_function_call_header_with_parameters(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_call_header(ctx, &p)) { + return -1; + } + if (_parse_assignment_expression(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + return 0; + } + if (_parse_assignment_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_END); + } +} + + +static int +_parse_function_call_header_no_parameters(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_function_call_header(ctx, ps)) { + return -1; + } + _parse_id(ctx, ctx->dict._void, ps); + return 0; +} + + +static int +_parse_function_call_generic(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_call_header_with_parameters(ctx, &p) == 0) { + if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) { + *ps = p; + return 0; + } + } + + p = *ps; + if (_parse_function_call_header_no_parameters(ctx, &p) == 0) { + if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) { + *ps = p; + return 0; + } + } + + return -1; +} + + +static int +_parse_method_call(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_METHOD); + if (_parse_identifier(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_DOT, &p)) { + return -1; + } + if (_parse_function_call_generic(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_regular_function_call(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_CALL); + if (_parse_function_call_generic(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_function_call(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_regular_function_call(ctx, ps) == 0) { + return 0; + } + + if (_parse_method_call(ctx, ps) == 0) { + return 0; + } + + return -1; +} + + +static int +_parse_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_assignment_expression(ctx, &p)) { + return -1; + } + + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + return 0; + } + if (_parse_assignment_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_SEQUENCE); + } +} + + +static int +_parse_postfix_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + + if (_parse_function_call(ctx, ps)) { + if (_parse_primary_expression(ctx, ps)) { + return -1; + } + } + + for (p = *ps;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) { + _emit(ctx, &p.out, OP_POSTINCREMENT); + } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) { + _emit(ctx, &p.out, OP_POSTDECREMENT); + } else if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) { + if (_parse_expression(ctx, &p)) { + return 0; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_SUBSCRIPT); + } else if (_parse_token(ctx, SL_PP_DOT, &p) == 0) { + _emit(ctx, &p.out, OP_FIELD); + if (_parse_identifier(ctx, &p)) { + return 0; + } + } else { + return 0; + } + } +} + + +static int +_parse_unary_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + unsigned int op; + + if (_parse_postfix_expression(ctx, ps) == 0) { + return 0; + } + + p = *ps; + if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) { + op = OP_PREINCREMENT; + } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) { + op = OP_PREDECREMENT; + } else if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) { + op = OP_PLUS; + } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) { + op = OP_MINUS; + } else if (_parse_token(ctx, SL_PP_NOT, &p) == 0) { + op = OP_NOT; + } else { + return -1; + } + + if (_parse_unary_expression(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, op); + *ps = p; + return 0; +} + + +static int +_parse_multiplicative_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_unary_expression(ctx, &p)) { + return -1; + } + for (;;) { + unsigned int op; + + *ps = p; + if (_parse_token(ctx, SL_PP_STAR, &p) == 0) { + op = OP_MULTIPLY; + } else if (_parse_token(ctx, SL_PP_SLASH, &p) == 0) { + op = OP_DIVIDE; + } else { + return 0; + } + if (_parse_unary_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, op); + } +} + + +static int +_parse_additive_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_multiplicative_expression(ctx, &p)) { + return -1; + } + for (;;) { + unsigned int op; + + *ps = p; + if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) { + op = OP_ADD; + } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) { + op = OP_SUBTRACT; + } else { + return 0; + } + if (_parse_multiplicative_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, op); + } +} + + +static int +_parse_relational_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_additive_expression(ctx, &p)) { + return -1; + } + for (;;) { + unsigned int op; + + *ps = p; + if (_parse_token(ctx, SL_PP_LESS, &p) == 0) { + op = OP_LESS; + } else if (_parse_token(ctx, SL_PP_GREATER, &p) == 0) { + op = OP_GREATER; + } else if (_parse_token(ctx, SL_PP_LESSEQUAL, &p) == 0) { + op = OP_LESSEQUAL; + } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, &p) == 0) { + op = OP_GREATEREQUAL; + } else { + return 0; + } + if (_parse_additive_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, op); + } +} + + +static int +_parse_equality_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_relational_expression(ctx, &p)) { + return -1; + } + for (;;) { + unsigned int op; + + *ps = p; + if (_parse_token(ctx, SL_PP_EQUAL, &p) == 0) { + op = OP_EQUAL; + } else if (_parse_token(ctx, SL_PP_NOTEQUAL, &p) == 0) { + op = OP_NOTEQUAL; + } else { + return 0; + } + if (_parse_relational_expression(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, op); + } +} + + +static int +_parse_logical_and_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_equality_expression(ctx, &p)) { + return -1; + } + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_AND, &p)) { + return 0; + } + if (_parse_equality_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_LOGICALAND); + } +} + + +static int +_parse_logical_xor_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_logical_and_expression(ctx, &p)) { + return -1; + } + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_XOR, &p)) { + return 0; + } + if (_parse_logical_and_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_LOGICALXOR); + } +} + + +static int +_parse_logical_or_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_logical_xor_expression(ctx, &p)) { + return -1; + } + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_OR, &p)) { + return 0; + } + if (_parse_logical_xor_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_LOGICALOR); + } +} + + +static int +_parse_conditional_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_logical_or_expression(ctx, &p)) { + return -1; + } + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_QUESTION, &p)) { + return 0; + } + if (_parse_expression(ctx, &p)) { + return 0; + } + if (_parse_token(ctx, SL_PP_COLON, &p)) { + return 0; + } + if (_parse_conditional_expression(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_SELECT); + } +} + + +static int +_parse_constant_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_conditional_expression(ctx, ps)) { + return -1; + } + _emit(ctx, &ps->out, OP_END); + return 0; +} + + +static int +_parse_parameter_declarator_array(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p)) { + return -1; + } + if (_parse_constant_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_parameter_declarator(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e; + + if (_parse_type_specifier(ctx, &p)) { + return -1; + } + if (_parse_identifier(ctx, &p)) { + return -1; + } + e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT); + if (_parse_parameter_declarator_array(ctx, &p)) { + _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT); + } + *ps = p; + return 0; +} + + +static int +_parse_parameter_type_specifier_array(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p)) { + return -1; + } + if (_parse_constant_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_parameter_type_specifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e; + + if (_parse_type_specifier(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, '\0'); + + e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT); + if (_parse_parameter_type_specifier_array(ctx, &p)) { + _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT); + } + *ps = p; + return 0; +} + + +static int +_parse_parameter_declaration(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, PARAMETER_NEXT); + + if (_parse_type_qualifier(ctx, &p)) { + _emit(ctx, &p.out, TYPE_QUALIFIER_NONE); + } + _parse_parameter_qualifier(ctx, &p); + if (_parse_precision(ctx, &p)) { + _emit(ctx, &p.out, PRECISION_DEFAULT); + } + if (_parse_parameter_declarator(ctx, &p) == 0) { + *ps = p; + return 0; + } + if (_parse_parameter_type_specifier(ctx, &p) == 0) { + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_function_header_with_parameters(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_header(ctx, &p)) { + return -1; + } + if (_parse_parameter_declaration(ctx, &p)) { + return -1; + } + + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + return 0; + } + if (_parse_parameter_declaration(ctx, &p)) { + return 0; + } + } +} + + +static int +_parse_function_declarator(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_function_header_with_parameters(ctx, ps) == 0) { + return 0; + } + + if (_parse_function_header(ctx, ps) == 0) { + return 0; + } + + return -1; +} + + +static int +_parse_function_prototype(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_header(ctx, &p) == 0) { + if (_parse_id(ctx, ctx->dict._void, &p) == 0) { + if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) { + _emit(ctx, &p.out, PARAMETER_NONE); + *ps = p; + return 0; + } + } + } + + p = *ps; + if (_parse_function_declarator(ctx, &p) == 0) { + if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) { + _emit(ctx, &p.out, PARAMETER_NONE); + *ps = p; + return 0; + } + } + + return -1; +} + + +static int +_parse_precision(struct parse_context *ctx, + struct parse_state *ps) +{ + int id; + unsigned int precision; + + if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + return -1; + } + id = ctx->input[ps->in].data.identifier; + + if (id == ctx->dict.lowp) { + precision = PRECISION_LOW; + } else if (id == ctx->dict.mediump) { + precision = PRECISION_MEDIUM; + } else if (id == ctx->dict.highp) { + precision = PRECISION_HIGH; + } else { + return -1; + } + + _parse_token(ctx, SL_PP_IDENTIFIER, ps); + _emit(ctx, &ps->out, precision); + return 0; +} + + +static int +_parse_prectype(struct parse_context *ctx, + struct parse_state *ps) +{ + int id; + unsigned int type; + + if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + return -1; + } + id = ctx->input[ps->in].data.identifier; + + if (id == ctx->dict._int) { + type = TYPE_SPECIFIER_INT; + } else if (id == ctx->dict._float) { + type = TYPE_SPECIFIER_FLOAT; + } else if (id == ctx->dict.sampler1D) { + type = TYPE_SPECIFIER_SAMPLER1D; + } else if (id == ctx->dict.sampler2D) { + type = TYPE_SPECIFIER_SAMPLER2D; + } else if (id == ctx->dict.sampler3D) { + type = TYPE_SPECIFIER_SAMPLER3D; + } else if (id == ctx->dict.samplerCube) { + type = TYPE_SPECIFIER_SAMPLERCUBE; + } else if (id == ctx->dict.sampler1DShadow) { + type = TYPE_SPECIFIER_SAMPLER1DSHADOW; + } else if (id == ctx->dict.sampler2DShadow) { + type = TYPE_SPECIFIER_SAMPLER2DSHADOW; + } else if (id == ctx->dict.sampler2DRect) { + type = TYPE_SPECIFIER_SAMPLER2DRECT; + } else if (id == ctx->dict.sampler2DRectShadow) { + type = TYPE_SPECIFIER_SAMPLER2DRECTSHADOW; + } else { + return -1; + } + + _parse_token(ctx, SL_PP_IDENTIFIER, ps); + _emit(ctx, &ps->out, type); + return 0; +} + + +static int +_parse_precision_stmt(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_id(ctx, ctx->dict.precision, &p)) { + return -1; + } + if (_parse_precision(ctx, &p)) { + return -1; + } + if (_parse_prectype(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_floatconstant(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_PUSH_FLOAT); + if (_parse_float(ctx, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_intconstant(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_PUSH_INT); + if (_parse_uint(ctx, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_boolconstant(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_id(ctx, ctx->dict._false, ps) == 0) { + _emit(ctx, &ps->out, OP_PUSH_BOOL); + _emit(ctx, &ps->out, '0'); + _emit(ctx, &ps->out, '\0'); + return 0; + } + + if (_parse_id(ctx, ctx->dict._true, ps) == 0) { + _emit(ctx, &ps->out, OP_PUSH_BOOL); + _emit(ctx, &ps->out, '1'); + _emit(ctx, &ps->out, '\0'); + return 0; + } + + return -1; +} + + +static int +_parse_variable_identifier(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_PUSH_IDENTIFIER); + if (_parse_identifier(ctx, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_primary_expression(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + + if (_parse_floatconstant(ctx, ps) == 0) { + return 0; + } + if (_parse_boolconstant(ctx, ps) == 0) { + return 0; + } + if (_parse_intconstant(ctx, ps) == 0) { + return 0; + } + if (_parse_variable_identifier(ctx, ps) == 0) { + return 0; + } + + p = *ps; + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + if (_parse_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + return -1; + } + + *ps = p; + return 0; +} + + +static int +_parse_asm_argument(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_variable_identifier(ctx, ps) == 0) { + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_DOT, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_FIELD); + if (_parse_identifier(ctx, &p)) { + return 0; + } + *ps = p; + return 0; + } + + if (_parse_floatconstant(ctx, ps) == 0) { + return 0; + } + + return -1; +} + + +static int +_parse_asm_arguments(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_asm_argument(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + + for (;;) { + *ps = p; + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + return 0; + } + if (_parse_asm_argument(ctx, &p)) { + return 0; + } + _emit(ctx, &p.out, OP_END); + } +} + + +static int +_parse_asm_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_id(ctx, ctx->dict.___asm, &p)) { + return -1; + } + if (_parse_identifier(ctx, &p)) { + return -1; + } + if (_parse_asm_arguments(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_selection_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_IF); + if (_parse_id(ctx, ctx->dict._if, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + if (_parse_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + if (_parse_statement(ctx, &p)) { + return -1; + } + + *ps = p; + if (_parse_id(ctx, ctx->dict._else, &p) == 0) { + if (_parse_statement(ctx, &p) == 0) { + *ps = p; + return 0; + } + } + + _emit(ctx, &ps->out, OP_EXPRESSION); + _emit(ctx, &ps->out, OP_PUSH_VOID); + _emit(ctx, &ps->out, OP_END); + return 0; +} + + +static int +_parse_expression_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_expression(ctx, &p)) { + _emit(ctx, &p.out, OP_PUSH_VOID); + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_for_init_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, OP_EXPRESSION); + + if (_parse_expression_statement(ctx, &p) == 0) { + *ps = p; + return 0; + } + + if (_parse_declaration(ctx, &p) == 0) { + _update(ctx, e, OP_DECLARE); + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_initializer(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_assignment_expression(ctx, ps) == 0) { + _emit(ctx, &ps->out, OP_END); + return 0; + } + return -1; +} + + +static int +_parse_condition_initializer(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + _emit(ctx, &p.out, OP_DECLARE); + _emit(ctx, &p.out, DECLARATION_INIT_DECLARATOR_LIST); + if (_parse_fully_specified_type(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, VARIABLE_IDENTIFIER); + if (_parse_identifier(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_ASSIGN, &p)) { + return -1; + } + _emit(ctx, &p.out, VARIABLE_INITIALIZER); + if (_parse_initializer(ctx, &p)) { + return -1; + } + _emit(ctx, &p.out, DECLARATOR_NONE); + *ps = p; + return 0; +} + + +static int +_parse_condition(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + + if (_parse_condition_initializer(ctx, ps) == 0) { + return 0; + } + + p = *ps; + _emit(ctx, &p.out, OP_EXPRESSION); + if (_parse_expression(ctx, &p) == 0) { + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_for_rest_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_condition(ctx, &p)) { + _emit(ctx, &p.out, OP_EXPRESSION); + _emit(ctx, &p.out, OP_PUSH_BOOL); + _emit(ctx, &p.out, 2); + _emit(ctx, &p.out, '1'); + _emit(ctx, &p.out, '\0'); + _emit(ctx, &p.out, OP_END); + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + if (_parse_expression(ctx, &p)) { + _emit(ctx, &p.out, OP_PUSH_VOID); + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_iteration_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_id(ctx, ctx->dict._while, &p) == 0) { + _emit(ctx, &p.out, OP_WHILE); + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + if (_parse_condition(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + return -1; + } + if (_parse_statement(ctx, &p)) { + return -1; + } + *ps = p; + return 0; + } + + if (_parse_id(ctx, ctx->dict._do, &p) == 0) { + _emit(ctx, &p.out, OP_DO); + if (_parse_statement(ctx, &p)) { + return -1; + } + if (_parse_id(ctx, ctx->dict._while, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + if (_parse_expression(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + *ps = p; + return 0; + } + + if (_parse_id(ctx, ctx->dict._for, &p) == 0) { + _emit(ctx, &p.out, OP_FOR); + if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + return -1; + } + if (_parse_for_init_statement(ctx, &p)) { + return -1; + } + if (_parse_for_rest_statement(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + return -1; + } + if (_parse_statement(ctx, &p)) { + return -1; + } + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_jump_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, 0); + + if (_parse_id(ctx, ctx->dict._continue, &p) == 0) { + _update(ctx, e, OP_CONTINUE); + } else if (_parse_id(ctx, ctx->dict._break, &p) == 0) { + _update(ctx, e, OP_BREAK); + } else if (_parse_id(ctx, ctx->dict._return, &p) == 0) { + _update(ctx, e, OP_RETURN); + if (_parse_expression(ctx, &p)) { + _emit(ctx, &p.out, OP_PUSH_VOID); + } + _emit(ctx, &p.out, OP_END); + } else if (ctx->shader_type == 1 && _parse_id(ctx, ctx->dict.discard, &p) == 0) { + _update(ctx, e, OP_DISCARD); + } else { + return -1; + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_simple_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p; + unsigned int e; + + if (_parse_selection_statement(ctx, ps) == 0) { + return 0; + } + + if (_parse_iteration_statement(ctx, ps) == 0) { + return 0; + } + + if (_parse_jump_statement(ctx, ps) == 0) { + return 0; + } + + p = *ps; + e = _emit(ctx, &p.out, OP_EXPRESSION); + if (_parse_expression_statement(ctx, &p) == 0) { + *ps = p; + return 0; + } + + if (_parse_precision_stmt(ctx, &p) == 0) { + _update(ctx, e, OP_PRECISION); + *ps = p; + return 0; + } + + if (ctx->parsing_builtin && _parse_asm_statement(ctx, &p) == 0) { + _update(ctx, e, OP_ASM); + *ps = p; + return 0; + } + + if (_parse_declaration(ctx, &p) == 0) { + _update(ctx, e, OP_DECLARE); + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_compound_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACE, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_BLOCK_BEGIN_NEW_SCOPE); + _parse_statement_list(ctx, &p); + if (_parse_token(ctx, SL_PP_RBRACE, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_statement(struct parse_context *ctx, + struct parse_state *ps) +{ + if (_parse_compound_statement(ctx, ps) == 0) { + return 0; + } + + if (_parse_simple_statement(ctx, ps) == 0) { + return 0; + } + + return -1; +} + + +static int +_parse_statement_list(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_statement(ctx, &p)) { + return -1; + } + + for (;;) { + *ps = p; + if (_parse_statement(ctx, &p)) { + return 0; + } + } +} + + +static int +_parse_compound_statement_no_new_scope(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACE, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_BLOCK_BEGIN_NO_NEW_SCOPE); + _parse_statement_list(ctx, &p); + if (_parse_token(ctx, SL_PP_RBRACE, &p)) { + return -1; + } + _emit(ctx, &p.out, OP_END); + *ps = p; + return 0; +} + + +static int +_parse_function_definition(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_function_prototype(ctx, &p)) { + return -1; + } + if (_parse_compound_statement_no_new_scope(ctx, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_invariant_stmt(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_id(ctx, ctx->dict.invariant, &p)) { + return -1; + } + if (_parse_identifier(ctx, &p)) { + return -1; + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_single_declaration(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e; + + if (_parse_fully_specified_type(ctx, &p)) { + return -1; + } + + e = _emit(ctx, &p.out, VARIABLE_IDENTIFIER); + if (_parse_identifier(ctx, &p)) { + _update(ctx, e, VARIABLE_NONE); + *ps = p; + return 0; + } + + e = _emit(ctx, &p.out, VARIABLE_NONE); + *ps = p; + + if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) { + _update(ctx, e, VARIABLE_INITIALIZER); + if (_parse_initializer(ctx, &p) == 0) { + *ps = p; + return 0; + } + } + p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) { + if (_parse_constant_expression(ctx, &p)) { + _update(ctx, e, VARIABLE_ARRAY_UNKNOWN); + } else { + _update(ctx, e, VARIABLE_ARRAY_EXPLICIT); + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) { + *ps = p; + return 0; + } + } + return 0; +} + + +static int +_parse_init_declarator_list(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + + if (_parse_single_declaration(ctx, &p)) { + return -1; + } + + for (;;) { + unsigned int e; + + *ps = p; + if (_parse_token(ctx, SL_PP_COMMA, &p)) { + break; + } + _emit(ctx, &p.out, DECLARATOR_NEXT); + _emit(ctx, &p.out, VARIABLE_IDENTIFIER); + if (_parse_identifier(ctx, &p)) { + break; + } + + e = _emit(ctx, &p.out, VARIABLE_NONE); + *ps = p; + + if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) { + if (_parse_initializer(ctx, &p) == 0) { + _update(ctx, e, VARIABLE_INITIALIZER); + *ps = p; + continue; + } + } + p = *ps; + + if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) { + unsigned int arr; + + if (_parse_constant_expression(ctx, &p)) { + arr = VARIABLE_ARRAY_UNKNOWN; + } else { + arr = VARIABLE_ARRAY_EXPLICIT; + } + if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) { + _update(ctx, e, arr); + *ps = p; + continue; + } + } + p = *ps; + } + + _emit(ctx, &ps->out, DECLARATOR_NONE); + return 0; +} + + +static int +_parse_declaration(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, DECLARATION_FUNCTION_PROTOTYPE); + + if (_parse_function_prototype(ctx, &p)) { + if (_parse_init_declarator_list(ctx, &p)) { + return -1; + } + _update(ctx, e, DECLARATION_INIT_DECLARATOR_LIST); + } + if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + return -1; + } + *ps = p; + return 0; +} + + +static int +_parse_external_declaration(struct parse_context *ctx, + struct parse_state *ps) +{ + struct parse_state p = *ps; + unsigned int e = _emit(ctx, &p.out, 0); + + if (_parse_precision_stmt(ctx, &p) == 0) { + _update(ctx, e, DEFAULT_PRECISION); + *ps = p; + return 0; + } + + if (_parse_function_definition(ctx, &p) == 0) { + _update(ctx, e, EXTERNAL_FUNCTION_DEFINITION); + *ps = p; + return 0; + } + + if (_parse_invariant_stmt(ctx, &p) == 0) { + _update(ctx, e, INVARIANT_STMT); + *ps = p; + return 0; + } + + if (_parse_declaration(ctx, &p) == 0) { + _update(ctx, e, EXTERNAL_DECLARATION); + *ps = p; + return 0; + } + + return -1; +} + + +static int +_parse_translation_unit(struct parse_context *ctx, + struct parse_state *ps) +{ + _emit(ctx, &ps->out, REVISION); + if (_parse_external_declaration(ctx, ps)) { + return -1; + } + while (_parse_external_declaration(ctx, ps) == 0) { + } + _emit(ctx, &ps->out, EXTERNAL_NULL); + if (_parse_token(ctx, SL_PP_EOF, ps)) { + return -1; + } + return 0; +} + + +#define ADD_NAME_STR(CTX, NAME, STR)\ + do {\ + (CTX).dict.NAME = sl_pp_context_add_unique_str((CTX).context, (STR));\ + if ((CTX).dict.NAME == -1) {\ + return -1;\ + }\ + } while (0) + +#define ADD_NAME(CTX, NAME) ADD_NAME_STR(CTX, NAME, #NAME) + + +int +sl_cl_compile(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int shader_type, + unsigned char **output, + unsigned int *cboutput) +{ + struct parse_context ctx; + struct parse_state ps; + + ctx.context = context; + ctx.input = input; + + ADD_NAME_STR(ctx, _void, "void"); + ADD_NAME_STR(ctx, _float, "float"); + ADD_NAME_STR(ctx, _int, "int"); + ADD_NAME_STR(ctx, _bool, "bool"); + ADD_NAME(ctx, vec2); + ADD_NAME(ctx, vec3); + ADD_NAME(ctx, vec4); + ADD_NAME(ctx, bvec2); + ADD_NAME(ctx, bvec3); + ADD_NAME(ctx, bvec4); + ADD_NAME(ctx, ivec2); + ADD_NAME(ctx, ivec3); + ADD_NAME(ctx, ivec4); + ADD_NAME(ctx, mat2); + ADD_NAME(ctx, mat3); + ADD_NAME(ctx, mat4); + ADD_NAME(ctx, mat2x3); + ADD_NAME(ctx, mat3x2); + ADD_NAME(ctx, mat2x4); + ADD_NAME(ctx, mat4x2); + ADD_NAME(ctx, mat3x4); + ADD_NAME(ctx, mat4x3); + ADD_NAME(ctx, sampler1D); + ADD_NAME(ctx, sampler2D); + ADD_NAME(ctx, sampler3D); + ADD_NAME(ctx, samplerCube); + ADD_NAME(ctx, sampler1DShadow); + ADD_NAME(ctx, sampler2DShadow); + ADD_NAME(ctx, sampler2DRect); + ADD_NAME(ctx, sampler2DRectShadow); + + ADD_NAME(ctx, invariant); + + ADD_NAME(ctx, centroid); + + ADD_NAME(ctx, precision); + ADD_NAME(ctx, lowp); + ADD_NAME(ctx, mediump); + ADD_NAME(ctx, highp); + + ADD_NAME_STR(ctx, _const, "const"); + ADD_NAME(ctx, attribute); + ADD_NAME(ctx, varying); + ADD_NAME(ctx, uniform); + ADD_NAME(ctx, __fixed_output); + ADD_NAME(ctx, __fixed_input); + + ADD_NAME(ctx, in); + ADD_NAME(ctx, out); + ADD_NAME(ctx, inout); + + ADD_NAME_STR(ctx, _struct, "struct"); + + ADD_NAME(ctx, __constructor); + ADD_NAME(ctx, __operator); + ADD_NAME_STR(ctx, ___asm, "__asm"); + + ADD_NAME_STR(ctx, _if, "if"); + ADD_NAME_STR(ctx, _else, "else"); + ADD_NAME_STR(ctx, _for, "for"); + ADD_NAME_STR(ctx, _while, "while"); + ADD_NAME_STR(ctx, _do, "do"); + + ADD_NAME_STR(ctx, _continue, "continue"); + ADD_NAME_STR(ctx, _break, "break"); + ADD_NAME_STR(ctx, _return, "return"); + ADD_NAME(ctx, discard); + + ADD_NAME_STR(ctx, _false, "false"); + ADD_NAME_STR(ctx, _true, "true"); + + ctx.out_buf = NULL; + ctx.out_cap = 0; + + ctx.shader_type = shader_type; + ctx.parsing_builtin = 1; + + ps.in = 0; + ps.out = 0; + + if (_parse_translation_unit(&ctx, &ps)) { + return -1; + } + + *output = ctx.out_buf; + *cboutput = ps.out; + return 0; +} -- cgit v1.2.3 From 99c89ebdb00ff0452f4b106cd53ec4a2e5162137 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Fri, 13 Nov 2009 19:51:02 +0100 Subject: glsl/cl: Add simple error reporting. --- src/glsl/cl/sl_cl_parse.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- src/glsl/cl/sl_cl_parse.h | 5 ++- 2 files changed, 74 insertions(+), 8 deletions(-) (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index 06224b31ec..5919186c52 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -330,6 +330,8 @@ struct parse_context { unsigned int shader_type; unsigned int parsing_builtin; + + char error[256]; }; @@ -362,6 +364,16 @@ _update(struct parse_context *ctx, } +static void +_error(struct parse_context *ctx, + char *msg) +{ + if (ctx->error[0] == '\0') { + strcpy(ctx->error, msg); + } +} + + static int _parse_token(struct parse_context *ctx, enum sl_pp_token token, @@ -648,10 +660,12 @@ _parse_struct_declarator(struct parse_context *ctx, return 0; } if (_parse_constant_expression(ctx, &p)) { - return 0; + _error(ctx, "expected constant integral expression"); + return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { - return 0; + _error(ctx, "expected `]'"); + return -1; } _update(ctx, e, FIELD_ARRAY); *ps = p; @@ -736,6 +750,7 @@ _parse_struct_specifier(struct parse_context *ctx, _emit(ctx, &p.out, '\0'); } if (_parse_token(ctx, SL_PP_LBRACE, &p)) { + _error(ctx, "expected `{'"); return -1; } if (_parse_struct_declaration_list(ctx, &p)) { @@ -853,9 +868,11 @@ _parse_type_specifier_array(struct parse_context *ctx, return -1; } if (_parse_constant_expression(ctx, &p)) { + _error(ctx, "expected constant integral expression"); return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + _error(ctx, "expected `]'"); return -1; } *ps = p; @@ -963,10 +980,12 @@ _parse_function_identifier(struct parse_context *ctx, return 0; } if (_parse_constant_expression(ctx, &p)) { - return 0; + _error(ctx, "expected constant integral expression"); + return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { - return 0; + _error(ctx, "expected `]'"); + return -1; } _update(ctx, e, FUNCTION_CALL_ARRAY); *ps = p; @@ -1091,6 +1110,8 @@ _parse_function_call_generic(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected `)'"); + return -1; } p = *ps; @@ -1099,6 +1120,8 @@ _parse_function_call_generic(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected `)'"); + return -1; } return -1; @@ -1202,10 +1225,12 @@ _parse_postfix_expression(struct parse_context *ctx, _emit(ctx, &p.out, OP_POSTDECREMENT); } else if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) { if (_parse_expression(ctx, &p)) { - return 0; + _error(ctx, "expected an integral expression"); + return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { - return 0; + _error(ctx, "expected `]'"); + return -1; } _emit(ctx, &p.out, OP_SUBSCRIPT); } else if (_parse_token(ctx, SL_PP_DOT, &p) == 0) { @@ -1487,9 +1512,11 @@ _parse_parameter_declarator_array(struct parse_context *ctx, return -1; } if (_parse_constant_expression(ctx, &p)) { + _error(ctx, "expected constant integral expression"); return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + _error(ctx, "expected `]'"); return -1; } *ps = p; @@ -1529,9 +1556,11 @@ _parse_parameter_type_specifier_array(struct parse_context *ctx, return -1; } if (_parse_constant_expression(ctx, &p)) { + _error(ctx, "expected constant integral expression"); return -1; } if (_parse_token(ctx, SL_PP_RBRACKET, &p)) { + _error(ctx, "expected `]'"); return -1; } *ps = p; @@ -1641,6 +1670,8 @@ _parse_function_prototype(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected `)'"); + return -1; } } @@ -1651,6 +1682,8 @@ _parse_function_prototype(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected `)'"); + return -1; } return -1; @@ -1937,12 +1970,15 @@ _parse_selection_statement(struct parse_context *ctx, return -1; } if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + _error(ctx, "expected `('"); return -1; } if (_parse_expression(ctx, &p)) { + _error(ctx, "expected an expression"); return -1; } if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + _error(ctx, "expected `)'"); return -1; } _emit(ctx, &p.out, OP_END); @@ -2033,10 +2069,12 @@ _parse_condition_initializer(struct parse_context *ctx, return -1; } if (_parse_token(ctx, SL_PP_ASSIGN, &p)) { + _error(ctx, "expected `='"); return -1; } _emit(ctx, &p.out, VARIABLE_INITIALIZER); if (_parse_initializer(ctx, &p)) { + _error(ctx, "expected an initialiser"); return -1; } _emit(ctx, &p.out, DECLARATOR_NONE); @@ -2102,12 +2140,15 @@ _parse_iteration_statement(struct parse_context *ctx, if (_parse_id(ctx, ctx->dict._while, &p) == 0) { _emit(ctx, &p.out, OP_WHILE); if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + _error(ctx, "expected `('"); return -1; } if (_parse_condition(ctx, &p)) { + _error(ctx, "expected an expression"); return -1; } if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + _error(ctx, "expected `)'"); return -1; } if (_parse_statement(ctx, &p)) { @@ -2126,16 +2167,20 @@ _parse_iteration_statement(struct parse_context *ctx, return -1; } if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + _error(ctx, "expected `('"); return -1; } if (_parse_expression(ctx, &p)) { + _error(ctx, "expected an expression"); return -1; } if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + _error(ctx, "expected `)'"); return -1; } _emit(ctx, &p.out, OP_END); if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + _error(ctx, "expected `;'"); return -1; } *ps = p; @@ -2145,6 +2190,7 @@ _parse_iteration_statement(struct parse_context *ctx, if (_parse_id(ctx, ctx->dict._for, &p) == 0) { _emit(ctx, &p.out, OP_FOR); if (_parse_token(ctx, SL_PP_LPAREN, &p)) { + _error(ctx, "expected `('"); return -1; } if (_parse_for_init_statement(ctx, &p)) { @@ -2154,6 +2200,7 @@ _parse_iteration_statement(struct parse_context *ctx, return -1; } if (_parse_token(ctx, SL_PP_RPAREN, &p)) { + _error(ctx, "expected `)'"); return -1; } if (_parse_statement(ctx, &p)) { @@ -2384,6 +2431,8 @@ _parse_single_declaration(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected an initialiser"); + return -1; } p = *ps; @@ -2397,6 +2446,8 @@ _parse_single_declaration(struct parse_context *ctx, *ps = p; return 0; } + _error(ctx, "expected `]'"); + return -1; } return 0; } @@ -2434,6 +2485,8 @@ _parse_init_declarator_list(struct parse_context *ctx, *ps = p; continue; } + _error(ctx, "expected an initialiser"); + break; } p = *ps; @@ -2450,6 +2503,8 @@ _parse_init_declarator_list(struct parse_context *ctx, *ps = p; continue; } + _error(ctx, "expected `]'"); + break; } p = *ps; } @@ -2473,6 +2528,7 @@ _parse_declaration(struct parse_context *ctx, _update(ctx, e, DECLARATION_INIT_DECLARATOR_LIST); } if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) { + _error(ctx, "expected `;'"); return -1; } *ps = p; @@ -2511,6 +2567,7 @@ _parse_external_declaration(struct parse_context *ctx, return 0; } + _error(ctx, "expected an identifier"); return -1; } @@ -2548,8 +2605,11 @@ int sl_cl_compile(struct sl_pp_context *context, const struct sl_pp_token_info *input, unsigned int shader_type, + unsigned int parsing_builtin, unsigned char **output, - unsigned int *cboutput) + unsigned int *cboutput, + char *error, + unsigned int cberror) { struct parse_context ctx; struct parse_state ps; @@ -2634,10 +2694,13 @@ sl_cl_compile(struct sl_pp_context *context, ctx.shader_type = shader_type; ctx.parsing_builtin = 1; + ctx.error[0] = '\0'; + ps.in = 0; ps.out = 0; if (_parse_translation_unit(&ctx, &ps)) { + strncpy(error, ctx.error, cberror); return -1; } diff --git a/src/glsl/cl/sl_cl_parse.h b/src/glsl/cl/sl_cl_parse.h index 5b4abe54fd..23a0d5fee0 100644 --- a/src/glsl/cl/sl_cl_parse.h +++ b/src/glsl/cl/sl_cl_parse.h @@ -32,7 +32,10 @@ int sl_cl_compile(struct sl_pp_context *context, const struct sl_pp_token_info *input, unsigned int shader_type, + unsigned int parsing_builtin, unsigned char **output, - unsigned int *cboutput); + unsigned int *cboutput, + char *error, + unsigned int cberror); #endif /* SL_CL_PARSE_H */ -- cgit v1.2.3 From 7502b6affa72915cadeb0837028e7655e459da69 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 10 Dec 2009 08:24:45 -0700 Subject: glsl/cl: silence unused var warning --- src/glsl/cl/sl_cl_parse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index 5919186c52..81e30a8c28 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -1596,6 +1596,8 @@ _parse_parameter_declaration(struct parse_context *ctx, struct parse_state p = *ps; unsigned int e = _emit(ctx, &p.out, PARAMETER_NEXT); + (void) e; + if (_parse_type_qualifier(ctx, &p)) { _emit(ctx, &p.out, TYPE_QUALIFIER_NONE); } -- cgit v1.2.3 From 289eab5389c0f0f3f85f872b2ba440f5e8416a50 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 10 Dec 2009 09:16:20 -0700 Subject: glsl/sl: fix _parse_boolconstant() Need to emit the radix before the digits. This fixes several glean/glgl1 regressions. --- src/glsl/cl/sl_cl_parse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index 81e30a8c28..a9db65c7ad 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -1821,6 +1821,7 @@ _parse_boolconstant(struct parse_context *ctx, { if (_parse_id(ctx, ctx->dict._false, ps) == 0) { _emit(ctx, &ps->out, OP_PUSH_BOOL); + _emit(ctx, &ps->out, 2); /* radix */ _emit(ctx, &ps->out, '0'); _emit(ctx, &ps->out, '\0'); return 0; @@ -1828,6 +1829,7 @@ _parse_boolconstant(struct parse_context *ctx, if (_parse_id(ctx, ctx->dict._true, ps) == 0) { _emit(ctx, &ps->out, OP_PUSH_BOOL); + _emit(ctx, &ps->out, 2); /* radix */ _emit(ctx, &ps->out, '1'); _emit(ctx, &ps->out, '\0'); return 0; -- cgit v1.2.3 From d801c296c602d04055b02b3be2f1369bfe1092b7 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Sun, 20 Dec 2009 21:11:16 +0100 Subject: glsl: Do syntax parsing inline with processing. --- src/glsl/cl/sl_cl_parse.c | 151 ++++++++++++++++++++++++++++++++++++------ src/glsl/cl/sl_cl_parse.h | 1 - src/glsl/pp/sl_pp_context.c | 3 + src/glsl/pp/sl_pp_context.h | 3 + src/glsl/pp/sl_pp_define.c | 1 + src/glsl/pp/sl_pp_error.c | 1 + src/glsl/pp/sl_pp_extension.c | 1 + src/glsl/pp/sl_pp_line.c | 1 + src/glsl/pp/sl_pp_macro.c | 1 + src/glsl/pp/sl_pp_pragma.c | 1 + src/glsl/pp/sl_pp_process.c | 116 +++++++++++++++++++++----------- src/glsl/pp/sl_pp_process.h | 3 +- src/glsl/pp/sl_pp_public.h | 4 ++ 13 files changed, 225 insertions(+), 62 deletions(-) (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index a9db65c7ad..5dddf434e1 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -321,10 +321,13 @@ struct parse_dict { struct parse_context { struct sl_pp_context *context; - const struct sl_pp_token_info *input; struct parse_dict dict; + struct sl_pp_token_info *tokens; + unsigned int tokens_read; + unsigned int tokens_cap; + unsigned char *out_buf; unsigned int out_cap; @@ -332,6 +335,7 @@ struct parse_context { unsigned int parsing_builtin; char error[256]; + int process_error; }; @@ -366,7 +370,7 @@ _update(struct parse_context *ctx, static void _error(struct parse_context *ctx, - char *msg) + const char *msg) { if (ctx->error[0] == '\0') { strcpy(ctx->error, msg); @@ -374,12 +378,96 @@ _error(struct parse_context *ctx, } +static const struct sl_pp_token_info * +_fetch_token(struct parse_context *ctx, + unsigned int pos) +{ + if (ctx->process_error) { + return NULL; + } + + while (pos >= ctx->tokens_read) { + if (ctx->tokens_read == ctx->tokens_cap) { + ctx->tokens_cap += 1024; + ctx->tokens = realloc(ctx->tokens, + ctx->tokens_cap * sizeof(struct sl_pp_token_info)); + if (!ctx->tokens) { + _error(ctx, "out of memory"); + ctx->process_error = 1; + return NULL; + } + } + if (sl_pp_process_get(ctx->context, &ctx->tokens[ctx->tokens_read])) { + _error(ctx, sl_pp_context_error_message(ctx->context)); + ctx->process_error = 1; + return NULL; + } + switch (ctx->tokens[ctx->tokens_read].token) { + case SL_PP_COMMA: + case SL_PP_SEMICOLON: + case SL_PP_LBRACE: + case SL_PP_RBRACE: + case SL_PP_LPAREN: + case SL_PP_RPAREN: + case SL_PP_LBRACKET: + case SL_PP_RBRACKET: + case SL_PP_DOT: + case SL_PP_INCREMENT: + case SL_PP_ADDASSIGN: + case SL_PP_PLUS: + case SL_PP_DECREMENT: + case SL_PP_SUBASSIGN: + case SL_PP_MINUS: + case SL_PP_BITNOT: + case SL_PP_NOTEQUAL: + case SL_PP_NOT: + case SL_PP_MULASSIGN: + case SL_PP_STAR: + case SL_PP_DIVASSIGN: + case SL_PP_SLASH: + case SL_PP_MODASSIGN: + case SL_PP_MODULO: + case SL_PP_LSHIFTASSIGN: + case SL_PP_LSHIFT: + case SL_PP_LESSEQUAL: + case SL_PP_LESS: + case SL_PP_RSHIFTASSIGN: + case SL_PP_RSHIFT: + case SL_PP_GREATEREQUAL: + case SL_PP_GREATER: + case SL_PP_EQUAL: + case SL_PP_ASSIGN: + case SL_PP_AND: + case SL_PP_BITANDASSIGN: + case SL_PP_BITAND: + case SL_PP_XOR: + case SL_PP_BITXORASSIGN: + case SL_PP_BITXOR: + case SL_PP_OR: + case SL_PP_BITORASSIGN: + case SL_PP_BITOR: + case SL_PP_QUESTION: + case SL_PP_COLON: + case SL_PP_IDENTIFIER: + case SL_PP_UINT: + case SL_PP_FLOAT: + case SL_PP_EOF: + ctx->tokens_read++; + break; + } + } + return &ctx->tokens[pos]; +} + + static int _parse_token(struct parse_context *ctx, enum sl_pp_token token, struct parse_state *ps) { - if (ctx->input[ps->in].token == token) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == token) { ps->in++; return 0; } @@ -392,8 +480,9 @@ _parse_id(struct parse_context *ctx, int id, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_IDENTIFIER && - ctx->input[ps->in].data.identifier == id) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_IDENTIFIER && input->data.identifier == id) { ps->in++; return 0; } @@ -405,8 +494,10 @@ static int _parse_identifier(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_IDENTIFIER) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data.identifier); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_IDENTIFIER) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data.identifier); do { _emit(ctx, &ps->out, *cstr); @@ -422,8 +513,10 @@ static int _parse_float(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_FLOAT) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._float); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_FLOAT) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data._float); _emit(ctx, &ps->out, 1); do { @@ -440,8 +533,10 @@ static int _parse_uint(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_UINT) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._uint); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_UINT) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data._uint); _emit(ctx, &ps->out, 1); do { @@ -614,13 +709,14 @@ _parse_type_qualifier(struct parse_context *ctx, struct parse_state *ps) { struct parse_state p = *ps; + const struct sl_pp_token_info *input = _fetch_token(ctx, p.in); unsigned int e = _emit(ctx, &p.out, 0); int id; - if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[p.in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._const) { _update(ctx, e, TYPE_QUALIFIER_CONST); @@ -771,6 +867,7 @@ _parse_type_specifier_nonarray(struct parse_context *ctx, { struct parse_state p = *ps; unsigned int e = _emit(ctx, &p.out, 0); + const struct sl_pp_token_info *input; int id; if (_parse_struct_specifier(ctx, &p) == 0) { @@ -779,10 +876,11 @@ _parse_type_specifier_nonarray(struct parse_context *ctx, return 0; } - if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + input = _fetch_token(ctx, p.in); + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[p.in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._void) { _update(ctx, e, TYPE_SPECIFIER_VOID); @@ -1696,13 +1794,14 @@ static int _parse_precision(struct parse_context *ctx, struct parse_state *ps) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); int id; unsigned int precision; - if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[ps->in].data.identifier; + id = input->data.identifier; if (id == ctx->dict.lowp) { precision = PRECISION_LOW; @@ -1724,13 +1823,14 @@ static int _parse_prectype(struct parse_context *ctx, struct parse_state *ps) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); int id; unsigned int type; - if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[ps->in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._int) { type = TYPE_SPECIFIER_INT; @@ -2607,7 +2707,6 @@ _parse_translation_unit(struct parse_context *ctx, int sl_cl_compile(struct sl_pp_context *context, - const struct sl_pp_token_info *input, unsigned int shader_type, unsigned int parsing_builtin, unsigned char **output, @@ -2619,7 +2718,6 @@ sl_cl_compile(struct sl_pp_context *context, struct parse_state ps; ctx.context = context; - ctx.input = input; ADD_NAME_STR(ctx, _void, "void"); ADD_NAME_STR(ctx, _float, "float"); @@ -2699,16 +2797,27 @@ sl_cl_compile(struct sl_pp_context *context, ctx.parsing_builtin = 1; ctx.error[0] = '\0'; + ctx.process_error = 0; + + ctx.tokens_cap = 1024; + ctx.tokens_read = 0; + ctx.tokens = malloc(ctx.tokens_cap * sizeof(struct sl_pp_token_info)); + if (!ctx.tokens) { + strncpy(error, "out of memory", cberror); + return -1; + } ps.in = 0; ps.out = 0; if (_parse_translation_unit(&ctx, &ps)) { strncpy(error, ctx.error, cberror); + free(ctx.tokens); return -1; } *output = ctx.out_buf; *cboutput = ps.out; + free(ctx.tokens); return 0; } diff --git a/src/glsl/cl/sl_cl_parse.h b/src/glsl/cl/sl_cl_parse.h index 23a0d5fee0..dd5791d590 100644 --- a/src/glsl/cl/sl_cl_parse.h +++ b/src/glsl/cl/sl_cl_parse.h @@ -30,7 +30,6 @@ int sl_cl_compile(struct sl_pp_context *context, - const struct sl_pp_token_info *input, unsigned int shader_type, unsigned int parsing_builtin, unsigned char **output, diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c index c1cef41bce..74a9bdddfd 100644 --- a/src/glsl/pp/sl_pp_context.c +++ b/src/glsl/pp/sl_pp_context.c @@ -69,6 +69,8 @@ sl_pp_context_create(const char *input, sl_pp_purify_state_init(&context->pure, input, options); + memset(&context->process_state, 0, sizeof(context->process_state)); + return context; } @@ -80,6 +82,7 @@ sl_pp_context_destroy(struct sl_pp_context *context) sl_pp_macro_free(context->macro); free(context->getc_buf); sl_pp_token_buffer_destroy(&context->tokens); + free(context->process_state.out); free(context); } } diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h index 5e1c563048..3eada380cd 100644 --- a/src/glsl/pp/sl_pp_context.h +++ b/src/glsl/pp/sl_pp_context.h @@ -30,6 +30,7 @@ #include "sl_pp_dict.h" #include "sl_pp_macro.h" +#include "sl_pp_process.h" #include "sl_pp_purify.h" #include "sl_pp_token_util.h" @@ -84,6 +85,8 @@ struct sl_pp_context { unsigned int getc_buf_capacity; struct sl_pp_token_buffer tokens; + + struct sl_pp_process_state process_state; }; #endif /* SL_PP_CONTEXT_H */ diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c index e004c9f95b..808a6a0d4f 100644 --- a/src/glsl/pp/sl_pp_define.c +++ b/src/glsl/pp/sl_pp_define.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_error.c b/src/glsl/pp/sl_pp_error.c index a9eeff98ba..b628e37ce8 100644 --- a/src/glsl/pp/sl_pp_error.c +++ b/src/glsl/pp/sl_pp_error.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_extension.c b/src/glsl/pp/sl_pp_extension.c index 67b24404d4..8af5731e84 100644 --- a/src/glsl/pp/sl_pp_extension.c +++ b/src/glsl/pp/sl_pp_extension.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_line.c b/src/glsl/pp/sl_pp_line.c index 87987fc2ba..6f7e9eb562 100644 --- a/src/glsl/pp/sl_pp_line.c +++ b/src/glsl/pp/sl_pp_line.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_public.h" #include "sl_pp_process.h" diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c index c98ab6559a..9f520b8fc5 100644 --- a/src/glsl/pp/sl_pp_macro.c +++ b/src/glsl/pp/sl_pp_macro.c @@ -28,6 +28,7 @@ #include #include #include +#include "sl_pp_context.h" #include "sl_pp_public.h" #include "sl_pp_macro.h" #include "sl_pp_process.h" diff --git a/src/glsl/pp/sl_pp_pragma.c b/src/glsl/pp/sl_pp_pragma.c index 489eb17b8e..caf4c63f65 100644 --- a/src/glsl/pp/sl_pp_pragma.c +++ b/src/glsl/pp/sl_pp_pragma.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_process.h" diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c index 6dcd0ab401..563ea948e7 100644 --- a/src/glsl/pp/sl_pp_process.c +++ b/src/glsl/pp/sl_pp_process.c @@ -27,6 +27,7 @@ #include #include +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" @@ -58,34 +59,47 @@ sl_pp_process_out(struct sl_pp_process_state *state, } int -sl_pp_process(struct sl_pp_context *context, - struct sl_pp_token_info **output) +sl_pp_process_get(struct sl_pp_context *context, + struct sl_pp_token_info *output) { - struct sl_pp_process_state state; - int found_eof = 0; - - memset(&state, 0, sizeof(state)); - - if (context->line > 1) { - struct sl_pp_token_info ti; - - ti.token = SL_PP_LINE; - ti.data.line.lineno = context->line - 1; - ti.data.line.fileno = context->file; - if (sl_pp_process_out(&state, &ti)) { - strcpy(context->error_msg, "out of memory"); - return -1; - } + if (!context->process_state.out) { + if (context->line > 1) { + struct sl_pp_token_info ti; + + ti.token = SL_PP_LINE; + ti.data.line.lineno = context->line - 1; + ti.data.line.fileno = context->file; + if (sl_pp_process_out(&context->process_state, &ti)) { + strcpy(context->error_msg, "out of memory"); + return -1; + } - ti.token = SL_PP_NEWLINE; - if (sl_pp_process_out(&state, &ti)) { - strcpy(context->error_msg, "out of memory"); - return -1; + ti.token = SL_PP_NEWLINE; + if (sl_pp_process_out(&context->process_state, &ti)) { + strcpy(context->error_msg, "out of memory"); + return -1; + } } } - while (!found_eof) { + for (;;) { struct sl_pp_token_info input; + int found_eof = 0; + + if (context->process_state.out_len) { + *output = context->process_state.out[0]; + + if (context->process_state.out_len > 1) { + unsigned int i; + + for (i = 1; i < context->process_state.out_len; i++) { + context->process_state.out[i - 1] = context->process_state.out[i]; + } + } + context->process_state.out_len--; + + return 0; + } if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) { return -1; @@ -101,7 +115,7 @@ sl_pp_process(struct sl_pp_context *context, int found_eol = 0; struct sl_pp_token_info endof; struct sl_pp_token_peek peek; - int result; + int result = 0; /* Directive name. */ name = input.data.identifier; @@ -166,17 +180,17 @@ sl_pp_process(struct sl_pp_context *context, sl_pp_process_error(context, peek.tokens, 0, peek.size - 1); result = -1; } else if (name == context->dict.extension) { - result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &state); + result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &context->process_state); } else if (name == context->dict.line) { struct sl_pp_token_buffer buffer; result = sl_pp_token_peek_to_buffer(&peek, &buffer); if (result == 0) { - result = sl_pp_process_line(context, &buffer, &state); + result = sl_pp_process_line(context, &buffer, &context->process_state); sl_pp_token_buffer_destroy(&buffer); } } else if (name == context->dict.pragma) { - result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &state); + result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &context->process_state); } else if (name == context->dict.undef) { result = sl_pp_process_undef(context, peek.tokens, 0, peek.size - 1); } else { @@ -192,7 +206,7 @@ sl_pp_process(struct sl_pp_context *context, return result; } - if (sl_pp_process_out(&state, &endof)) { + if (sl_pp_process_out(&context->process_state, &endof)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -202,7 +216,7 @@ sl_pp_process(struct sl_pp_context *context, case SL_PP_NEWLINE: /* Empty directive. */ - if (sl_pp_process_out(&state, &input)) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -211,7 +225,7 @@ sl_pp_process(struct sl_pp_context *context, case SL_PP_EOF: /* Empty directive. */ - if (sl_pp_process_out(&state, &input)) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -239,7 +253,7 @@ sl_pp_process(struct sl_pp_context *context, case SL_PP_NEWLINE: /* Preserve newline just for the sake of line numbering. */ - if (sl_pp_process_out(&state, &input)) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -248,7 +262,7 @@ sl_pp_process(struct sl_pp_context *context, break; case SL_PP_EOF: - if (sl_pp_process_out(&state, &input)) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -258,7 +272,7 @@ sl_pp_process(struct sl_pp_context *context, case SL_PP_IDENTIFIER: sl_pp_token_buffer_unget(&context->tokens, &input); - if (sl_pp_macro_expand(context, &context->tokens, NULL, &state, + if (sl_pp_macro_expand(context, &context->tokens, NULL, &context->process_state, context->if_value ? sl_pp_macro_expand_normal : sl_pp_macro_expand_mute)) { return -1; } @@ -266,7 +280,7 @@ sl_pp_process(struct sl_pp_context *context, default: if (context->if_value) { - if (sl_pp_process_out(&state, &input)) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -274,13 +288,37 @@ sl_pp_process(struct sl_pp_context *context, } } } - } - if (context->if_ptr != SL_PP_MAX_IF_NESTING) { - strcpy(context->error_msg, "expected `#endif' directive"); - return -1; + if (found_eof) { + if (context->if_ptr != SL_PP_MAX_IF_NESTING) { + strcpy(context->error_msg, "expected `#endif' directive"); + return -1; + } + } } +} - *output = state.out; - return 0; +int +sl_pp_process(struct sl_pp_context *context, + struct sl_pp_token_info **output) +{ + struct sl_pp_process_state state; + + memset(&state, 0, sizeof(state)); + for (;;) { + struct sl_pp_token_info input; + + if (sl_pp_process_get(context, &input)) { + free(state.out); + return -1; + } + if (sl_pp_process_out(&state, &input)) { + free(state.out); + return -1; + } + if (input.token == SL_PP_EOF) { + *output = state.out; + return 0; + } + } } diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h index 31defd911a..fe6ff0d464 100644 --- a/src/glsl/pp/sl_pp_process.h +++ b/src/glsl/pp/sl_pp_process.h @@ -28,11 +28,12 @@ #ifndef SL_PP_PROCESS_H #define SL_PP_PROCESS_H -#include "sl_pp_context.h" #include "sl_pp_macro.h" #include "sl_pp_token.h" +struct sl_pp_context; + struct sl_pp_process_state { struct sl_pp_token_info *out; unsigned int out_len; diff --git a/src/glsl/pp/sl_pp_public.h b/src/glsl/pp/sl_pp_public.h index 309a70c07f..12528d6f8d 100644 --- a/src/glsl/pp/sl_pp_public.h +++ b/src/glsl/pp/sl_pp_public.h @@ -73,6 +73,10 @@ int sl_pp_version(struct sl_pp_context *context, unsigned int *version); +int +sl_pp_process_get(struct sl_pp_context *context, + struct sl_pp_token_info *output); + int sl_pp_process(struct sl_pp_context *context, struct sl_pp_token_info **output); -- cgit v1.2.3 From 561a107df71aace22a15003cc77dd504ab8b06a0 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 29 Dec 2009 08:47:40 -0700 Subject: glsl: added default case in _fetch_token() to silence warnings --- src/glsl/cl/sl_cl_parse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/glsl/cl/sl_cl_parse.c') diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index 5dddf434e1..e9b3707ac1 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -454,6 +454,8 @@ _fetch_token(struct parse_context *ctx, case SL_PP_EOF: ctx->tokens_read++; break; + default: + ; /* no-op */ } } return &ctx->tokens[pos]; -- cgit v1.2.3