aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesalib/src/glsl/ast.h1464
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp6848
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.c8430
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y3778
-rw-r--r--mesalib/src/glsl/glsl_lexer.cpp7435
-rw-r--r--mesalib/src/glsl/glsl_lexer.lpp879
-rw-r--r--mesalib/src/glsl/glsl_parser.cpp311
-rw-r--r--mesalib/src/glsl/glsl_parser.ypp39
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp7
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h500
-rw-r--r--mesalib/src/glsl/ir.cpp3105
-rw-r--r--mesalib/src/glsl/ir.h3257
-rw-r--r--mesalib/src/glsl/linker.cpp26
-rw-r--r--mesalib/src/mesa/main/extensions.c114
-rw-r--r--mesalib/src/mesa/main/mtypes.h19
-rw-r--r--mesalib/src/mesa/main/texformat.c1205
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp88
-rw-r--r--pixman/configure.ac23
-rw-r--r--pixman/pixman/pixman-arm-neon.c865
-rw-r--r--pixman/pixman/pixman-arm-simd.c847
-rw-r--r--pixman/pixman/pixman-cpu.c30
-rw-r--r--pixman/pixman/pixman-fast-path.c3871
-rw-r--r--pixman/pixman/pixman-mmx.c5
-rw-r--r--pixman/pixman/pixman-private.h12
-rw-r--r--pixman/pixman/pixman-sse2.c7
-rw-r--r--pixman/pixman/pixman-vmx.c5
26 files changed, 21710 insertions, 21460 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h
index ab28aff0f..b2e19169e 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -1,728 +1,736 @@
-/* -*- c++ -*- */
-/*
- * Copyright © 2009 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#pragma once
-#ifndef AST_H
-#define AST_H
-
-#include "list.h"
-#include "glsl_parser_extras.h"
-
-struct _mesa_glsl_parse_state;
-
-struct YYLTYPE;
-
-/**
- * \defgroup AST Abstract syntax tree node definitions
- *
- * An abstract syntax tree is generated by the parser. This is a fairly
- * direct representation of the gramma derivation for the source program.
- * No symantic checking is done during the generation of the AST. Only
- * syntactic checking is done. Symantic checking is performed by a later
- * stage that converts the AST to a more generic intermediate representation.
- *
- *@{
- */
-/**
- * Base class of all abstract syntax tree nodes
- */
-class ast_node {
-public:
- /* Callers of this talloc-based new need not call delete. It's
- * easier to just talloc_free 'ctx' (or any of its ancestors). */
- static void* operator new(size_t size, void *ctx)
- {
- void *node;
-
- node = talloc_zero_size(ctx, size);
- assert(node != NULL);
-
- return node;
- }
-
- /* If the user *does* call delete, that's OK, we will just
- * talloc_free in that case. */
- static void operator delete(void *table)
- {
- talloc_free(table);
- }
-
- /**
- * Print an AST node in something approximating the original GLSL code
- */
- virtual void print(void) const;
-
- /**
- * Convert the AST node to the high-level intermediate representation
- */
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- /**
- * Retrieve the source location of an AST node
- *
- * This function is primarily used to get the source position of an AST node
- * into a form that can be passed to \c _mesa_glsl_error.
- *
- * \sa _mesa_glsl_error, ast_node::set_location
- */
- struct YYLTYPE get_location(void) const
- {
- struct YYLTYPE locp;
-
- locp.source = this->location.source;
- locp.first_line = this->location.line;
- locp.first_column = this->location.column;
- locp.last_line = locp.first_line;
- locp.last_column = locp.first_column;
-
- return locp;
- }
-
- /**
- * Set the source location of an AST node from a parser location
- *
- * \sa ast_node::get_location
- */
- void set_location(const struct YYLTYPE &locp)
- {
- this->location.source = locp.source;
- this->location.line = locp.first_line;
- this->location.column = locp.first_column;
- }
-
- /**
- * Source location of the AST node.
- */
- struct {
- unsigned source; /**< GLSL source number. */
- unsigned line; /**< Line number within the source string. */
- unsigned column; /**< Column in the line. */
- } location;
-
- exec_node link;
-
-protected:
- /**
- * The only constructor is protected so that only derived class objects can
- * be created.
- */
- ast_node(void);
-};
-
-
-/**
- * Operators for AST expression nodes.
- */
-enum ast_operators {
- ast_assign,
- ast_plus, /**< Unary + operator. */
- ast_neg,
- ast_add,
- ast_sub,
- ast_mul,
- ast_div,
- ast_mod,
- ast_lshift,
- ast_rshift,
- ast_less,
- ast_greater,
- ast_lequal,
- ast_gequal,
- ast_equal,
- ast_nequal,
- ast_bit_and,
- ast_bit_xor,
- ast_bit_or,
- ast_bit_not,
- ast_logic_and,
- ast_logic_xor,
- ast_logic_or,
- ast_logic_not,
-
- ast_mul_assign,
- ast_div_assign,
- ast_mod_assign,
- ast_add_assign,
- ast_sub_assign,
- ast_ls_assign,
- ast_rs_assign,
- ast_and_assign,
- ast_xor_assign,
- ast_or_assign,
-
- ast_conditional,
-
- ast_pre_inc,
- ast_pre_dec,
- ast_post_inc,
- ast_post_dec,
- ast_field_selection,
- ast_array_index,
-
- ast_function_call,
-
- ast_identifier,
- ast_int_constant,
- ast_uint_constant,
- ast_float_constant,
- ast_bool_constant,
-
- ast_sequence
-};
-
-/**
- * Representation of any sort of expression.
- */
-class ast_expression : public ast_node {
-public:
- ast_expression(int oper, ast_expression *,
- ast_expression *, ast_expression *);
-
- ast_expression(const char *identifier) :
- oper(ast_identifier)
- {
- subexpressions[0] = NULL;
- subexpressions[1] = NULL;
- subexpressions[2] = NULL;
- primary_expression.identifier = (char *) identifier;
- }
-
- static const char *operator_string(enum ast_operators op);
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- virtual void print(void) const;
-
- enum ast_operators oper;
-
- ast_expression *subexpressions[3];
-
- union {
- char *identifier;
- int int_constant;
- float float_constant;
- unsigned uint_constant;
- int bool_constant;
- } primary_expression;
-
-
- /**
- * List of expressions for an \c ast_sequence or parameters for an
- * \c ast_function_call
- */
- exec_list expressions;
-};
-
-class ast_expression_bin : public ast_expression {
-public:
- ast_expression_bin(int oper, ast_expression *, ast_expression *);
-
- virtual void print(void) const;
-};
-
-/**
- * Subclass of expressions for function calls
- */
-class ast_function_expression : public ast_expression {
-public:
- ast_function_expression(ast_expression *callee)
- : ast_expression(ast_function_call, callee,
- NULL, NULL),
- cons(false)
- {
- /* empty */
- }
-
- ast_function_expression(class ast_type_specifier *type)
- : ast_expression(ast_function_call, (ast_expression *) type,
- NULL, NULL),
- cons(true)
- {
- /* empty */
- }
-
- bool is_constructor() const
- {
- return cons;
- }
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
-private:
- /**
- * Is this function call actually a constructor?
- */
- bool cons;
-};
-
-
-/**
- * Number of possible operators for an ast_expression
- *
- * This is done as a define instead of as an additional value in the enum so
- * that the compiler won't generate spurious messages like "warning:
- * enumeration value ‘ast_num_operators’ not handled in switch"
- */
-#define AST_NUM_OPERATORS (ast_sequence + 1)
-
-
-class ast_compound_statement : public ast_node {
-public:
- ast_compound_statement(int new_scope, ast_node *statements);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- int new_scope;
- exec_list statements;
-};
-
-class ast_declaration : public ast_node {
-public:
- ast_declaration(char *identifier, int is_array, ast_expression *array_size,
- ast_expression *initializer);
- virtual void print(void) const;
-
- char *identifier;
-
- int is_array;
- ast_expression *array_size;
-
- ast_expression *initializer;
-};
-
-
-enum {
- ast_precision_none = 0, /**< Absence of precision qualifier. */
- ast_precision_high,
- ast_precision_medium,
- ast_precision_low
-};
-
-struct ast_type_qualifier {
- union {
- struct {
- unsigned invariant:1;
- unsigned constant:1;
- unsigned attribute:1;
- unsigned varying:1;
- unsigned in:1;
- unsigned out:1;
- unsigned centroid:1;
- unsigned uniform:1;
- unsigned smooth:1;
- unsigned flat:1;
- unsigned noperspective:1;
-
- /** \name Layout qualifiers for GL_ARB_fragment_coord_conventions */
- /*@{*/
- unsigned origin_upper_left:1;
- unsigned pixel_center_integer:1;
- /*@}*/
-
- /**
- * Flag set if GL_ARB_explicit_attrib_location "location" layout
- * qualifier is used.
- */
- unsigned explicit_location:1;
- }
- /** \brief Set of flags, accessed by name. */
- q;
-
- /** \brief Set of flags, accessed as a bitmask. */
- unsigned i;
- } flags;
-
- /**
- * Location specified via GL_ARB_explicit_attrib_location layout
- *
- * \note
- * This field is only valid if \c explicit_location is set.
- */
- unsigned location;
-
- /**
- * Return true if and only if an interpolation qualifier is present.
- */
- bool has_interpolation() const;
-
- /**
- * \brief Return string representation of interpolation qualifier.
- *
- * If an interpolation qualifier is present, then return that qualifier's
- * string representation. Otherwise, return null. For example, if the
- * noperspective bit is set, then this returns "noperspective".
- *
- * If multiple interpolation qualifiers are somehow present, then the
- * returned string is undefined but not null.
- */
- const char *interpolation_string() const;
-};
-
-class ast_struct_specifier : public ast_node {
-public:
- ast_struct_specifier(char *identifier, ast_node *declarator_list);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- char *name;
- exec_list declarations;
-};
-
-
-enum ast_types {
- ast_void,
- ast_float,
- ast_int,
- ast_uint,
- ast_bool,
- ast_vec2,
- ast_vec3,
- ast_vec4,
- ast_bvec2,
- ast_bvec3,
- ast_bvec4,
- ast_ivec2,
- ast_ivec3,
- ast_ivec4,
- ast_uvec2,
- ast_uvec3,
- ast_uvec4,
- ast_mat2,
- ast_mat2x3,
- ast_mat2x4,
- ast_mat3x2,
- ast_mat3,
- ast_mat3x4,
- ast_mat4x2,
- ast_mat4x3,
- ast_mat4,
- ast_sampler1d,
- ast_sampler2d,
- ast_sampler2drect,
- ast_sampler3d,
- ast_samplercube,
- ast_sampler1dshadow,
- ast_sampler2dshadow,
- ast_sampler2drectshadow,
- ast_samplercubeshadow,
- ast_sampler1darray,
- ast_sampler2darray,
- ast_sampler1darrayshadow,
- ast_sampler2darrayshadow,
- ast_isampler1d,
- ast_isampler2d,
- ast_isampler3d,
- ast_isamplercube,
- ast_isampler1darray,
- ast_isampler2darray,
- ast_usampler1d,
- ast_usampler2d,
- ast_usampler3d,
- ast_usamplercube,
- ast_usampler1darray,
- ast_usampler2darray,
-
- ast_struct,
- ast_type_name
-};
-
-
-class ast_type_specifier : public ast_node {
-public:
- ast_type_specifier(int specifier);
-
- /** Construct a type specifier from a type name */
- ast_type_specifier(const char *name)
- : type_specifier(ast_type_name), type_name(name), structure(NULL),
- is_array(false), array_size(NULL), precision(ast_precision_none),
- is_precision_statement(false)
- {
- /* empty */
- }
-
- /** Construct a type specifier from a structure definition */
- ast_type_specifier(ast_struct_specifier *s)
- : type_specifier(ast_struct), type_name(s->name), structure(s),
- is_array(false), array_size(NULL), precision(ast_precision_none),
- is_precision_statement(false)
- {
- /* empty */
- }
-
- const struct glsl_type *glsl_type(const char **name,
- struct _mesa_glsl_parse_state *state)
- const;
-
- virtual void print(void) const;
-
- ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
-
- enum ast_types type_specifier;
-
- const char *type_name;
- ast_struct_specifier *structure;
-
- int is_array;
- ast_expression *array_size;
-
- unsigned precision:2;
-
- bool is_precision_statement;
-};
-
-
-class ast_fully_specified_type : public ast_node {
-public:
- virtual void print(void) const;
- bool has_qualifiers() const;
-
- ast_type_qualifier qualifier;
- ast_type_specifier *specifier;
-};
-
-
-class ast_declarator_list : public ast_node {
-public:
- ast_declarator_list(ast_fully_specified_type *);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_fully_specified_type *type;
- exec_list declarations;
-
- /**
- * Special flag for vertex shader "invariant" declarations.
- *
- * Vertex shaders can contain "invariant" variable redeclarations that do
- * not include a type. For example, "invariant gl_Position;". This flag
- * is used to note these cases when no type is specified.
- */
- int invariant;
-};
-
-
-class ast_parameter_declarator : public ast_node {
-public:
- ast_parameter_declarator()
- {
- this->identifier = NULL;
- this->is_array = false;
- this->array_size = 0;
- }
-
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_fully_specified_type *type;
- char *identifier;
- int is_array;
- ast_expression *array_size;
-
- static void parameters_to_hir(exec_list *ast_parameters,
- bool formal, exec_list *ir_parameters,
- struct _mesa_glsl_parse_state *state);
-
-private:
- /** Is this parameter declaration part of a formal parameter list? */
- bool formal_parameter;
-
- /**
- * Is this parameter 'void' type?
- *
- * This field is set by \c ::hir.
- */
- bool is_void;
-};
-
-
-class ast_function : public ast_node {
-public:
- ast_function(void);
-
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_fully_specified_type *return_type;
- char *identifier;
-
- exec_list parameters;
-
-private:
- /**
- * Is this prototype part of the function definition?
- *
- * Used by ast_function_definition::hir to process the parameters, etc.
- * of the function.
- *
- * \sa ::hir
- */
- bool is_definition;
-
- /**
- * Function signature corresponding to this function prototype instance
- *
- * Used by ast_function_definition::hir to process the parameters, etc.
- * of the function.
- *
- * \sa ::hir
- */
- class ir_function_signature *signature;
-
- friend class ast_function_definition;
-};
-
-
-class ast_expression_statement : public ast_node {
-public:
- ast_expression_statement(ast_expression *);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_expression *expression;
-};
-
-
-class ast_case_label : public ast_node {
-public:
-
- /**
- * An expression of NULL means 'default'.
- */
- ast_expression *expression;
-};
-
-class ast_selection_statement : public ast_node {
-public:
- ast_selection_statement(ast_expression *condition,
- ast_node *then_statement,
- ast_node *else_statement);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_expression *condition;
- ast_node *then_statement;
- ast_node *else_statement;
-};
-
-
-class ast_switch_statement : public ast_node {
-public:
- ast_expression *expression;
- exec_list statements;
-};
-
-class ast_iteration_statement : public ast_node {
-public:
- ast_iteration_statement(int mode, ast_node *init, ast_node *condition,
- ast_expression *rest_expression, ast_node *body);
-
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
-
- enum ast_iteration_modes {
- ast_for,
- ast_while,
- ast_do_while
- } mode;
-
-
- ast_node *init_statement;
- ast_node *condition;
- ast_expression *rest_expression;
-
- ast_node *body;
-
-private:
- /**
- * Generate IR from the condition of a loop
- *
- * This is factored out of ::hir because some loops have the condition
- * test at the top (for and while), and others have it at the end (do-while).
- */
- void condition_to_hir(class ir_loop *, struct _mesa_glsl_parse_state *);
-};
-
-
-class ast_jump_statement : public ast_node {
-public:
- ast_jump_statement(int mode, ast_expression *return_value);
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- enum ast_jump_modes {
- ast_continue,
- ast_break,
- ast_return,
- ast_discard
- } mode;
-
- ast_expression *opt_return_value;
-};
-
-
-class ast_function_definition : public ast_node {
-public:
- virtual void print(void) const;
-
- virtual ir_rvalue *hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
- ast_function *prototype;
- ast_compound_statement *body;
-};
-/*@}*/
-
-extern void
-_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state);
-
-extern ir_rvalue *
-_mesa_ast_field_selection_to_hir(const ast_expression *expr,
- exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
-void
-emit_function(_mesa_glsl_parse_state *state, exec_list *instructions,
- ir_function *f);
-
-#endif /* AST_H */
+/* -*- c++ -*- */
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef AST_H
+#define AST_H
+
+#include "list.h"
+#include "glsl_parser_extras.h"
+
+struct _mesa_glsl_parse_state;
+
+struct YYLTYPE;
+
+/**
+ * \defgroup AST Abstract syntax tree node definitions
+ *
+ * An abstract syntax tree is generated by the parser. This is a fairly
+ * direct representation of the gramma derivation for the source program.
+ * No symantic checking is done during the generation of the AST. Only
+ * syntactic checking is done. Symantic checking is performed by a later
+ * stage that converts the AST to a more generic intermediate representation.
+ *
+ *@{
+ */
+/**
+ * Base class of all abstract syntax tree nodes
+ */
+class ast_node {
+public:
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *node;
+
+ node = talloc_zero_size(ctx, size);
+ assert(node != NULL);
+
+ return node;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *table)
+ {
+ talloc_free(table);
+ }
+
+ /**
+ * Print an AST node in something approximating the original GLSL code
+ */
+ virtual void print(void) const;
+
+ /**
+ * Convert the AST node to the high-level intermediate representation
+ */
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ /**
+ * Retrieve the source location of an AST node
+ *
+ * This function is primarily used to get the source position of an AST node
+ * into a form that can be passed to \c _mesa_glsl_error.
+ *
+ * \sa _mesa_glsl_error, ast_node::set_location
+ */
+ struct YYLTYPE get_location(void) const
+ {
+ struct YYLTYPE locp;
+
+ locp.source = this->location.source;
+ locp.first_line = this->location.line;
+ locp.first_column = this->location.column;
+ locp.last_line = locp.first_line;
+ locp.last_column = locp.first_column;
+
+ return locp;
+ }
+
+ /**
+ * Set the source location of an AST node from a parser location
+ *
+ * \sa ast_node::get_location
+ */
+ void set_location(const struct YYLTYPE &locp)
+ {
+ this->location.source = locp.source;
+ this->location.line = locp.first_line;
+ this->location.column = locp.first_column;
+ }
+
+ /**
+ * Source location of the AST node.
+ */
+ struct {
+ unsigned source; /**< GLSL source number. */
+ unsigned line; /**< Line number within the source string. */
+ unsigned column; /**< Column in the line. */
+ } location;
+
+ exec_node link;
+
+protected:
+ /**
+ * The only constructor is protected so that only derived class objects can
+ * be created.
+ */
+ ast_node(void);
+};
+
+
+/**
+ * Operators for AST expression nodes.
+ */
+enum ast_operators {
+ ast_assign,
+ ast_plus, /**< Unary + operator. */
+ ast_neg,
+ ast_add,
+ ast_sub,
+ ast_mul,
+ ast_div,
+ ast_mod,
+ ast_lshift,
+ ast_rshift,
+ ast_less,
+ ast_greater,
+ ast_lequal,
+ ast_gequal,
+ ast_equal,
+ ast_nequal,
+ ast_bit_and,
+ ast_bit_xor,
+ ast_bit_or,
+ ast_bit_not,
+ ast_logic_and,
+ ast_logic_xor,
+ ast_logic_or,
+ ast_logic_not,
+
+ ast_mul_assign,
+ ast_div_assign,
+ ast_mod_assign,
+ ast_add_assign,
+ ast_sub_assign,
+ ast_ls_assign,
+ ast_rs_assign,
+ ast_and_assign,
+ ast_xor_assign,
+ ast_or_assign,
+
+ ast_conditional,
+
+ ast_pre_inc,
+ ast_pre_dec,
+ ast_post_inc,
+ ast_post_dec,
+ ast_field_selection,
+ ast_array_index,
+
+ ast_function_call,
+
+ ast_identifier,
+ ast_int_constant,
+ ast_uint_constant,
+ ast_float_constant,
+ ast_bool_constant,
+
+ ast_sequence
+};
+
+/**
+ * Representation of any sort of expression.
+ */
+class ast_expression : public ast_node {
+public:
+ ast_expression(int oper, ast_expression *,
+ ast_expression *, ast_expression *);
+
+ ast_expression(const char *identifier) :
+ oper(ast_identifier)
+ {
+ subexpressions[0] = NULL;
+ subexpressions[1] = NULL;
+ subexpressions[2] = NULL;
+ primary_expression.identifier = (char *) identifier;
+ }
+
+ static const char *operator_string(enum ast_operators op);
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ virtual void print(void) const;
+
+ enum ast_operators oper;
+
+ ast_expression *subexpressions[3];
+
+ union {
+ char *identifier;
+ int int_constant;
+ float float_constant;
+ unsigned uint_constant;
+ int bool_constant;
+ } primary_expression;
+
+
+ /**
+ * List of expressions for an \c ast_sequence or parameters for an
+ * \c ast_function_call
+ */
+ exec_list expressions;
+};
+
+class ast_expression_bin : public ast_expression {
+public:
+ ast_expression_bin(int oper, ast_expression *, ast_expression *);
+
+ virtual void print(void) const;
+};
+
+/**
+ * Subclass of expressions for function calls
+ */
+class ast_function_expression : public ast_expression {
+public:
+ ast_function_expression(ast_expression *callee)
+ : ast_expression(ast_function_call, callee,
+ NULL, NULL),
+ cons(false)
+ {
+ /* empty */
+ }
+
+ ast_function_expression(class ast_type_specifier *type)
+ : ast_expression(ast_function_call, (ast_expression *) type,
+ NULL, NULL),
+ cons(true)
+ {
+ /* empty */
+ }
+
+ bool is_constructor() const
+ {
+ return cons;
+ }
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+private:
+ /**
+ * Is this function call actually a constructor?
+ */
+ bool cons;
+};
+
+
+/**
+ * Number of possible operators for an ast_expression
+ *
+ * This is done as a define instead of as an additional value in the enum so
+ * that the compiler won't generate spurious messages like "warning:
+ * enumeration value ‘ast_num_operators’ not handled in switch"
+ */
+#define AST_NUM_OPERATORS (ast_sequence + 1)
+
+
+class ast_compound_statement : public ast_node {
+public:
+ ast_compound_statement(int new_scope, ast_node *statements);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ int new_scope;
+ exec_list statements;
+};
+
+class ast_declaration : public ast_node {
+public:
+ ast_declaration(char *identifier, int is_array, ast_expression *array_size,
+ ast_expression *initializer);
+ virtual void print(void) const;
+
+ char *identifier;
+
+ int is_array;
+ ast_expression *array_size;
+
+ ast_expression *initializer;
+};
+
+
+enum {
+ ast_precision_none = 0, /**< Absence of precision qualifier. */
+ ast_precision_high,
+ ast_precision_medium,
+ ast_precision_low
+};
+
+struct ast_type_qualifier {
+ union {
+ struct {
+ unsigned invariant:1;
+ unsigned constant:1;
+ unsigned attribute:1;
+ unsigned varying:1;
+ unsigned in:1;
+ unsigned out:1;
+ unsigned centroid:1;
+ unsigned uniform:1;
+ unsigned smooth:1;
+ unsigned flat:1;
+ unsigned noperspective:1;
+
+ /** \name Layout qualifiers for GL_ARB_fragment_coord_conventions */
+ /*@{*/
+ unsigned origin_upper_left:1;
+ unsigned pixel_center_integer:1;
+ /*@}*/
+
+ /**
+ * Flag set if GL_ARB_explicit_attrib_location "location" layout
+ * qualifier is used.
+ */
+ unsigned explicit_location:1;
+
+ /** \name Layout qualifiers for GL_AMD_conservative_depth */
+ /** \{ */
+ unsigned depth_any:1;
+ unsigned depth_greater:1;
+ unsigned depth_less:1;
+ unsigned depth_unchanged:1;
+ /** \} */
+ }
+ /** \brief Set of flags, accessed by name. */
+ q;
+
+ /** \brief Set of flags, accessed as a bitmask. */
+ unsigned i;
+ } flags;
+
+ /**
+ * Location specified via GL_ARB_explicit_attrib_location layout
+ *
+ * \note
+ * This field is only valid if \c explicit_location is set.
+ */
+ unsigned location;
+
+ /**
+ * Return true if and only if an interpolation qualifier is present.
+ */
+ bool has_interpolation() const;
+
+ /**
+ * \brief Return string representation of interpolation qualifier.
+ *
+ * If an interpolation qualifier is present, then return that qualifier's
+ * string representation. Otherwise, return null. For example, if the
+ * noperspective bit is set, then this returns "noperspective".
+ *
+ * If multiple interpolation qualifiers are somehow present, then the
+ * returned string is undefined but not null.
+ */
+ const char *interpolation_string() const;
+};
+
+class ast_struct_specifier : public ast_node {
+public:
+ ast_struct_specifier(char *identifier, ast_node *declarator_list);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ char *name;
+ exec_list declarations;
+};
+
+
+enum ast_types {
+ ast_void,
+ ast_float,
+ ast_int,
+ ast_uint,
+ ast_bool,
+ ast_vec2,
+ ast_vec3,
+ ast_vec4,
+ ast_bvec2,
+ ast_bvec3,
+ ast_bvec4,
+ ast_ivec2,
+ ast_ivec3,
+ ast_ivec4,
+ ast_uvec2,
+ ast_uvec3,
+ ast_uvec4,
+ ast_mat2,
+ ast_mat2x3,
+ ast_mat2x4,
+ ast_mat3x2,
+ ast_mat3,
+ ast_mat3x4,
+ ast_mat4x2,
+ ast_mat4x3,
+ ast_mat4,
+ ast_sampler1d,
+ ast_sampler2d,
+ ast_sampler2drect,
+ ast_sampler3d,
+ ast_samplercube,
+ ast_sampler1dshadow,
+ ast_sampler2dshadow,
+ ast_sampler2drectshadow,
+ ast_samplercubeshadow,
+ ast_sampler1darray,
+ ast_sampler2darray,
+ ast_sampler1darrayshadow,
+ ast_sampler2darrayshadow,
+ ast_isampler1d,
+ ast_isampler2d,
+ ast_isampler3d,
+ ast_isamplercube,
+ ast_isampler1darray,
+ ast_isampler2darray,
+ ast_usampler1d,
+ ast_usampler2d,
+ ast_usampler3d,
+ ast_usamplercube,
+ ast_usampler1darray,
+ ast_usampler2darray,
+
+ ast_struct,
+ ast_type_name
+};
+
+
+class ast_type_specifier : public ast_node {
+public:
+ ast_type_specifier(int specifier);
+
+ /** Construct a type specifier from a type name */
+ ast_type_specifier(const char *name)
+ : type_specifier(ast_type_name), type_name(name), structure(NULL),
+ is_array(false), array_size(NULL), precision(ast_precision_none),
+ is_precision_statement(false)
+ {
+ /* empty */
+ }
+
+ /** Construct a type specifier from a structure definition */
+ ast_type_specifier(ast_struct_specifier *s)
+ : type_specifier(ast_struct), type_name(s->name), structure(s),
+ is_array(false), array_size(NULL), precision(ast_precision_none),
+ is_precision_statement(false)
+ {
+ /* empty */
+ }
+
+ const struct glsl_type *glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state)
+ const;
+
+ virtual void print(void) const;
+
+ ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+ enum ast_types type_specifier;
+
+ const char *type_name;
+ ast_struct_specifier *structure;
+
+ int is_array;
+ ast_expression *array_size;
+
+ unsigned precision:2;
+
+ bool is_precision_statement;
+};
+
+
+class ast_fully_specified_type : public ast_node {
+public:
+ virtual void print(void) const;
+ bool has_qualifiers() const;
+
+ ast_type_qualifier qualifier;
+ ast_type_specifier *specifier;
+};
+
+
+class ast_declarator_list : public ast_node {
+public:
+ ast_declarator_list(ast_fully_specified_type *);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *type;
+ exec_list declarations;
+
+ /**
+ * Special flag for vertex shader "invariant" declarations.
+ *
+ * Vertex shaders can contain "invariant" variable redeclarations that do
+ * not include a type. For example, "invariant gl_Position;". This flag
+ * is used to note these cases when no type is specified.
+ */
+ int invariant;
+};
+
+
+class ast_parameter_declarator : public ast_node {
+public:
+ ast_parameter_declarator()
+ {
+ this->identifier = NULL;
+ this->is_array = false;
+ this->array_size = 0;
+ }
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *type;
+ char *identifier;
+ int is_array;
+ ast_expression *array_size;
+
+ static void parameters_to_hir(exec_list *ast_parameters,
+ bool formal, exec_list *ir_parameters,
+ struct _mesa_glsl_parse_state *state);
+
+private:
+ /** Is this parameter declaration part of a formal parameter list? */
+ bool formal_parameter;
+
+ /**
+ * Is this parameter 'void' type?
+ *
+ * This field is set by \c ::hir.
+ */
+ bool is_void;
+};
+
+
+class ast_function : public ast_node {
+public:
+ ast_function(void);
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_fully_specified_type *return_type;
+ char *identifier;
+
+ exec_list parameters;
+
+private:
+ /**
+ * Is this prototype part of the function definition?
+ *
+ * Used by ast_function_definition::hir to process the parameters, etc.
+ * of the function.
+ *
+ * \sa ::hir
+ */
+ bool is_definition;
+
+ /**
+ * Function signature corresponding to this function prototype instance
+ *
+ * Used by ast_function_definition::hir to process the parameters, etc.
+ * of the function.
+ *
+ * \sa ::hir
+ */
+ class ir_function_signature *signature;
+
+ friend class ast_function_definition;
+};
+
+
+class ast_expression_statement : public ast_node {
+public:
+ ast_expression_statement(ast_expression *);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_expression *expression;
+};
+
+
+class ast_case_label : public ast_node {
+public:
+
+ /**
+ * An expression of NULL means 'default'.
+ */
+ ast_expression *expression;
+};
+
+class ast_selection_statement : public ast_node {
+public:
+ ast_selection_statement(ast_expression *condition,
+ ast_node *then_statement,
+ ast_node *else_statement);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_expression *condition;
+ ast_node *then_statement;
+ ast_node *else_statement;
+};
+
+
+class ast_switch_statement : public ast_node {
+public:
+ ast_expression *expression;
+ exec_list statements;
+};
+
+class ast_iteration_statement : public ast_node {
+public:
+ ast_iteration_statement(int mode, ast_node *init, ast_node *condition,
+ ast_expression *rest_expression, ast_node *body);
+
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+ enum ast_iteration_modes {
+ ast_for,
+ ast_while,
+ ast_do_while
+ } mode;
+
+
+ ast_node *init_statement;
+ ast_node *condition;
+ ast_expression *rest_expression;
+
+ ast_node *body;
+
+private:
+ /**
+ * Generate IR from the condition of a loop
+ *
+ * This is factored out of ::hir because some loops have the condition
+ * test at the top (for and while), and others have it at the end (do-while).
+ */
+ void condition_to_hir(class ir_loop *, struct _mesa_glsl_parse_state *);
+};
+
+
+class ast_jump_statement : public ast_node {
+public:
+ ast_jump_statement(int mode, ast_expression *return_value);
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ enum ast_jump_modes {
+ ast_continue,
+ ast_break,
+ ast_return,
+ ast_discard
+ } mode;
+
+ ast_expression *opt_return_value;
+};
+
+
+class ast_function_definition : public ast_node {
+public:
+ virtual void print(void) const;
+
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+ ast_function *prototype;
+ ast_compound_statement *body;
+};
+/*@}*/
+
+extern void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state);
+
+extern ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+ exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+void
+emit_function(_mesa_glsl_parse_state *state, exec_list *instructions,
+ ir_function *f);
+
+#endif /* AST_H */
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index d2a499868..df11a30c1 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -1,3392 +1,3456 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 ast_to_hir.c
- * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
- *
- * During the conversion to HIR, the majority of the symantic checking is
- * preformed on the program. This includes:
- *
- * * Symbol table management
- * * Type checking
- * * Function binding
- *
- * The majority of this work could be done during parsing, and the parser could
- * probably generate HIR directly. However, this results in frequent changes
- * to the parser code. Since we do not assume that every system this complier
- * is built on will have Flex and Bison installed, we have to store the code
- * generated by these tools in our version control system. In other parts of
- * the system we've seen problems where a parser was changed but the generated
- * code was not committed, merge conflicts where created because two developers
- * had slightly different versions of Bison installed, etc.
- *
- * I have also noticed that running Bison generated parsers in GDB is very
- * irritating. When you get a segfault on '$$ = $1->foo', you can't very
- * well 'print $1' in GDB.
- *
- * As a result, my preference is to put as little C code as possible in the
- * parser (and lexer) sources.
- */
-
-#include "main/core.h" /* for struct gl_extensions */
-#include "glsl_symbol_table.h"
-#include "glsl_parser_extras.h"
-#include "ast.h"
-#include "glsl_types.h"
-#include "ir.h"
-
-void
-_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
-{
- _mesa_glsl_initialize_variables(instructions, state);
- _mesa_glsl_initialize_functions(state);
-
- state->symbols->language_version = state->language_version;
-
- state->current_function = NULL;
-
- /* Section 4.2 of the GLSL 1.20 specification states:
- * "The built-in functions are scoped in a scope outside the global scope
- * users declare global variables in. That is, a shader's global scope,
- * available for user-defined functions and global variables, is nested
- * inside the scope containing the built-in functions."
- *
- * Since built-in functions like ftransform() access built-in variables,
- * it follows that those must be in the outer scope as well.
- *
- * We push scope here to create this nesting effect...but don't pop.
- * This way, a shader's globals are still in the symbol table for use
- * by the linker.
- */
- state->symbols->push_scope();
-
- foreach_list_typed (ast_node, ast, link, & state->translation_unit)
- ast->hir(instructions, state);
-}
-
-
-/**
- * If a conversion is available, convert one operand to a different type
- *
- * The \c from \c ir_rvalue is converted "in place".
- *
- * \param to Type that the operand it to be converted to
- * \param from Operand that is being converted
- * \param state GLSL compiler state
- *
- * \return
- * If a conversion is possible (or unnecessary), \c true is returned.
- * Otherwise \c false is returned.
- */
-bool
-apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- if (to->base_type == from->type->base_type)
- return true;
-
- /* This conversion was added in GLSL 1.20. If the compilation mode is
- * GLSL 1.10, the conversion is skipped.
- */
- if (state->language_version < 120)
- return false;
-
- /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec:
- *
- * "There are no implicit array or structure conversions. For
- * example, an array of int cannot be implicitly converted to an
- * array of float. There are no implicit conversions between
- * signed and unsigned integers."
- */
- /* FINISHME: The above comment is partially a lie. There is int/uint
- * FINISHME: conversion for immediate constants.
- */
- if (!to->is_float() || !from->type->is_numeric())
- return false;
-
- /* Convert to a floating point type with the same number of components
- * as the original type - i.e. int to float, not int to vec4.
- */
- to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements,
- from->type->matrix_columns);
-
- switch (from->type->base_type) {
- case GLSL_TYPE_INT:
- from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL);
- break;
- case GLSL_TYPE_UINT:
- from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL);
- break;
- case GLSL_TYPE_BOOL:
- from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL);
- break;
- default:
- assert(0);
- }
-
- return true;
-}
-
-
-static const struct glsl_type *
-arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
- bool multiply,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- const glsl_type *type_a = value_a->type;
- const glsl_type *type_b = value_b->type;
-
- /* From GLSL 1.50 spec, page 56:
- *
- * "The arithmetic binary operators add (+), subtract (-),
- * multiply (*), and divide (/) operate on integer and
- * floating-point scalars, vectors, and matrices."
- */
- if (!type_a->is_numeric() || !type_b->is_numeric()) {
- _mesa_glsl_error(loc, state,
- "Operands to arithmetic operators must be numeric");
- return glsl_type::error_type;
- }
-
-
- /* "If one operand is floating-point based and the other is
- * not, then the conversions from Section 4.1.10 "Implicit
- * Conversions" are applied to the non-floating-point-based operand."
- */
- if (!apply_implicit_conversion(type_a, value_b, state)
- && !apply_implicit_conversion(type_b, value_a, state)) {
- _mesa_glsl_error(loc, state,
- "Could not implicitly convert operands to "
- "arithmetic operator");
- return glsl_type::error_type;
- }
- type_a = value_a->type;
- type_b = value_b->type;
-
- /* "If the operands are integer types, they must both be signed or
- * both be unsigned."
- *
- * From this rule and the preceeding conversion it can be inferred that
- * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
- * The is_numeric check above already filtered out the case where either
- * type is not one of these, so now the base types need only be tested for
- * equality.
- */
- if (type_a->base_type != type_b->base_type) {
- _mesa_glsl_error(loc, state,
- "base type mismatch for arithmetic operator");
- return glsl_type::error_type;
- }
-
- /* "All arithmetic binary operators result in the same fundamental type
- * (signed integer, unsigned integer, or floating-point) as the
- * operands they operate on, after operand type conversion. After
- * conversion, the following cases are valid
- *
- * * The two operands are scalars. In this case the operation is
- * applied, resulting in a scalar."
- */
- if (type_a->is_scalar() && type_b->is_scalar())
- return type_a;
-
- /* "* One operand is a scalar, and the other is a vector or matrix.
- * In this case, the scalar operation is applied independently to each
- * component of the vector or matrix, resulting in the same size
- * vector or matrix."
- */
- if (type_a->is_scalar()) {
- if (!type_b->is_scalar())
- return type_b;
- } else if (type_b->is_scalar()) {
- return type_a;
- }
-
- /* All of the combinations of <scalar, scalar>, <vector, scalar>,
- * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
- * handled.
- */
- assert(!type_a->is_scalar());
- assert(!type_b->is_scalar());
-
- /* "* The two operands are vectors of the same size. In this case, the
- * operation is done component-wise resulting in the same size
- * vector."
- */
- if (type_a->is_vector() && type_b->is_vector()) {
- if (type_a == type_b) {
- return type_a;
- } else {
- _mesa_glsl_error(loc, state,
- "vector size mismatch for arithmetic operator");
- return glsl_type::error_type;
- }
- }
-
- /* All of the combinations of <scalar, scalar>, <vector, scalar>,
- * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
- * <vector, vector> have been handled. At least one of the operands must
- * be matrix. Further, since there are no integer matrix types, the base
- * type of both operands must be float.
- */
- assert(type_a->is_matrix() || type_b->is_matrix());
- assert(type_a->base_type == GLSL_TYPE_FLOAT);
- assert(type_b->base_type == GLSL_TYPE_FLOAT);
-
- /* "* The operator is add (+), subtract (-), or divide (/), and the
- * operands are matrices with the same number of rows and the same
- * number of columns. In this case, the operation is done component-
- * wise resulting in the same size matrix."
- * * The operator is multiply (*), where both operands are matrices or
- * one operand is a vector and the other a matrix. A right vector
- * operand is treated as a column vector and a left vector operand as a
- * row vector. In all these cases, it is required that the number of
- * columns of the left operand is equal to the number of rows of the
- * right operand. Then, the multiply (*) operation does a linear
- * algebraic multiply, yielding an object that has the same number of
- * rows as the left operand and the same number of columns as the right
- * operand. Section 5.10 "Vector and Matrix Operations" explains in
- * more detail how vectors and matrices are operated on."
- */
- if (! multiply) {
- if (type_a == type_b)
- return type_a;
- } else {
- if (type_a->is_matrix() && type_b->is_matrix()) {
- /* Matrix multiply. The columns of A must match the rows of B. Given
- * the other previously tested constraints, this means the vector type
- * of a row from A must be the same as the vector type of a column from
- * B.
- */
- if (type_a->row_type() == type_b->column_type()) {
- /* The resulting matrix has the number of columns of matrix B and
- * the number of rows of matrix A. We get the row count of A by
- * looking at the size of a vector that makes up a column. The
- * transpose (size of a row) is done for B.
- */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- type_b->row_type()->vector_elements);
- assert(type != glsl_type::error_type);
-
- return type;
- }
- } else if (type_a->is_matrix()) {
- /* A is a matrix and B is a column vector. Columns of A must match
- * rows of B. Given the other previously tested constraints, this
- * means the vector type of a row from A must be the same as the
- * vector the type of B.
- */
- if (type_a->row_type() == type_b) {
- /* The resulting vector has a number of elements equal to
- * the number of rows of matrix A. */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- 1);
- assert(type != glsl_type::error_type);
-
- return type;
- }
- } else {
- assert(type_b->is_matrix());
-
- /* A is a row vector and B is a matrix. Columns of A must match rows
- * of B. Given the other previously tested constraints, this means
- * the type of A must be the same as the vector type of a column from
- * B.
- */
- if (type_a == type_b->column_type()) {
- /* The resulting vector has a number of elements equal to
- * the number of columns of matrix B. */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_b->row_type()->vector_elements,
- 1);
- assert(type != glsl_type::error_type);
-
- return type;
- }
- }
-
- _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
- return glsl_type::error_type;
- }
-
-
- /* "All other cases are illegal."
- */
- _mesa_glsl_error(loc, state, "type mismatch");
- return glsl_type::error_type;
-}
-
-
-static const struct glsl_type *
-unary_arithmetic_result_type(const struct glsl_type *type,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- /* From GLSL 1.50 spec, page 57:
- *
- * "The arithmetic unary operators negate (-), post- and pre-increment
- * and decrement (-- and ++) operate on integer or floating-point
- * values (including vectors and matrices). All unary operators work
- * component-wise on their operands. These result with the same type
- * they operated on."
- */
- if (!type->is_numeric()) {
- _mesa_glsl_error(loc, state,
- "Operands to arithmetic operators must be numeric");
- return glsl_type::error_type;
- }
-
- return type;
-}
-
-/**
- * \brief Return the result type of a bit-logic operation.
- *
- * If the given types to the bit-logic operator are invalid, return
- * glsl_type::error_type.
- *
- * \param type_a Type of LHS of bit-logic op
- * \param type_b Type of RHS of bit-logic op
- */
-static const struct glsl_type *
-bit_logic_result_type(const struct glsl_type *type_a,
- const struct glsl_type *type_b,
- ast_operators op,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- if (state->language_version < 130) {
- _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
- return glsl_type::error_type;
- }
-
- /* From page 50 (page 56 of PDF) of GLSL 1.30 spec:
- *
- * "The bitwise operators and (&), exclusive-or (^), and inclusive-or
- * (|). The operands must be of type signed or unsigned integers or
- * integer vectors."
- */
- if (!type_a->is_integer()) {
- _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer",
- ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
- if (!type_b->is_integer()) {
- _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer",
- ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "The fundamental types of the operands (signed or unsigned) must
- * match,"
- */
- if (type_a->base_type != type_b->base_type) {
- _mesa_glsl_error(loc, state, "operands of `%s' must have the same "
- "base type", ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "The operands cannot be vectors of differing size." */
- if (type_a->is_vector() &&
- type_b->is_vector() &&
- type_a->vector_elements != type_b->vector_elements) {
- _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of "
- "different sizes", ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "If one operand is a scalar and the other a vector, the scalar is
- * applied component-wise to the vector, resulting in the same type as
- * the vector. The fundamental types of the operands [...] will be the
- * resulting fundamental type."
- */
- if (type_a->is_scalar())
- return type_b;
- else
- return type_a;
-}
-
-static const struct glsl_type *
-modulus_result_type(const struct glsl_type *type_a,
- const struct glsl_type *type_b,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- /* From GLSL 1.50 spec, page 56:
- * "The operator modulus (%) operates on signed or unsigned integers or
- * integer vectors. The operand types must both be signed or both be
- * unsigned."
- */
- if (!type_a->is_integer() || !type_b->is_integer()
- || (type_a->base_type != type_b->base_type)) {
- _mesa_glsl_error(loc, state, "type mismatch");
- return glsl_type::error_type;
- }
-
- /* "The operands cannot be vectors of differing size. If one operand is
- * a scalar and the other vector, then the scalar is applied component-
- * wise to the vector, resulting in the same type as the vector. If both
- * are vectors of the same size, the result is computed component-wise."
- */
- if (type_a->is_vector()) {
- if (!type_b->is_vector()
- || (type_a->vector_elements == type_b->vector_elements))
- return type_a;
- } else
- return type_b;
-
- /* "The operator modulus (%) is not defined for any other data types
- * (non-integer types)."
- */
- _mesa_glsl_error(loc, state, "type mismatch");
- return glsl_type::error_type;
-}
-
-
-static const struct glsl_type *
-relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- const glsl_type *type_a = value_a->type;
- const glsl_type *type_b = value_b->type;
-
- /* From GLSL 1.50 spec, page 56:
- * "The relational operators greater than (>), less than (<), greater
- * than or equal (>=), and less than or equal (<=) operate only on
- * scalar integer and scalar floating-point expressions."
- */
- if (!type_a->is_numeric()
- || !type_b->is_numeric()
- || !type_a->is_scalar()
- || !type_b->is_scalar()) {
- _mesa_glsl_error(loc, state,
- "Operands to relational operators must be scalar and "
- "numeric");
- return glsl_type::error_type;
- }
-
- /* "Either the operands' types must match, or the conversions from
- * Section 4.1.10 "Implicit Conversions" will be applied to the integer
- * operand, after which the types must match."
- */
- if (!apply_implicit_conversion(type_a, value_b, state)
- && !apply_implicit_conversion(type_b, value_a, state)) {
- _mesa_glsl_error(loc, state,
- "Could not implicitly convert operands to "
- "relational operator");
- return glsl_type::error_type;
- }
- type_a = value_a->type;
- type_b = value_b->type;
-
- if (type_a->base_type != type_b->base_type) {
- _mesa_glsl_error(loc, state, "base type mismatch");
- return glsl_type::error_type;
- }
-
- /* "The result is scalar Boolean."
- */
- return glsl_type::bool_type;
-}
-
-/**
- * \brief Return the result type of a bit-shift operation.
- *
- * If the given types to the bit-shift operator are invalid, return
- * glsl_type::error_type.
- *
- * \param type_a Type of LHS of bit-shift op
- * \param type_b Type of RHS of bit-shift op
- */
-static const struct glsl_type *
-shift_result_type(const struct glsl_type *type_a,
- const struct glsl_type *type_b,
- ast_operators op,
- struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
-{
- if (state->language_version < 130) {
- _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
- return glsl_type::error_type;
- }
-
- /* From page 50 (page 56 of the PDF) of the GLSL 1.30 spec:
- *
- * "The shift operators (<<) and (>>). For both operators, the operands
- * must be signed or unsigned integers or integer vectors. One operand
- * can be signed while the other is unsigned."
- */
- if (!type_a->is_integer()) {
- _mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or "
- "integer vector", ast_expression::operator_string(op));
- return glsl_type::error_type;
-
- }
- if (!type_b->is_integer()) {
- _mesa_glsl_error(loc, state, "RHS of operator %s must be an integer or "
- "integer vector", ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "If the first operand is a scalar, the second operand has to be
- * a scalar as well."
- */
- if (type_a->is_scalar() && !type_b->is_scalar()) {
- _mesa_glsl_error(loc, state, "If the first operand of %s is scalar, the "
- "second must be scalar as well",
- ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* If both operands are vectors, check that they have same number of
- * elements.
- */
- if (type_a->is_vector() &&
- type_b->is_vector() &&
- type_a->vector_elements != type_b->vector_elements) {
- _mesa_glsl_error(loc, state, "Vector operands to operator %s must "
- "have same number of elements",
- ast_expression::operator_string(op));
- return glsl_type::error_type;
- }
-
- /* "In all cases, the resulting type will be the same type as the left
- * operand."
- */
- return type_a;
-}
-
-/**
- * Validates that a value can be assigned to a location with a specified type
- *
- * Validates that \c rhs can be assigned to some location. If the types are
- * not an exact match but an automatic conversion is possible, \c rhs will be
- * converted.
- *
- * \return
- * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type.
- * Otherwise the actual RHS to be assigned will be returned. This may be
- * \c rhs, or it may be \c rhs after some type conversion.
- *
- * \note
- * In addition to being used for assignments, this function is used to
- * type-check return values.
- */
-ir_rvalue *
-validate_assignment(struct _mesa_glsl_parse_state *state,
- const glsl_type *lhs_type, ir_rvalue *rhs)
-{
- /* If there is already some error in the RHS, just return it. Anything
- * else will lead to an avalanche of error message back to the user.
- */
- if (rhs->type->is_error())
- return rhs;
-
- /* If the types are identical, the assignment can trivially proceed.
- */
- if (rhs->type == lhs_type)
- return rhs;
-
- /* If the array element types are the same and the size of the LHS is zero,
- * the assignment is okay.
- *
- * Note: Whole-array assignments are not permitted in GLSL 1.10, but this
- * is handled by ir_dereference::is_lvalue.
- */
- if (lhs_type->is_array() && rhs->type->is_array()
- && (lhs_type->element_type() == rhs->type->element_type())
- && (lhs_type->array_size() == 0)) {
- return rhs;
- }
-
- /* Check for implicit conversion in GLSL 1.20 */
- if (apply_implicit_conversion(lhs_type, rhs, state)) {
- if (rhs->type == lhs_type)
- return rhs;
- }
-
- return NULL;
-}
-
-ir_rvalue *
-do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
- ir_rvalue *lhs, ir_rvalue *rhs,
- YYLTYPE lhs_loc)
-{
- void *ctx = state;
- bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
-
- if (!error_emitted) {
- if (lhs->variable_referenced() != NULL
- && lhs->variable_referenced()->read_only) {
- _mesa_glsl_error(&lhs_loc, state,
- "assignment to read-only variable '%s'",
- lhs->variable_referenced()->name);
- error_emitted = true;
-
- } else if (!lhs->is_lvalue()) {
- _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
- error_emitted = true;
- }
-
- if (state->es_shader && lhs->type->is_array()) {
- _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not "
- "allowed in GLSL ES 1.00.");
- error_emitted = true;
- }
- }
-
- ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs);
- if (new_rhs == NULL) {
- _mesa_glsl_error(& lhs_loc, state, "type mismatch");
- } else {
- rhs = new_rhs;
-
- /* If the LHS array was not declared with a size, it takes it size from
- * the RHS. If the LHS is an l-value and a whole array, it must be a
- * dereference of a variable. Any other case would require that the LHS
- * is either not an l-value or not a whole array.
- */
- if (lhs->type->array_size() == 0) {
- ir_dereference *const d = lhs->as_dereference();
-
- assert(d != NULL);
-
- ir_variable *const var = d->variable_referenced();
-
- assert(var != NULL);
-
- if (var->max_array_access >= unsigned(rhs->type->array_size())) {
- /* FINISHME: This should actually log the location of the RHS. */
- _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
- "previous access",
- var->max_array_access);
- }
-
- var->type = glsl_type::get_array_instance(lhs->type->element_type(),
- rhs->type->array_size());
- d->type = var->type;
- }
- }
-
- /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
- * but not post_inc) need the converted assigned value as an rvalue
- * to handle things like:
- *
- * i = j += 1;
- *
- * So we always just store the computed value being assigned to a
- * temporary and return a deref of that temporary. If the rvalue
- * ends up not being used, the temp will get copy-propagated out.
- */
- ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
- ir_var_temporary);
- ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
- instructions->push_tail(var);
- instructions->push_tail(new(ctx) ir_assignment(deref_var,
- rhs,
- NULL));
- deref_var = new(ctx) ir_dereference_variable(var);
-
- if (!error_emitted)
- instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
-
- return new(ctx) ir_dereference_variable(var);
-}
-
-static ir_rvalue *
-get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
-{
- void *ctx = talloc_parent(lvalue);
- ir_variable *var;
-
- var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
- ir_var_temporary);
- instructions->push_tail(var);
- var->mode = ir_var_auto;
-
- instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
- lvalue, NULL));
-
- /* Once we've created this temporary, mark it read only so it's no
- * longer considered an lvalue.
- */
- var->read_only = true;
-
- return new(ctx) ir_dereference_variable(var);
-}
-
-
-ir_rvalue *
-ast_node::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- (void) instructions;
- (void) state;
-
- return NULL;
-}
-
-static void
-mark_whole_array_access(ir_rvalue *access)
-{
- ir_dereference_variable *deref = access->as_dereference_variable();
-
- if (deref) {
- deref->var->max_array_access = deref->type->length - 1;
- }
-}
-
-static ir_rvalue *
-do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
-{
- int join_op;
- ir_rvalue *cmp = NULL;
-
- if (operation == ir_binop_all_equal)
- join_op = ir_binop_logic_and;
- else
- join_op = ir_binop_logic_or;
-
- switch (op0->type->base_type) {
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_BOOL:
- return new(mem_ctx) ir_expression(operation, op0, op1);
-
- case GLSL_TYPE_ARRAY: {
- for (unsigned int i = 0; i < op0->type->length; i++) {
- ir_rvalue *e0, *e1, *result;
-
- e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL),
- new(mem_ctx) ir_constant(i));
- e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL),
- new(mem_ctx) ir_constant(i));
- result = do_comparison(mem_ctx, operation, e0, e1);
-
- if (cmp) {
- cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
- } else {
- cmp = result;
- }
- }
-
- mark_whole_array_access(op0);
- mark_whole_array_access(op1);
- break;
- }
-
- case GLSL_TYPE_STRUCT: {
- for (unsigned int i = 0; i < op0->type->length; i++) {
- ir_rvalue *e0, *e1, *result;
- const char *field_name = op0->type->fields.structure[i].name;
-
- e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL),
- field_name);
- e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL),
- field_name);
- result = do_comparison(mem_ctx, operation, e0, e1);
-
- if (cmp) {
- cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
- } else {
- cmp = result;
- }
- }
- break;
- }
-
- case GLSL_TYPE_ERROR:
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_SAMPLER:
- /* I assume a comparison of a struct containing a sampler just
- * ignores the sampler present in the type.
- */
- break;
-
- default:
- assert(!"Should not get here.");
- break;
- }
-
- if (cmp == NULL)
- cmp = new(mem_ctx) ir_constant(true);
-
- return cmp;
-}
-
-ir_rvalue *
-ast_expression::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- static const int operations[AST_NUM_OPERATORS] = {
- -1, /* ast_assign doesn't convert to ir_expression. */
- -1, /* ast_plus doesn't convert to ir_expression. */
- ir_unop_neg,
- ir_binop_add,
- ir_binop_sub,
- ir_binop_mul,
- ir_binop_div,
- ir_binop_mod,
- ir_binop_lshift,
- ir_binop_rshift,
- ir_binop_less,
- ir_binop_greater,
- ir_binop_lequal,
- ir_binop_gequal,
- ir_binop_all_equal,
- ir_binop_any_nequal,
- ir_binop_bit_and,
- ir_binop_bit_xor,
- ir_binop_bit_or,
- ir_unop_bit_not,
- ir_binop_logic_and,
- ir_binop_logic_xor,
- ir_binop_logic_or,
- ir_unop_logic_not,
-
- /* Note: The following block of expression types actually convert
- * to multiple IR instructions.
- */
- ir_binop_mul, /* ast_mul_assign */
- ir_binop_div, /* ast_div_assign */
- ir_binop_mod, /* ast_mod_assign */
- ir_binop_add, /* ast_add_assign */
- ir_binop_sub, /* ast_sub_assign */
- ir_binop_lshift, /* ast_ls_assign */
- ir_binop_rshift, /* ast_rs_assign */
- ir_binop_bit_and, /* ast_and_assign */
- ir_binop_bit_xor, /* ast_xor_assign */
- ir_binop_bit_or, /* ast_or_assign */
-
- -1, /* ast_conditional doesn't convert to ir_expression. */
- ir_binop_add, /* ast_pre_inc. */
- ir_binop_sub, /* ast_pre_dec. */
- ir_binop_add, /* ast_post_inc. */
- ir_binop_sub, /* ast_post_dec. */
- -1, /* ast_field_selection doesn't conv to ir_expression. */
- -1, /* ast_array_index doesn't convert to ir_expression. */
- -1, /* ast_function_call doesn't conv to ir_expression. */
- -1, /* ast_identifier doesn't convert to ir_expression. */
- -1, /* ast_int_constant doesn't convert to ir_expression. */
- -1, /* ast_uint_constant doesn't conv to ir_expression. */
- -1, /* ast_float_constant doesn't conv to ir_expression. */
- -1, /* ast_bool_constant doesn't conv to ir_expression. */
- -1, /* ast_sequence doesn't convert to ir_expression. */
- };
- ir_rvalue *result = NULL;
- ir_rvalue *op[3];
- const struct glsl_type *type = glsl_type::error_type;
- bool error_emitted = false;
- YYLTYPE loc;
-
- loc = this->get_location();
-
- switch (this->oper) {
- case ast_assign: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- result = do_assignment(instructions, state, op[0], op[1],
- this->subexpressions[0]->get_location());
- error_emitted = result->type->is_error();
- type = result->type;
- break;
- }
-
- case ast_plus:
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- type = unary_arithmetic_result_type(op[0]->type, state, & loc);
-
- error_emitted = type->is_error();
-
- result = op[0];
- break;
-
- case ast_neg:
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- type = unary_arithmetic_result_type(op[0]->type, state, & loc);
-
- error_emitted = type->is_error();
-
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], NULL);
- break;
-
- case ast_add:
- case ast_sub:
- case ast_mul:
- case ast_div:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- type = arithmetic_result_type(op[0], op[1],
- (this->oper == ast_mul),
- state, & loc);
- error_emitted = type->is_error();
-
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
- break;
-
- case ast_mod:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
-
- assert(operations[this->oper] == ir_binop_mod);
-
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
- error_emitted = type->is_error();
- break;
-
- case ast_lshift:
- case ast_rshift:
- if (state->language_version < 130) {
- _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30",
- operator_string(this->oper));
- error_emitted = true;
- }
-
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
- type = shift_result_type(op[0]->type, op[1]->type, this->oper, state,
- &loc);
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
- break;
-
- case ast_less:
- case ast_greater:
- case ast_lequal:
- case ast_gequal:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- type = relational_result_type(op[0], op[1], state, & loc);
-
- /* The relational operators must either generate an error or result
- * in a scalar boolean. See page 57 of the GLSL 1.50 spec.
- */
- assert(type->is_error()
- || ((type->base_type == GLSL_TYPE_BOOL)
- && type->is_scalar()));
-
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
- error_emitted = type->is_error();
- break;
-
- case ast_nequal:
- case ast_equal:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec:
- *
- * "The equality operators equal (==), and not equal (!=)
- * operate on all types. They result in a scalar Boolean. If
- * the operand types do not match, then there must be a
- * conversion from Section 4.1.10 "Implicit Conversions"
- * applied to one operand that can make them match, in which
- * case this conversion is done."
- */
- if ((!apply_implicit_conversion(op[0]->type, op[1], state)
- && !apply_implicit_conversion(op[1]->type, op[0], state))
- || (op[0]->type != op[1]->type)) {
- _mesa_glsl_error(& loc, state, "operands of `%s' must have the same "
- "type", (this->oper == ast_equal) ? "==" : "!=");
- error_emitted = true;
- } else if ((state->language_version <= 110)
- && (op[0]->type->is_array() || op[1]->type->is_array())) {
- _mesa_glsl_error(& loc, state, "array comparisons forbidden in "
- "GLSL 1.10");
- error_emitted = true;
- }
-
- result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
- type = glsl_type::bool_type;
-
- assert(error_emitted || (result->type == glsl_type::bool_type));
- break;
-
- case ast_bit_and:
- case ast_bit_xor:
- case ast_bit_or:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
- type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper,
- state, &loc);
- result = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
- break;
-
- case ast_bit_not:
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (state->language_version < 130) {
- _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
- error_emitted = true;
- }
-
- if (!op[0]->type->is_integer()) {
- _mesa_glsl_error(&loc, state, "operand of `~' must be an integer");
- error_emitted = true;
- }
-
- type = op[0]->type;
- result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL);
- break;
-
- case ast_logic_and: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
- ir_constant *op0_const = op[0]->constant_expression_value();
- if (op0_const) {
- if (op0_const->value.b[0]) {
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
- result = op[1];
- } else {
- result = op0_const;
- }
- type = glsl_type::bool_type;
- } else {
- ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
- "and_tmp",
- ir_var_temporary);
- instructions->push_tail(tmp);
-
- ir_if *const stmt = new(ctx) ir_if(op[0]);
- instructions->push_tail(stmt);
-
- op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
- ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const then_assign =
- new(ctx) ir_assignment(then_deref, op[1], NULL);
- stmt->then_instructions.push_tail(then_assign);
-
- ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const else_assign =
- new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL);
- stmt->else_instructions.push_tail(else_assign);
-
- result = new(ctx) ir_dereference_variable(tmp);
- type = tmp->type;
- }
- break;
- }
-
- case ast_logic_or: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
- ir_constant *op0_const = op[0]->constant_expression_value();
- if (op0_const) {
- if (op0_const->value.b[0]) {
- result = op0_const;
- } else {
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
- result = op[1];
- }
- type = glsl_type::bool_type;
- } else {
- ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
- "or_tmp",
- ir_var_temporary);
- instructions->push_tail(tmp);
-
- ir_if *const stmt = new(ctx) ir_if(op[0]);
- instructions->push_tail(stmt);
-
- op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
- ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const then_assign =
- new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL);
- stmt->then_instructions.push_tail(then_assign);
-
- ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const else_assign =
- new(ctx) ir_assignment(else_deref, op[1], NULL);
- stmt->else_instructions.push_tail(else_assign);
-
- result = new(ctx) ir_dereference_variable(tmp);
- type = tmp->type;
- }
- break;
- }
-
- case ast_logic_xor:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
-
- result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
- op[0], op[1]);
- type = glsl_type::bool_type;
- break;
-
- case ast_logic_not:
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "operand of `!' must be scalar boolean");
- error_emitted = true;
- }
-
- result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
- op[0], NULL);
- type = glsl_type::bool_type;
- break;
-
- case ast_mul_assign:
- case ast_div_assign:
- case ast_add_assign:
- case ast_sub_assign: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- type = arithmetic_result_type(op[0], op[1],
- (this->oper == ast_mul_assign),
- state, & loc);
-
- ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
-
- result = do_assignment(instructions, state,
- op[0]->clone(ctx, NULL), temp_rhs,
- this->subexpressions[0]->get_location());
- type = result->type;
- error_emitted = (op[0]->type->is_error());
-
- /* GLSL 1.10 does not allow array assignment. However, we don't have to
- * explicitly test for this because none of the binary expression
- * operators allow array operands either.
- */
-
- break;
- }
-
- case ast_mod_assign: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
-
- assert(operations[this->oper] == ir_binop_mod);
-
- ir_rvalue *temp_rhs;
- temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
-
- result = do_assignment(instructions, state,
- op[0]->clone(ctx, NULL), temp_rhs,
- this->subexpressions[0]->get_location());
- type = result->type;
- error_emitted = type->is_error();
- break;
- }
-
- case ast_ls_assign:
- case ast_rs_assign: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
- type = shift_result_type(op[0]->type, op[1]->type, this->oper, state,
- &loc);
- ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
- type, op[0], op[1]);
- result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
- temp_rhs,
- this->subexpressions[0]->get_location());
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
- break;
- }
-
- case ast_and_assign:
- case ast_xor_assign:
- case ast_or_assign: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
- type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper,
- state, &loc);
- ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
- type, op[0], op[1]);
- result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
- temp_rhs,
- this->subexpressions[0]->get_location());
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
- break;
- }
-
- case ast_conditional: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
- *
- * "The ternary selection operator (?:). It operates on three
- * expressions (exp1 ? exp2 : exp3). This operator evaluates the
- * first expression, which must result in a scalar Boolean."
- */
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean");
- error_emitted = true;
- }
-
- /* The :? operator is implemented by generating an anonymous temporary
- * followed by an if-statement. The last instruction in each branch of
- * the if-statement assigns a value to the anonymous temporary. This
- * temporary is the r-value of the expression.
- */
- exec_list then_instructions;
- exec_list else_instructions;
-
- op[1] = this->subexpressions[1]->hir(&then_instructions, state);
- op[2] = this->subexpressions[2]->hir(&else_instructions, state);
-
- /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
- *
- * "The second and third expressions can be any type, as
- * long their types match, or there is a conversion in
- * Section 4.1.10 "Implicit Conversions" that can be applied
- * to one of the expressions to make their types match. This
- * resulting matching type is the type of the entire
- * expression."
- */
- if ((!apply_implicit_conversion(op[1]->type, op[2], state)
- && !apply_implicit_conversion(op[2]->type, op[1], state))
- || (op[1]->type != op[2]->type)) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
- "operator must have matching types.");
- error_emitted = true;
- type = glsl_type::error_type;
- } else {
- type = op[1]->type;
- }
-
- /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec:
- *
- * "The second and third expressions must be the same type, but can
- * be of any type other than an array."
- */
- if ((state->language_version <= 110) && type->is_array()) {
- _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
- "operator must not be arrays.");
- error_emitted = true;
- }
-
- ir_constant *cond_val = op[0]->constant_expression_value();
- ir_constant *then_val = op[1]->constant_expression_value();
- ir_constant *else_val = op[2]->constant_expression_value();
-
- if (then_instructions.is_empty()
- && else_instructions.is_empty()
- && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
- result = (cond_val->value.b[0]) ? then_val : else_val;
- } else {
- ir_variable *const tmp =
- new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
- instructions->push_tail(tmp);
-
- ir_if *const stmt = new(ctx) ir_if(op[0]);
- instructions->push_tail(stmt);
-
- then_instructions.move_nodes_to(& stmt->then_instructions);
- ir_dereference *const then_deref =
- new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const then_assign =
- new(ctx) ir_assignment(then_deref, op[1], NULL);
- stmt->then_instructions.push_tail(then_assign);
-
- else_instructions.move_nodes_to(& stmt->else_instructions);
- ir_dereference *const else_deref =
- new(ctx) ir_dereference_variable(tmp);
- ir_assignment *const else_assign =
- new(ctx) ir_assignment(else_deref, op[2], NULL);
- stmt->else_instructions.push_tail(else_assign);
-
- result = new(ctx) ir_dereference_variable(tmp);
- }
- break;
- }
-
- case ast_pre_inc:
- case ast_pre_dec: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
- op[1] = new(ctx) ir_constant(1.0f);
- else
- op[1] = new(ctx) ir_constant(1);
-
- type = arithmetic_result_type(op[0], op[1], false, state, & loc);
-
- ir_rvalue *temp_rhs;
- temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
-
- result = do_assignment(instructions, state,
- op[0]->clone(ctx, NULL), temp_rhs,
- this->subexpressions[0]->get_location());
- type = result->type;
- error_emitted = op[0]->type->is_error();
- break;
- }
-
- case ast_post_inc:
- case ast_post_dec: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
- if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
- op[1] = new(ctx) ir_constant(1.0f);
- else
- op[1] = new(ctx) ir_constant(1);
-
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
-
- type = arithmetic_result_type(op[0], op[1], false, state, & loc);
-
- ir_rvalue *temp_rhs;
- temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
- op[0], op[1]);
-
- /* Get a temporary of a copy of the lvalue before it's modified.
- * This may get thrown away later.
- */
- result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
-
- (void)do_assignment(instructions, state,
- op[0]->clone(ctx, NULL), temp_rhs,
- this->subexpressions[0]->get_location());
-
- type = result->type;
- error_emitted = op[0]->type->is_error();
- break;
- }
-
- case ast_field_selection:
- result = _mesa_ast_field_selection_to_hir(this, instructions, state);
- type = result->type;
- break;
-
- case ast_array_index: {
- YYLTYPE index_loc = subexpressions[1]->get_location();
-
- op[0] = subexpressions[0]->hir(instructions, state);
- op[1] = subexpressions[1]->hir(instructions, state);
-
- error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
-
- ir_rvalue *const array = op[0];
-
- result = new(ctx) ir_dereference_array(op[0], op[1]);
-
- /* Do not use op[0] after this point. Use array.
- */
- op[0] = NULL;
-
-
- if (error_emitted)
- break;
-
- if (!array->type->is_array()
- && !array->type->is_matrix()
- && !array->type->is_vector()) {
- _mesa_glsl_error(& index_loc, state,
- "cannot dereference non-array / non-matrix / "
- "non-vector");
- error_emitted = true;
- }
-
- if (!op[1]->type->is_integer()) {
- _mesa_glsl_error(& index_loc, state,
- "array index must be integer type");
- error_emitted = true;
- } else if (!op[1]->type->is_scalar()) {
- _mesa_glsl_error(& index_loc, state,
- "array index must be scalar");
- error_emitted = true;
- }
-
- /* If the array index is a constant expression and the array has a
- * declared size, ensure that the access is in-bounds. If the array
- * index is not a constant expression, ensure that the array has a
- * declared size.
- */
- ir_constant *const const_index = op[1]->constant_expression_value();
- if (const_index != NULL) {
- const int idx = const_index->value.i[0];
- const char *type_name;
- unsigned bound = 0;
-
- if (array->type->is_matrix()) {
- type_name = "matrix";
- } else if (array->type->is_vector()) {
- type_name = "vector";
- } else {
- type_name = "array";
- }
-
- /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
- *
- * "It is illegal to declare an array with a size, and then
- * later (in the same shader) index the same array with an
- * integral constant expression greater than or equal to the
- * declared size. It is also illegal to index an array with a
- * negative constant expression."
- */
- if (array->type->is_matrix()) {
- if (array->type->row_type()->vector_elements <= idx) {
- bound = array->type->row_type()->vector_elements;
- }
- } else if (array->type->is_vector()) {
- if (array->type->vector_elements <= idx) {
- bound = array->type->vector_elements;
- }
- } else {
- if ((array->type->array_size() > 0)
- && (array->type->array_size() <= idx)) {
- bound = array->type->array_size();
- }
- }
-
- if (bound > 0) {
- _mesa_glsl_error(& loc, state, "%s index must be < %u",
- type_name, bound);
- error_emitted = true;
- } else if (idx < 0) {
- _mesa_glsl_error(& loc, state, "%s index must be >= 0",
- type_name);
- error_emitted = true;
- }
-
- if (array->type->is_array()) {
- /* If the array is a variable dereference, it dereferences the
- * whole array, by definition. Use this to get the variable.
- *
- * FINISHME: Should some methods for getting / setting / testing
- * FINISHME: array access limits be added to ir_dereference?
- */
- ir_variable *const v = array->whole_variable_referenced();
- if ((v != NULL) && (unsigned(idx) > v->max_array_access))
- v->max_array_access = idx;
- }
- } else if (array->type->array_size() == 0) {
- _mesa_glsl_error(&loc, state, "unsized array index must be constant");
- } else {
- if (array->type->is_array()) {
- /* whole_variable_referenced can return NULL if the array is a
- * member of a structure. In this case it is safe to not update
- * the max_array_access field because it is never used for fields
- * of structures.
- */
- ir_variable *v = array->whole_variable_referenced();
- if (v != NULL)
- v->max_array_access = array->type->array_size();
- }
- }
-
- /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
- *
- * "Samplers aggregated into arrays within a shader (using square
- * brackets [ ]) can only be indexed with integral constant
- * expressions [...]."
- *
- * This restriction was added in GLSL 1.30. Shaders using earlier version
- * of the language should not be rejected by the compiler front-end for
- * using this construct. This allows useful things such as using a loop
- * counter as the index to an array of samplers. If the loop in unrolled,
- * the code should compile correctly. Instead, emit a warning.
- */
- if (array->type->is_array() &&
- array->type->element_type()->is_sampler() &&
- const_index == NULL) {
-
- if (state->language_version == 100) {
- _mesa_glsl_warning(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions is optional in GLSL ES 1.00");
- } else if (state->language_version < 130) {
- _mesa_glsl_warning(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions is forbidden in GLSL 1.30 and "
- "later");
- } else {
- _mesa_glsl_error(&loc, state,
- "sampler arrays indexed with non-constant "
- "expressions is forbidden in GLSL 1.30 and "
- "later");
- error_emitted = true;
- }
- }
-
- if (error_emitted)
- result->type = glsl_type::error_type;
-
- type = result->type;
- break;
- }
-
- case ast_function_call:
- /* Should *NEVER* get here. ast_function_call should always be handled
- * by ast_function_expression::hir.
- */
- assert(0);
- break;
-
- case ast_identifier: {
- /* ast_identifier can appear several places in a full abstract syntax
- * tree. This particular use must be at location specified in the grammar
- * as 'variable_identifier'.
- */
- ir_variable *var =
- state->symbols->get_variable(this->primary_expression.identifier);
-
- result = new(ctx) ir_dereference_variable(var);
-
- if (var != NULL) {
- var->used = true;
- type = result->type;
- } else {
- _mesa_glsl_error(& loc, state, "`%s' undeclared",
- this->primary_expression.identifier);
-
- error_emitted = true;
- }
- break;
- }
-
- case ast_int_constant:
- type = glsl_type::int_type;
- result = new(ctx) ir_constant(this->primary_expression.int_constant);
- break;
-
- case ast_uint_constant:
- type = glsl_type::uint_type;
- result = new(ctx) ir_constant(this->primary_expression.uint_constant);
- break;
-
- case ast_float_constant:
- type = glsl_type::float_type;
- result = new(ctx) ir_constant(this->primary_expression.float_constant);
- break;
-
- case ast_bool_constant:
- type = glsl_type::bool_type;
- result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
- break;
-
- case ast_sequence: {
- /* It should not be possible to generate a sequence in the AST without
- * any expressions in it.
- */
- assert(!this->expressions.is_empty());
-
- /* The r-value of a sequence is the last expression in the sequence. If
- * the other expressions in the sequence do not have side-effects (and
- * therefore add instructions to the instruction list), they get dropped
- * on the floor.
- */
- foreach_list_typed (ast_node, ast, link, &this->expressions)
- result = ast->hir(instructions, state);
-
- type = result->type;
-
- /* Any errors should have already been emitted in the loop above.
- */
- error_emitted = true;
- break;
- }
- }
-
- if (type->is_error() && !error_emitted)
- _mesa_glsl_error(& loc, state, "type mismatch");
-
- return result;
-}
-
-
-ir_rvalue *
-ast_expression_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- /* It is possible to have expression statements that don't have an
- * expression. This is the solitary semicolon:
- *
- * for (i = 0; i < 5; i++)
- * ;
- *
- * In this case the expression will be NULL. Test for NULL and don't do
- * anything in that case.
- */
- if (expression != NULL)
- expression->hir(instructions, state);
-
- /* Statements do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_compound_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- if (new_scope)
- state->symbols->push_scope();
-
- foreach_list_typed (ast_node, ast, link, &this->statements)
- ast->hir(instructions, state);
-
- if (new_scope)
- state->symbols->pop_scope();
-
- /* Compound statements do not have r-values.
- */
- return NULL;
-}
-
-
-static const glsl_type *
-process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
- struct _mesa_glsl_parse_state *state)
-{
- unsigned length = 0;
-
- /* FINISHME: Reject delcarations of multidimensional arrays. */
-
- if (array_size != NULL) {
- exec_list dummy_instructions;
- ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
- YYLTYPE loc = array_size->get_location();
-
- /* FINISHME: Verify that the grammar forbids side-effects in array
- * FINISHME: sizes. i.e., 'vec4 [x = 12] data'
- */
- assert(dummy_instructions.is_empty());
-
- if (ir != NULL) {
- if (!ir->type->is_integer()) {
- _mesa_glsl_error(& loc, state, "array size must be integer type");
- } else if (!ir->type->is_scalar()) {
- _mesa_glsl_error(& loc, state, "array size must be scalar type");
- } else {
- ir_constant *const size = ir->constant_expression_value();
-
- if (size == NULL) {
- _mesa_glsl_error(& loc, state, "array size must be a "
- "constant valued expression");
- } else if (size->value.i[0] <= 0) {
- _mesa_glsl_error(& loc, state, "array size must be > 0");
- } else {
- assert(size->type == ir->type);
- length = size->value.u[0];
- }
- }
- }
- } else if (state->es_shader) {
- /* Section 10.17 of the GLSL ES 1.00 specification states that unsized
- * array declarations have been removed from the language.
- */
- _mesa_glsl_error(loc, state, "unsized array declarations are not "
- "allowed in GLSL ES 1.00.");
- }
-
- return glsl_type::get_array_instance(base, length);
-}
-
-
-const glsl_type *
-ast_type_specifier::glsl_type(const char **name,
- struct _mesa_glsl_parse_state *state) const
-{
- const struct glsl_type *type;
-
- type = state->symbols->get_type(this->type_name);
- *name = this->type_name;
-
- if (this->is_array) {
- YYLTYPE loc = this->get_location();
- type = process_array_type(&loc, type, this->array_size, state);
- }
-
- return type;
-}
-
-
-static void
-apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
- ir_variable *var,
- struct _mesa_glsl_parse_state *state,
- YYLTYPE *loc)
-{
- if (qual->flags.q.invariant) {
- if (var->used) {
- _mesa_glsl_error(loc, state,
- "variable `%s' may not be redeclared "
- "`invariant' after being used",
- var->name);
- } else {
- var->invariant = 1;
- }
- }
-
- if (qual->flags.q.constant || qual->flags.q.attribute
- || qual->flags.q.uniform
- || (qual->flags.q.varying && (state->target == fragment_shader)))
- var->read_only = 1;
-
- if (qual->flags.q.centroid)
- var->centroid = 1;
-
- if (qual->flags.q.attribute && state->target != vertex_shader) {
- var->type = glsl_type::error_type;
- _mesa_glsl_error(loc, state,
- "`attribute' variables may not be declared in the "
- "%s shader",
- _mesa_glsl_shader_target_name(state->target));
- }
-
- /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
- *
- * "The varying qualifier can be used only with the data types
- * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
- * these."
- */
- if (qual->flags.q.varying) {
- const glsl_type *non_array_type;
-
- if (var->type && var->type->is_array())
- non_array_type = var->type->fields.array;
- else
- non_array_type = var->type;
-
- if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
- var->type = glsl_type::error_type;
- _mesa_glsl_error(loc, state,
- "varying variables must be of base type float");
- }
- }
-
- /* If there is no qualifier that changes the mode of the variable, leave
- * the setting alone.
- */
- if (qual->flags.q.in && qual->flags.q.out)
- var->mode = ir_var_inout;
- else if (qual->flags.q.attribute || qual->flags.q.in
- || (qual->flags.q.varying && (state->target == fragment_shader)))
- var->mode = ir_var_in;
- else if (qual->flags.q.out
- || (qual->flags.q.varying && (state->target == vertex_shader)))
- var->mode = ir_var_out;
- else if (qual->flags.q.uniform)
- var->mode = ir_var_uniform;
-
- if (state->all_invariant && (state->current_function == NULL)) {
- switch (state->target) {
- case vertex_shader:
- if (var->mode == ir_var_out)
- var->invariant = true;
- break;
- case geometry_shader:
- if ((var->mode == ir_var_in) || (var->mode == ir_var_out))
- var->invariant = true;
- break;
- case fragment_shader:
- if (var->mode == ir_var_in)
- var->invariant = true;
- break;
- }
- }
-
- if (qual->flags.q.flat)
- var->interpolation = ir_var_flat;
- else if (qual->flags.q.noperspective)
- var->interpolation = ir_var_noperspective;
- else
- var->interpolation = ir_var_smooth;
-
- var->pixel_center_integer = qual->flags.q.pixel_center_integer;
- var->origin_upper_left = qual->flags.q.origin_upper_left;
- if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
- && (strcmp(var->name, "gl_FragCoord") != 0)) {
- const char *const qual_string = (qual->flags.q.origin_upper_left)
- ? "origin_upper_left" : "pixel_center_integer";
-
- _mesa_glsl_error(loc, state,
- "layout qualifier `%s' can only be applied to "
- "fragment shader input `gl_FragCoord'",
- qual_string);
- }
-
- if (qual->flags.q.explicit_location) {
- const bool global_scope = (state->current_function == NULL);
- bool fail = false;
- const char *string = "";
-
- /* In the vertex shader only shader inputs can be given explicit
- * locations.
- *
- * In the fragment shader only shader outputs can be given explicit
- * locations.
- */
- switch (state->target) {
- case vertex_shader:
- if (!global_scope || (var->mode != ir_var_in)) {
- fail = true;
- string = "input";
- }
- break;
-
- case geometry_shader:
- _mesa_glsl_error(loc, state,
- "geometry shader variables cannot be given "
- "explicit locations\n");
- break;
-
- case fragment_shader:
- if (!global_scope || (var->mode != ir_var_in)) {
- fail = true;
- string = "output";
- }
- break;
- };
-
- if (fail) {
- _mesa_glsl_error(loc, state,
- "only %s shader %s variables can be given an "
- "explicit location\n",
- _mesa_glsl_shader_target_name(state->target),
- string);
- } else {
- var->explicit_location = true;
-
- /* This bit of silliness is needed because invalid explicit locations
- * are supposed to be flagged during linking. Small negative values
- * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
- * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
- * The linker needs to be able to differentiate these cases. This
- * ensures that negative values stay negative.
- */
- if (qual->location >= 0) {
- var->location = (state->target == vertex_shader)
- ? (qual->location + VERT_ATTRIB_GENERIC0)
- : (qual->location + FRAG_RESULT_DATA0);
- } else {
- var->location = qual->location;
- }
- }
- }
-
- /* Does the declaration use the 'layout' keyword?
- */
- const bool uses_layout = qual->flags.q.pixel_center_integer
- || qual->flags.q.origin_upper_left
- || qual->flags.q.explicit_location;
-
- /* Does the declaration use the deprecated 'attribute' or 'varying'
- * keywords?
- */
- const bool uses_deprecated_qualifier = qual->flags.q.attribute
- || qual->flags.q.varying;
-
- /* Is the 'layout' keyword used with parameters that allow relaxed checking.
- * Many implementations of GL_ARB_fragment_coord_conventions_enable and some
- * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
- * allowed the layout qualifier to be used with 'varying' and 'attribute'.
- * These extensions and all following extensions that add the 'layout'
- * keyword have been modified to require the use of 'in' or 'out'.
- *
- * The following extension do not allow the deprecated keywords:
- *
- * GL_AMD_conservative_depth
- * GL_ARB_gpu_shader5
- * GL_ARB_separate_shader_objects
- * GL_ARB_tesselation_shader
- * GL_ARB_transform_feedback3
- * GL_ARB_uniform_buffer_object
- *
- * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5
- * allow layout with the deprecated keywords.
- */
- const bool relaxed_layout_qualifier_checking =
- state->ARB_fragment_coord_conventions_enable;
-
- if (uses_layout && uses_deprecated_qualifier) {
- if (relaxed_layout_qualifier_checking) {
- _mesa_glsl_warning(loc, state,
- "`layout' qualifier may not be used with "
- "`attribute' or `varying'");
- } else {
- _mesa_glsl_error(loc, state,
- "`layout' qualifier may not be used with "
- "`attribute' or `varying'");
- }
- }
-
- if (var->type->is_array() && state->language_version != 110) {
- var->array_lvalue = true;
- }
-}
-
-
-ir_rvalue *
-ast_declarator_list::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- const struct glsl_type *decl_type;
- const char *type_name = NULL;
- ir_rvalue *result = NULL;
- YYLTYPE loc = this->get_location();
-
- /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec:
- *
- * "To ensure that a particular output variable is invariant, it is
- * necessary to use the invariant qualifier. It can either be used to
- * qualify a previously declared variable as being invariant
- *
- * invariant gl_Position; // make existing gl_Position be invariant"
- *
- * In these cases the parser will set the 'invariant' flag in the declarator
- * list, and the type will be NULL.
- */
- if (this->invariant) {
- assert(this->type == NULL);
-
- if (state->current_function != NULL) {
- _mesa_glsl_error(& loc, state,
- "All uses of `invariant' keyword must be at global "
- "scope\n");
- }
-
- foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
- assert(!decl->is_array);
- assert(decl->array_size == NULL);
- assert(decl->initializer == NULL);
-
- ir_variable *const earlier =
- state->symbols->get_variable(decl->identifier);
- if (earlier == NULL) {
- _mesa_glsl_error(& loc, state,
- "Undeclared variable `%s' cannot be marked "
- "invariant\n", decl->identifier);
- } else if ((state->target == vertex_shader)
- && (earlier->mode != ir_var_out)) {
- _mesa_glsl_error(& loc, state,
- "`%s' cannot be marked invariant, vertex shader "
- "outputs only\n", decl->identifier);
- } else if ((state->target == fragment_shader)
- && (earlier->mode != ir_var_in)) {
- _mesa_glsl_error(& loc, state,
- "`%s' cannot be marked invariant, fragment shader "
- "inputs only\n", decl->identifier);
- } else if (earlier->used) {
- _mesa_glsl_error(& loc, state,
- "variable `%s' may not be redeclared "
- "`invariant' after being used",
- earlier->name);
- } else {
- earlier->invariant = true;
- }
- }
-
- /* Invariant redeclarations do not have r-values.
- */
- return NULL;
- }
-
- assert(this->type != NULL);
- assert(!this->invariant);
-
- /* The type specifier may contain a structure definition. Process that
- * before any of the variable declarations.
- */
- (void) this->type->specifier->hir(instructions, state);
-
- decl_type = this->type->specifier->glsl_type(& type_name, state);
- if (this->declarations.is_empty()) {
- /* The only valid case where the declaration list can be empty is when
- * the declaration is setting the default precision of a built-in type
- * (e.g., 'precision highp vec4;').
- */
-
- if (decl_type != NULL) {
- } else {
- _mesa_glsl_error(& loc, state, "incomplete declaration");
- }
- }
-
- foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
- const struct glsl_type *var_type;
- ir_variable *var;
-
- /* FINISHME: Emit a warning if a variable declaration shadows a
- * FINISHME: declaration at a higher scope.
- */
-
- if ((decl_type == NULL) || decl_type->is_void()) {
- if (type_name != NULL) {
- _mesa_glsl_error(& loc, state,
- "invalid type `%s' in declaration of `%s'",
- type_name, decl->identifier);
- } else {
- _mesa_glsl_error(& loc, state,
- "invalid type in declaration of `%s'",
- decl->identifier);
- }
- continue;
- }
-
- if (decl->is_array) {
- var_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- } else {
- var_type = decl_type;
- }
-
- var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
-
- /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
- *
- * "Global variables can only use the qualifiers const,
- * attribute, uni form, or varying. Only one may be
- * specified.
- *
- * Local variables can only use the qualifier const."
- *
- * This is relaxed in GLSL 1.30. It is also relaxed by any extension
- * that adds the 'layout' keyword.
- */
- if ((state->language_version < 130)
- && !state->ARB_explicit_attrib_location_enable
- && !state->ARB_fragment_coord_conventions_enable) {
- if (this->type->qualifier.flags.q.out) {
- _mesa_glsl_error(& loc, state,
- "`out' qualifier in declaration of `%s' "
- "only valid for function parameters in %s.",
- decl->identifier, state->version_string);
- }
- if (this->type->qualifier.flags.q.in) {
- _mesa_glsl_error(& loc, state,
- "`in' qualifier in declaration of `%s' "
- "only valid for function parameters in %s.",
- decl->identifier, state->version_string);
- }
- /* FINISHME: Test for other invalid qualifiers. */
- }
-
- apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
- & loc);
-
- if (this->type->qualifier.flags.q.invariant) {
- if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
- var->mode == ir_var_inout)) {
- /* FINISHME: Note that this doesn't work for invariant on
- * a function signature outval
- */
- _mesa_glsl_error(& loc, state,
- "`%s' cannot be marked invariant, vertex shader "
- "outputs only\n", var->name);
- } else if ((state->target == fragment_shader) &&
- !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
- /* FINISHME: Note that this doesn't work for invariant on
- * a function signature inval
- */
- _mesa_glsl_error(& loc, state,
- "`%s' cannot be marked invariant, fragment shader "
- "inputs only\n", var->name);
- }
- }
-
- if (state->current_function != NULL) {
- const char *mode = NULL;
- const char *extra = "";
-
- /* There is no need to check for 'inout' here because the parser will
- * only allow that in function parameter lists.
- */
- if (this->type->qualifier.flags.q.attribute) {
- mode = "attribute";
- } else if (this->type->qualifier.flags.q.uniform) {
- mode = "uniform";
- } else if (this->type->qualifier.flags.q.varying) {
- mode = "varying";
- } else if (this->type->qualifier.flags.q.in) {
- mode = "in";
- extra = " or in function parameter list";
- } else if (this->type->qualifier.flags.q.out) {
- mode = "out";
- extra = " or in function parameter list";
- }
-
- if (mode) {
- _mesa_glsl_error(& loc, state,
- "%s variable `%s' must be declared at "
- "global scope%s",
- mode, var->name, extra);
- }
- } else if (var->mode == ir_var_in) {
- var->read_only = true;
-
- if (state->target == vertex_shader) {
- bool error_emitted = false;
-
- /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
- *
- * "Vertex shader inputs can only be float, floating-point
- * vectors, matrices, signed and unsigned integers and integer
- * vectors. Vertex shader inputs can also form arrays of these
- * types, but not structures."
- *
- * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec:
- *
- * "Vertex shader inputs can only be float, floating-point
- * vectors, matrices, signed and unsigned integers and integer
- * vectors. They cannot be arrays or structures."
- *
- * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec:
- *
- * "The attribute qualifier can be used only with float,
- * floating-point vectors, and matrices. Attribute variables
- * cannot be declared as arrays or structures."
- */
- const glsl_type *check_type = var->type->is_array()
- ? var->type->fields.array : var->type;
-
- switch (check_type->base_type) {
- case GLSL_TYPE_FLOAT:
- break;
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- if (state->language_version > 120)
- break;
- /* FALLTHROUGH */
- default:
- _mesa_glsl_error(& loc, state,
- "vertex shader input / attribute cannot have "
- "type %s`%s'",
- var->type->is_array() ? "array of " : "",
- check_type->name);
- error_emitted = true;
- }
-
- if (!error_emitted && (state->language_version <= 130)
- && var->type->is_array()) {
- _mesa_glsl_error(& loc, state,
- "vertex shader input / attribute cannot have "
- "array type");
- error_emitted = true;
- }
- }
- }
-
- /* Integer vertex outputs must be qualified with 'flat'.
- *
- * From section 4.3.6 of the GLSL 1.30 spec:
- * "If a vertex output is a signed or unsigned integer or integer
- * vector, then it must be qualified with the interpolation qualifier
- * flat."
- */
- if (state->language_version >= 130
- && state->target == vertex_shader
- && state->current_function == NULL
- && var->type->is_integer()
- && var->mode == ir_var_out
- && var->interpolation != ir_var_flat) {
-
- _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
- "then it must be qualified with 'flat'");
- }
-
-
- /* Interpolation qualifiers cannot be applied to 'centroid' and
- * 'centroid varying'.
- *
- * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
- * "interpolation qualifiers may only precede the qualifiers in,
- * centroid in, out, or centroid out in a declaration. They do not apply
- * to the deprecated storage qualifiers varying or centroid varying."
- */
- if (state->language_version >= 130
- && this->type->qualifier.has_interpolation()
- && this->type->qualifier.flags.q.varying) {
-
- const char *i = this->type->qualifier.interpolation_string();
- assert(i != NULL);
- const char *s;
- if (this->type->qualifier.flags.q.centroid)
- s = "centroid varying";
- else
- s = "varying";
-
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to the "
- "deprecated storage qualifier '%s'", i, s);
- }
-
-
- /* Interpolation qualifiers can only apply to vertex shader outputs and
- * fragment shader inputs.
- *
- * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
- * "Outputs from a vertex shader (out) and inputs to a fragment
- * shader (in) can be further qualified with one or more of these
- * interpolation qualifiers"
- */
- if (state->language_version >= 130
- && this->type->qualifier.has_interpolation()) {
-
- const char *i = this->type->qualifier.interpolation_string();
- assert(i != NULL);
-
- switch (state->target) {
- case vertex_shader:
- if (this->type->qualifier.flags.q.in) {
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to vertex "
- "shader inputs", i);
- }
- break;
- case fragment_shader:
- if (this->type->qualifier.flags.q.out) {
- _mesa_glsl_error(&loc, state,
- "qualifier '%s' cannot be applied to fragment "
- "shader outputs", i);
- }
- break;
- default:
- assert(0);
- }
- }
-
-
- /* From section 4.3.4 of the GLSL 1.30 spec:
- * "It is an error to use centroid in in a vertex shader."
- */
- if (state->language_version >= 130
- && this->type->qualifier.flags.q.centroid
- && this->type->qualifier.flags.q.in
- && state->target == vertex_shader) {
-
- _mesa_glsl_error(&loc, state,
- "'centroid in' cannot be used in a vertex shader");
- }
-
-
- /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
- */
- if (this->type->specifier->precision != ast_precision_none
- && state->language_version != 100
- && state->language_version < 130) {
-
- _mesa_glsl_error(&loc, state,
- "precision qualifiers are supported only in GLSL ES "
- "1.00, and GLSL 1.30 and later");
- }
-
-
- /* Precision qualifiers only apply to floating point and integer types.
- *
- * From section 4.5.2 of the GLSL 1.30 spec:
- * "Any floating point or any integer declaration can have the type
- * preceded by one of these precision qualifiers [...] Literal
- * constants do not have precision qualifiers. Neither do Boolean
- * variables.
- */
- if (this->type->specifier->precision != ast_precision_none
- && !var->type->is_float()
- && !var->type->is_integer()
- && !(var->type->is_array()
- && (var->type->fields.array->is_float()
- || var->type->fields.array->is_integer()))) {
-
- _mesa_glsl_error(&loc, state,
- "precision qualifiers apply only to floating point "
- "and integer types");
- }
-
- /* Process the initializer and add its instructions to a temporary
- * list. This list will be added to the instruction stream (below) after
- * the declaration is added. This is done because in some cases (such as
- * redeclarations) the declaration may not actually be added to the
- * instruction stream.
- */
- exec_list initializer_instructions;
- if (decl->initializer != NULL) {
- YYLTYPE initializer_loc = decl->initializer->get_location();
-
- /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
- *
- * "All uniform variables are read-only and are initialized either
- * directly by an application via API commands, or indirectly by
- * OpenGL."
- */
- if ((state->language_version <= 110)
- && (var->mode == ir_var_uniform)) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize uniforms in GLSL 1.10");
- }
-
- if (var->type->is_sampler()) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize samplers");
- }
-
- if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize %s shader input / %s",
- _mesa_glsl_shader_target_name(state->target),
- (state->target == vertex_shader)
- ? "attribute" : "varying");
- }
-
- ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
- ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
- state);
-
- /* Calculate the constant value if this is a const or uniform
- * declaration.
- */
- if (this->type->qualifier.flags.q.constant
- || this->type->qualifier.flags.q.uniform) {
- ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
- if (new_rhs != NULL) {
- rhs = new_rhs;
-
- ir_constant *constant_value = rhs->constant_expression_value();
- if (!constant_value) {
- _mesa_glsl_error(& initializer_loc, state,
- "initializer of %s variable `%s' must be a "
- "constant expression",
- (this->type->qualifier.flags.q.constant)
- ? "const" : "uniform",
- decl->identifier);
- if (var->type->is_numeric()) {
- /* Reduce cascading errors. */
- var->constant_value = ir_constant::zero(ctx, var->type);
- }
- } else {
- rhs = constant_value;
- var->constant_value = constant_value;
- }
- } else {
- _mesa_glsl_error(&initializer_loc, state,
- "initializer of type %s cannot be assigned to "
- "variable of type %s",
- rhs->type->name, var->type->name);
- if (var->type->is_numeric()) {
- /* Reduce cascading errors. */
- var->constant_value = ir_constant::zero(ctx, var->type);
- }
- }
- }
-
- if (rhs && !rhs->type->is_error()) {
- bool temp = var->read_only;
- if (this->type->qualifier.flags.q.constant)
- var->read_only = false;
-
- /* Never emit code to initialize a uniform.
- */
- const glsl_type *initializer_type;
- if (!this->type->qualifier.flags.q.uniform) {
- result = do_assignment(&initializer_instructions, state,
- lhs, rhs,
- this->get_location());
- initializer_type = result->type;
- } else
- initializer_type = rhs->type;
-
- /* If the declared variable is an unsized array, it must inherrit
- * its full type from the initializer. A declaration such as
- *
- * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
- *
- * becomes
- *
- * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
- *
- * The assignment generated in the if-statement (below) will also
- * automatically handle this case for non-uniforms.
- *
- * If the declared variable is not an array, the types must
- * already match exactly. As a result, the type assignment
- * here can be done unconditionally. For non-uniforms the call
- * to do_assignment can change the type of the initializer (via
- * the implicit conversion rules). For uniforms the initializer
- * must be a constant expression, and the type of that expression
- * was validated above.
- */
- var->type = initializer_type;
-
- var->read_only = temp;
- }
- }
-
- /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
- *
- * "It is an error to write to a const variable outside of
- * its declaration, so they must be initialized when
- * declared."
- */
- if (this->type->qualifier.flags.q.constant && decl->initializer == NULL) {
- _mesa_glsl_error(& loc, state,
- "const declaration of `%s' must be initialized",
- decl->identifier);
- }
-
- /* Check if this declaration is actually a re-declaration, either to
- * resize an array or add qualifiers to an existing variable.
- *
- * This is allowed for variables in the current scope, or when at
- * global scope (for built-ins in the implicit outer scope).
- */
- ir_variable *earlier = state->symbols->get_variable(decl->identifier);
- if (earlier != NULL && (state->current_function == NULL ||
- state->symbols->name_declared_this_scope(decl->identifier))) {
-
- /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
- *
- * "It is legal to declare an array without a size and then
- * later re-declare the same name as an array of the same
- * type and specify a size."
- */
- if ((earlier->type->array_size() == 0)
- && var->type->is_array()
- && (var->type->element_type() == earlier->type->element_type())) {
- /* FINISHME: This doesn't match the qualifiers on the two
- * FINISHME: declarations. It's not 100% clear whether this is
- * FINISHME: required or not.
- */
-
- /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
- *
- * "The size [of gl_TexCoord] can be at most
- * gl_MaxTextureCoords."
- */
- const unsigned size = unsigned(var->type->array_size());
- if ((strcmp("gl_TexCoord", var->name) == 0)
- && (size > state->Const.MaxTextureCoords)) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
- "be larger than gl_MaxTextureCoords (%u)\n",
- state->Const.MaxTextureCoords);
- } else if ((size > 0) && (size <= earlier->max_array_access)) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "array size must be > %u due to "
- "previous access",
- earlier->max_array_access);
- }
-
- earlier->type = var->type;
- delete var;
- var = NULL;
- } else if (state->ARB_fragment_coord_conventions_enable
- && strcmp(var->name, "gl_FragCoord") == 0
- && earlier->type == var->type
- && earlier->mode == var->mode) {
- /* Allow redeclaration of gl_FragCoord for ARB_fcc layout
- * qualifiers.
- */
- earlier->origin_upper_left = var->origin_upper_left;
- earlier->pixel_center_integer = var->pixel_center_integer;
-
- /* According to section 4.3.7 of the GLSL 1.30 spec,
- * the following built-in varaibles can be redeclared with an
- * interpolation qualifier:
- * * gl_FrontColor
- * * gl_BackColor
- * * gl_FrontSecondaryColor
- * * gl_BackSecondaryColor
- * * gl_Color
- * * gl_SecondaryColor
- */
- } else if (state->language_version >= 130
- && (strcmp(var->name, "gl_FrontColor") == 0
- || strcmp(var->name, "gl_BackColor") == 0
- || strcmp(var->name, "gl_FrontSecondaryColor") == 0
- || strcmp(var->name, "gl_BackSecondaryColor") == 0
- || strcmp(var->name, "gl_Color") == 0
- || strcmp(var->name, "gl_SecondaryColor") == 0)
- && earlier->type == var->type
- && earlier->mode == var->mode) {
- earlier->interpolation = var->interpolation;
- } else {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
- }
-
- continue;
- }
-
- /* By now, we know it's a new variable declaration (we didn't hit the
- * above "continue").
- *
- * From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
- *
- * "Identifiers starting with "gl_" are reserved for use by
- * OpenGL, and may not be declared in a shader as either a
- * variable or a function."
- */
- if (strncmp(decl->identifier, "gl_", 3) == 0)
- _mesa_glsl_error(& loc, state,
- "identifier `%s' uses reserved `gl_' prefix",
- decl->identifier);
-
- /* Add the variable to the symbol table. Note that the initializer's
- * IR was already processed earlier (though it hasn't been emitted yet),
- * without the variable in scope.
- *
- * This differs from most C-like languages, but it follows the GLSL
- * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50
- * spec:
- *
- * "Within a declaration, the scope of a name starts immediately
- * after the initializer if present or immediately after the name
- * being declared if not."
- */
- if (!state->symbols->add_variable(var)) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
- "current scope", decl->identifier);
- continue;
- }
-
- /* Push the variable declaration to the top. It means that all
- * the variable declarations will appear in a funny
- * last-to-first order, but otherwise we run into trouble if a
- * function is prototyped, a global var is decled, then the
- * function is defined with usage of the global var. See
- * glslparsertest's CorrectModule.frag.
- */
- instructions->push_head(var);
- instructions->append_list(&initializer_instructions);
- }
-
-
- /* Generally, variable declarations do not have r-values. However,
- * one is used for the declaration in
- *
- * while (bool b = some_condition()) {
- * ...
- * }
- *
- * so we return the rvalue from the last seen declaration here.
- */
- return result;
-}
-
-
-ir_rvalue *
-ast_parameter_declarator::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- const struct glsl_type *type;
- const char *name = NULL;
- YYLTYPE loc = this->get_location();
-
- type = this->type->specifier->glsl_type(& name, state);
-
- if (type == NULL) {
- if (name != NULL) {
- _mesa_glsl_error(& loc, state,
- "invalid type `%s' in declaration of `%s'",
- name, this->identifier);
- } else {
- _mesa_glsl_error(& loc, state,
- "invalid type in declaration of `%s'",
- this->identifier);
- }
-
- type = glsl_type::error_type;
- }
-
- /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec:
- *
- * "Functions that accept no input arguments need not use void in the
- * argument list because prototypes (or definitions) are required and
- * therefore there is no ambiguity when an empty argument list "( )" is
- * declared. The idiom "(void)" as a parameter list is provided for
- * convenience."
- *
- * Placing this check here prevents a void parameter being set up
- * for a function, which avoids tripping up checks for main taking
- * parameters and lookups of an unnamed symbol.
- */
- if (type->is_void()) {
- if (this->identifier != NULL)
- _mesa_glsl_error(& loc, state,
- "named parameter cannot have type `void'");
-
- is_void = true;
- return NULL;
- }
-
- if (formal_parameter && (this->identifier == NULL)) {
- _mesa_glsl_error(& loc, state, "formal parameter lacks a name");
- return NULL;
- }
-
- /* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...)
- * call already handled the "vec4[..] foo" case.
- */
- if (this->is_array) {
- type = process_array_type(&loc, type, this->array_size, state);
- }
-
- if (type->array_size() == 0) {
- _mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
- "a declared size.");
- type = glsl_type::error_type;
- }
-
- is_void = false;
- ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
-
- /* Apply any specified qualifiers to the parameter declaration. Note that
- * for function parameters the default mode is 'in'.
- */
- apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
-
- instructions->push_tail(var);
-
- /* Parameter declarations do not have r-values.
- */
- return NULL;
-}
-
-
-void
-ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
- bool formal,
- exec_list *ir_parameters,
- _mesa_glsl_parse_state *state)
-{
- ast_parameter_declarator *void_param = NULL;
- unsigned count = 0;
-
- foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) {
- param->formal_parameter = formal;
- param->hir(ir_parameters, state);
-
- if (param->is_void)
- void_param = param;
-
- count++;
- }
-
- if ((void_param != NULL) && (count > 1)) {
- YYLTYPE loc = void_param->get_location();
-
- _mesa_glsl_error(& loc, state,
- "`void' parameter must be only parameter");
- }
-}
-
-
-void
-emit_function(_mesa_glsl_parse_state *state, exec_list *instructions,
- ir_function *f)
-{
- /* Emit the new function header */
- if (state->current_function == NULL) {
- instructions->push_tail(f);
- } else {
- /* IR invariants disallow function declarations or definitions nested
- * within other function definitions. Insert the new ir_function
- * block in the instruction sequence before the ir_function block
- * containing the current ir_function_signature.
- */
- ir_function *const curr =
- const_cast<ir_function *>(state->current_function->function());
-
- curr->insert_before(f);
- }
-}
-
-
-ir_rvalue *
-ast_function::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- ir_function *f = NULL;
- ir_function_signature *sig = NULL;
- exec_list hir_parameters;
-
- const char *const name = identifier;
-
- /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec,
- *
- * "Function declarations (prototypes) cannot occur inside of functions;
- * they must be at global scope, or for the built-in functions, outside
- * the global scope."
- *
- * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec,
- *
- * "User defined functions may only be defined within the global scope."
- *
- * Note that this language does not appear in GLSL 1.10.
- */
- if ((state->current_function != NULL) && (state->language_version != 110)) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state,
- "declaration of function `%s' not allowed within "
- "function body", name);
- }
-
- /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
- *
- * "Identifiers starting with "gl_" are reserved for use by
- * OpenGL, and may not be declared in a shader as either a
- * variable or a function."
- */
- if (strncmp(name, "gl_", 3) == 0) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state,
- "identifier `%s' uses reserved `gl_' prefix", name);
- }
-
- /* Convert the list of function parameters to HIR now so that they can be
- * used below to compare this function's signature with previously seen
- * signatures for functions with the same name.
- */
- ast_parameter_declarator::parameters_to_hir(& this->parameters,
- is_definition,
- & hir_parameters, state);
-
- const char *return_type_name;
- const glsl_type *return_type =
- this->return_type->specifier->glsl_type(& return_type_name, state);
-
- if (!return_type) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state,
- "function `%s' has undeclared return type `%s'",
- name, return_type_name);
- return_type = glsl_type::error_type;
- }
-
- /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec:
- * "No qualifier is allowed on the return type of a function."
- */
- if (this->return_type->has_qualifiers()) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(& loc, state,
- "function `%s' return type has qualifiers", name);
- }
-
- /* Verify that this function's signature either doesn't match a previously
- * seen signature for a function with the same name, or, if a match is found,
- * that the previously seen signature does not have an associated definition.
- */
- f = state->symbols->get_function(name);
- if (f != NULL && (state->es_shader || f->has_user_signature())) {
- sig = f->exact_matching_signature(&hir_parameters);
- if (sig != NULL) {
- const char *badvar = sig->qualifiers_match(&hir_parameters);
- if (badvar != NULL) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
- "qualifiers don't match prototype", name, badvar);
- }
-
- if (sig->return_type != return_type) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
- "match prototype", name);
- }
-
- if (is_definition && sig->is_defined) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
- }
- }
- } else {
- f = new(ctx) ir_function(name);
- if (!state->symbols->add_function(f)) {
- /* This function name shadows a non-function use of the same name. */
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
- "non-function", name);
- return NULL;
- }
-
- emit_function(state, instructions, f);
- }
-
- /* Verify the return type of main() */
- if (strcmp(name, "main") == 0) {
- if (! return_type->is_void()) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "main() must return void");
- }
-
- if (!hir_parameters.is_empty()) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "main() must not take any parameters");
- }
- }
-
- /* Finish storing the information about this new function in its signature.
- */
- if (sig == NULL) {
- sig = new(ctx) ir_function_signature(return_type);
- f->add_signature(sig);
- }
-
- sig->replace_parameters(&hir_parameters);
- signature = sig;
-
- /* Function declarations (prototypes) do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_function_definition::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- prototype->is_definition = true;
- prototype->hir(instructions, state);
-
- ir_function_signature *signature = prototype->signature;
- if (signature == NULL)
- return NULL;
-
- assert(state->current_function == NULL);
- state->current_function = signature;
- state->found_return = false;
-
- /* Duplicate parameters declared in the prototype as concrete variables.
- * Add these to the symbol table.
- */
- state->symbols->push_scope();
- foreach_iter(exec_list_iterator, iter, signature->parameters) {
- ir_variable *const var = ((ir_instruction *) iter.get())->as_variable();
-
- assert(var != NULL);
-
- /* The only way a parameter would "exist" is if two parameters have
- * the same name.
- */
- if (state->symbols->name_declared_this_scope(var->name)) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name);
- } else {
- state->symbols->add_variable(var);
- }
- }
-
- /* Convert the body of the function to HIR. */
- this->body->hir(&signature->body, state);
- signature->is_defined = true;
-
- state->symbols->pop_scope();
-
- assert(state->current_function == signature);
- state->current_function = NULL;
-
- if (!signature->return_type->is_void() && !state->found_return) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(& loc, state, "function `%s' has non-void return type "
- "%s, but no return statement",
- signature->function_name(),
- signature->return_type->name);
- }
-
- /* Function definitions do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_jump_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- switch (mode) {
- case ast_return: {
- ir_return *inst;
- assert(state->current_function);
-
- if (opt_return_value) {
- ir_rvalue *const ret = opt_return_value->hir(instructions, state);
-
- /* The value of the return type can be NULL if the shader says
- * 'return foo();' and foo() is a function that returns void.
- *
- * NOTE: The GLSL spec doesn't say that this is an error. The type
- * of the return value is void. If the return type of the function is
- * also void, then this should compile without error. Seriously.
- */
- const glsl_type *const ret_type =
- (ret == NULL) ? glsl_type::void_type : ret->type;
-
- /* Implicit conversions are not allowed for return values. */
- if (state->current_function->return_type != ret_type) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state,
- "`return' with wrong type %s, in function `%s' "
- "returning %s",
- ret_type->name,
- state->current_function->function_name(),
- state->current_function->return_type->name);
- }
-
- inst = new(ctx) ir_return(ret);
- } else {
- if (state->current_function->return_type->base_type !=
- GLSL_TYPE_VOID) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state,
- "`return' with no value, in function %s returning "
- "non-void",
- state->current_function->function_name());
- }
- inst = new(ctx) ir_return;
- }
-
- state->found_return = true;
- instructions->push_tail(inst);
- break;
- }
-
- case ast_discard:
- if (state->target != fragment_shader) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state,
- "`discard' may only appear in a fragment shader");
- }
- instructions->push_tail(new(ctx) ir_discard);
- break;
-
- case ast_break:
- case ast_continue:
- /* FINISHME: Handle switch-statements. They cannot contain 'continue',
- * FINISHME: and they use a different IR instruction for 'break'.
- */
- /* FINISHME: Correctly handle the nesting. If a switch-statement is
- * FINISHME: inside a loop, a 'continue' is valid and will bind to the
- * FINISHME: loop.
- */
- if (state->loop_or_switch_nesting == NULL) {
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(& loc, state,
- "`%s' may only appear in a loop",
- (mode == ast_break) ? "break" : "continue");
- } else {
- ir_loop *const loop = state->loop_or_switch_nesting->as_loop();
-
- /* Inline the for loop expression again, since we don't know
- * where near the end of the loop body the normal copy of it
- * is going to be placed.
- */
- if (mode == ast_continue &&
- state->loop_or_switch_nesting_ast->rest_expression) {
- state->loop_or_switch_nesting_ast->rest_expression->hir(instructions,
- state);
- }
-
- if (loop != NULL) {
- ir_loop_jump *const jump =
- new(ctx) ir_loop_jump((mode == ast_break)
- ? ir_loop_jump::jump_break
- : ir_loop_jump::jump_continue);
- instructions->push_tail(jump);
- }
- }
-
- break;
- }
-
- /* Jump instructions do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_selection_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- ir_rvalue *const condition = this->condition->hir(instructions, state);
-
- /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec:
- *
- * "Any expression whose type evaluates to a Boolean can be used as the
- * conditional expression bool-expression. Vector types are not accepted
- * as the expression to if."
- *
- * The checks are separated so that higher quality diagnostics can be
- * generated for cases where both rules are violated.
- */
- if (!condition->type->is_boolean() || !condition->type->is_scalar()) {
- YYLTYPE loc = this->condition->get_location();
-
- _mesa_glsl_error(& loc, state, "if-statement condition must be scalar "
- "boolean");
- }
-
- ir_if *const stmt = new(ctx) ir_if(condition);
-
- if (then_statement != NULL) {
- state->symbols->push_scope();
- then_statement->hir(& stmt->then_instructions, state);
- state->symbols->pop_scope();
- }
-
- if (else_statement != NULL) {
- state->symbols->push_scope();
- else_statement->hir(& stmt->else_instructions, state);
- state->symbols->pop_scope();
- }
-
- instructions->push_tail(stmt);
-
- /* if-statements do not have r-values.
- */
- return NULL;
-}
-
-
-void
-ast_iteration_statement::condition_to_hir(ir_loop *stmt,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- if (condition != NULL) {
- ir_rvalue *const cond =
- condition->hir(& stmt->body_instructions, state);
-
- if ((cond == NULL)
- || !cond->type->is_boolean() || !cond->type->is_scalar()) {
- YYLTYPE loc = condition->get_location();
-
- _mesa_glsl_error(& loc, state,
- "loop condition must be scalar boolean");
- } else {
- /* As the first code in the loop body, generate a block that looks
- * like 'if (!condition) break;' as the loop termination condition.
- */
- ir_rvalue *const not_cond =
- new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
- NULL);
-
- ir_if *const if_stmt = new(ctx) ir_if(not_cond);
-
- ir_jump *const break_stmt =
- new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
-
- if_stmt->then_instructions.push_tail(break_stmt);
- stmt->body_instructions.push_tail(if_stmt);
- }
- }
-}
-
-
-ir_rvalue *
-ast_iteration_statement::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
-
- /* For-loops and while-loops start a new scope, but do-while loops do not.
- */
- if (mode != ast_do_while)
- state->symbols->push_scope();
-
- if (init_statement != NULL)
- init_statement->hir(instructions, state);
-
- ir_loop *const stmt = new(ctx) ir_loop();
- instructions->push_tail(stmt);
-
- /* Track the current loop and / or switch-statement nesting.
- */
- ir_instruction *const nesting = state->loop_or_switch_nesting;
- ast_iteration_statement *nesting_ast = state->loop_or_switch_nesting_ast;
-
- state->loop_or_switch_nesting = stmt;
- state->loop_or_switch_nesting_ast = this;
-
- if (mode != ast_do_while)
- condition_to_hir(stmt, state);
-
- if (body != NULL)
- body->hir(& stmt->body_instructions, state);
-
- if (rest_expression != NULL)
- rest_expression->hir(& stmt->body_instructions, state);
-
- if (mode == ast_do_while)
- condition_to_hir(stmt, state);
-
- if (mode != ast_do_while)
- state->symbols->pop_scope();
-
- /* Restore previous nesting before returning.
- */
- state->loop_or_switch_nesting = nesting;
- state->loop_or_switch_nesting_ast = nesting_ast;
-
- /* Loops do not have r-values.
- */
- return NULL;
-}
-
-
-ir_rvalue *
-ast_type_specifier::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- if (!this->is_precision_statement && this->structure == NULL)
- return NULL;
-
- YYLTYPE loc = this->get_location();
-
- if (this->precision != ast_precision_none
- && state->language_version != 100
- && state->language_version < 130) {
- _mesa_glsl_error(&loc, state,
- "precision qualifiers exist only in "
- "GLSL ES 1.00, and GLSL 1.30 and later");
- return NULL;
- }
- if (this->precision != ast_precision_none
- && this->structure != NULL) {
- _mesa_glsl_error(&loc, state,
- "precision qualifiers do not apply to structures");
- return NULL;
- }
-
- /* If this is a precision statement, check that the type to which it is
- * applied is either float or int.
- *
- * From section 4.5.3 of the GLSL 1.30 spec:
- * "The precision statement
- * precision precision-qualifier type;
- * can be used to establish a default precision qualifier. The type
- * field can be either int or float [...]. Any other types or
- * qualifiers will result in an error.
- */
- if (this->is_precision_statement) {
- assert(this->precision != ast_precision_none);
- assert(this->structure == NULL); /* The check for structures was
- * performed above. */
- if (this->is_array) {
- _mesa_glsl_error(&loc, state,
- "default precision statements do not apply to "
- "arrays");
- return NULL;
- }
- if (this->type_specifier != ast_float
- && this->type_specifier != ast_int) {
- _mesa_glsl_error(&loc, state,
- "default precision statements apply only to types "
- "float and int");
- return NULL;
- }
-
- /* FINISHME: Translate precision statements into IR. */
- return NULL;
- }
-
- if (this->structure != NULL)
- return this->structure->hir(instructions, state);
-
- return NULL;
-}
-
-
-ir_rvalue *
-ast_struct_specifier::hir(exec_list *instructions,
- struct _mesa_glsl_parse_state *state)
-{
- unsigned decl_count = 0;
-
- /* Make an initial pass over the list of structure fields to determine how
- * many there are. Each element in this list is an ast_declarator_list.
- * This means that we actually need to count the number of elements in the
- * 'declarations' list in each of the elements.
- */
- foreach_list_typed (ast_declarator_list, decl_list, link,
- &this->declarations) {
- foreach_list_const (decl_ptr, & decl_list->declarations) {
- decl_count++;
- }
- }
-
- /* Allocate storage for the structure fields and process the field
- * declarations. As the declarations are processed, try to also convert
- * the types to HIR. This ensures that structure definitions embedded in
- * other structure definitions are processed.
- */
- glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
- decl_count);
-
- unsigned i = 0;
- foreach_list_typed (ast_declarator_list, decl_list, link,
- &this->declarations) {
- const char *type_name;
-
- decl_list->type->specifier->hir(instructions, state);
-
- /* Section 10.9 of the GLSL ES 1.00 specification states that
- * embedded structure definitions have been removed from the language.
- */
- if (state->es_shader && decl_list->type->specifier->structure != NULL) {
- YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state, "Embedded structure definitions are "
- "not allowed in GLSL ES 1.00.");
- }
-
- const glsl_type *decl_type =
- decl_list->type->specifier->glsl_type(& type_name, state);
-
- foreach_list_typed (ast_declaration, decl, link,
- &decl_list->declarations) {
- const struct glsl_type *field_type = decl_type;
- if (decl->is_array) {
- YYLTYPE loc = decl->get_location();
- field_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
- }
- fields[i].type = (field_type != NULL)
- ? field_type : glsl_type::error_type;
- fields[i].name = decl->identifier;
- i++;
- }
- }
-
- assert(i == decl_count);
-
- const glsl_type *t =
- glsl_type::get_record_instance(fields, decl_count, this->name);
-
- YYLTYPE loc = this->get_location();
- if (!state->symbols->add_type(name, t)) {
- _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
- } else {
-
- const glsl_type **s = (const glsl_type **)
- realloc(state->user_structures,
- sizeof(state->user_structures[0]) *
- (state->num_user_structures + 1));
- if (s != NULL) {
- s[state->num_user_structures] = t;
- state->user_structures = s;
- state->num_user_structures++;
- }
- }
-
- /* Structure type definitions do not have r-values.
- */
- return NULL;
-}
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 ast_to_hir.c
+ * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
+ *
+ * During the conversion to HIR, the majority of the symantic checking is
+ * preformed on the program. This includes:
+ *
+ * * Symbol table management
+ * * Type checking
+ * * Function binding
+ *
+ * The majority of this work could be done during parsing, and the parser could
+ * probably generate HIR directly. However, this results in frequent changes
+ * to the parser code. Since we do not assume that every system this complier
+ * is built on will have Flex and Bison installed, we have to store the code
+ * generated by these tools in our version control system. In other parts of
+ * the system we've seen problems where a parser was changed but the generated
+ * code was not committed, merge conflicts where created because two developers
+ * had slightly different versions of Bison installed, etc.
+ *
+ * I have also noticed that running Bison generated parsers in GDB is very
+ * irritating. When you get a segfault on '$$ = $1->foo', you can't very
+ * well 'print $1' in GDB.
+ *
+ * As a result, my preference is to put as little C code as possible in the
+ * parser (and lexer) sources.
+ */
+
+#include "main/core.h" /* for struct gl_extensions */
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+
+void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
+{
+ _mesa_glsl_initialize_variables(instructions, state);
+ _mesa_glsl_initialize_functions(state);
+
+ state->symbols->language_version = state->language_version;
+
+ state->current_function = NULL;
+
+ /* Section 4.2 of the GLSL 1.20 specification states:
+ * "The built-in functions are scoped in a scope outside the global scope
+ * users declare global variables in. That is, a shader's global scope,
+ * available for user-defined functions and global variables, is nested
+ * inside the scope containing the built-in functions."
+ *
+ * Since built-in functions like ftransform() access built-in variables,
+ * it follows that those must be in the outer scope as well.
+ *
+ * We push scope here to create this nesting effect...but don't pop.
+ * This way, a shader's globals are still in the symbol table for use
+ * by the linker.
+ */
+ state->symbols->push_scope();
+
+ foreach_list_typed (ast_node, ast, link, & state->translation_unit)
+ ast->hir(instructions, state);
+}
+
+
+/**
+ * If a conversion is available, convert one operand to a different type
+ *
+ * The \c from \c ir_rvalue is converted "in place".
+ *
+ * \param to Type that the operand it to be converted to
+ * \param from Operand that is being converted
+ * \param state GLSL compiler state
+ *
+ * \return
+ * If a conversion is possible (or unnecessary), \c true is returned.
+ * Otherwise \c false is returned.
+ */
+bool
+apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ if (to->base_type == from->type->base_type)
+ return true;
+
+ /* This conversion was added in GLSL 1.20. If the compilation mode is
+ * GLSL 1.10, the conversion is skipped.
+ */
+ if (state->language_version < 120)
+ return false;
+
+ /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "There are no implicit array or structure conversions. For
+ * example, an array of int cannot be implicitly converted to an
+ * array of float. There are no implicit conversions between
+ * signed and unsigned integers."
+ */
+ /* FINISHME: The above comment is partially a lie. There is int/uint
+ * FINISHME: conversion for immediate constants.
+ */
+ if (!to->is_float() || !from->type->is_numeric())
+ return false;
+
+ /* Convert to a floating point type with the same number of components
+ * as the original type - i.e. int to float, not int to vec4.
+ */
+ to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements,
+ from->type->matrix_columns);
+
+ switch (from->type->base_type) {
+ case GLSL_TYPE_INT:
+ from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL);
+ break;
+ case GLSL_TYPE_UINT:
+ from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL);
+ break;
+ case GLSL_TYPE_BOOL:
+ from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL);
+ break;
+ default:
+ assert(0);
+ }
+
+ return true;
+}
+
+
+static const struct glsl_type *
+arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+ bool multiply,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ const glsl_type *type_a = value_a->type;
+ const glsl_type *type_b = value_b->type;
+
+ /* From GLSL 1.50 spec, page 56:
+ *
+ * "The arithmetic binary operators add (+), subtract (-),
+ * multiply (*), and divide (/) operate on integer and
+ * floating-point scalars, vectors, and matrices."
+ */
+ if (!type_a->is_numeric() || !type_b->is_numeric()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to arithmetic operators must be numeric");
+ return glsl_type::error_type;
+ }
+
+
+ /* "If one operand is floating-point based and the other is
+ * not, then the conversions from Section 4.1.10 "Implicit
+ * Conversions" are applied to the non-floating-point-based operand."
+ */
+ if (!apply_implicit_conversion(type_a, value_b, state)
+ && !apply_implicit_conversion(type_b, value_a, state)) {
+ _mesa_glsl_error(loc, state,
+ "Could not implicitly convert operands to "
+ "arithmetic operator");
+ return glsl_type::error_type;
+ }
+ type_a = value_a->type;
+ type_b = value_b->type;
+
+ /* "If the operands are integer types, they must both be signed or
+ * both be unsigned."
+ *
+ * From this rule and the preceeding conversion it can be inferred that
+ * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
+ * The is_numeric check above already filtered out the case where either
+ * type is not one of these, so now the base types need only be tested for
+ * equality.
+ */
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state,
+ "base type mismatch for arithmetic operator");
+ return glsl_type::error_type;
+ }
+
+ /* "All arithmetic binary operators result in the same fundamental type
+ * (signed integer, unsigned integer, or floating-point) as the
+ * operands they operate on, after operand type conversion. After
+ * conversion, the following cases are valid
+ *
+ * * The two operands are scalars. In this case the operation is
+ * applied, resulting in a scalar."
+ */
+ if (type_a->is_scalar() && type_b->is_scalar())
+ return type_a;
+
+ /* "* One operand is a scalar, and the other is a vector or matrix.
+ * In this case, the scalar operation is applied independently to each
+ * component of the vector or matrix, resulting in the same size
+ * vector or matrix."
+ */
+ if (type_a->is_scalar()) {
+ if (!type_b->is_scalar())
+ return type_b;
+ } else if (type_b->is_scalar()) {
+ return type_a;
+ }
+
+ /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+ * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
+ * handled.
+ */
+ assert(!type_a->is_scalar());
+ assert(!type_b->is_scalar());
+
+ /* "* The two operands are vectors of the same size. In this case, the
+ * operation is done component-wise resulting in the same size
+ * vector."
+ */
+ if (type_a->is_vector() && type_b->is_vector()) {
+ if (type_a == type_b) {
+ return type_a;
+ } else {
+ _mesa_glsl_error(loc, state,
+ "vector size mismatch for arithmetic operator");
+ return glsl_type::error_type;
+ }
+ }
+
+ /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+ * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
+ * <vector, vector> have been handled. At least one of the operands must
+ * be matrix. Further, since there are no integer matrix types, the base
+ * type of both operands must be float.
+ */
+ assert(type_a->is_matrix() || type_b->is_matrix());
+ assert(type_a->base_type == GLSL_TYPE_FLOAT);
+ assert(type_b->base_type == GLSL_TYPE_FLOAT);
+
+ /* "* The operator is add (+), subtract (-), or divide (/), and the
+ * operands are matrices with the same number of rows and the same
+ * number of columns. In this case, the operation is done component-
+ * wise resulting in the same size matrix."
+ * * The operator is multiply (*), where both operands are matrices or
+ * one operand is a vector and the other a matrix. A right vector
+ * operand is treated as a column vector and a left vector operand as a
+ * row vector. In all these cases, it is required that the number of
+ * columns of the left operand is equal to the number of rows of the
+ * right operand. Then, the multiply (*) operation does a linear
+ * algebraic multiply, yielding an object that has the same number of
+ * rows as the left operand and the same number of columns as the right
+ * operand. Section 5.10 "Vector and Matrix Operations" explains in
+ * more detail how vectors and matrices are operated on."
+ */
+ if (! multiply) {
+ if (type_a == type_b)
+ return type_a;
+ } else {
+ if (type_a->is_matrix() && type_b->is_matrix()) {
+ /* Matrix multiply. The columns of A must match the rows of B. Given
+ * the other previously tested constraints, this means the vector type
+ * of a row from A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a->row_type() == type_b->column_type()) {
+ /* The resulting matrix has the number of columns of matrix B and
+ * the number of rows of matrix A. We get the row count of A by
+ * looking at the size of a vector that makes up a column. The
+ * transpose (size of a row) is done for B.
+ */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ type_b->row_type()->vector_elements);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ } else if (type_a->is_matrix()) {
+ /* A is a matrix and B is a column vector. Columns of A must match
+ * rows of B. Given the other previously tested constraints, this
+ * means the vector type of a row from A must be the same as the
+ * vector the type of B.
+ */
+ if (type_a->row_type() == type_b) {
+ /* The resulting vector has a number of elements equal to
+ * the number of rows of matrix A. */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ 1);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ } else {
+ assert(type_b->is_matrix());
+
+ /* A is a row vector and B is a matrix. Columns of A must match rows
+ * of B. Given the other previously tested constraints, this means
+ * the type of A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a == type_b->column_type()) {
+ /* The resulting vector has a number of elements equal to
+ * the number of columns of matrix B. */
+ const glsl_type *const type =
+ glsl_type::get_instance(type_a->base_type,
+ type_b->row_type()->vector_elements,
+ 1);
+ assert(type != glsl_type::error_type);
+
+ return type;
+ }
+ }
+
+ _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
+ return glsl_type::error_type;
+ }
+
+
+ /* "All other cases are illegal."
+ */
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+unary_arithmetic_result_type(const struct glsl_type *type,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ /* From GLSL 1.50 spec, page 57:
+ *
+ * "The arithmetic unary operators negate (-), post- and pre-increment
+ * and decrement (-- and ++) operate on integer or floating-point
+ * values (including vectors and matrices). All unary operators work
+ * component-wise on their operands. These result with the same type
+ * they operated on."
+ */
+ if (!type->is_numeric()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to arithmetic operators must be numeric");
+ return glsl_type::error_type;
+ }
+
+ return type;
+}
+
+/**
+ * \brief Return the result type of a bit-logic operation.
+ *
+ * If the given types to the bit-logic operator are invalid, return
+ * glsl_type::error_type.
+ *
+ * \param type_a Type of LHS of bit-logic op
+ * \param type_b Type of RHS of bit-logic op
+ */
+static const struct glsl_type *
+bit_logic_result_type(const struct glsl_type *type_a,
+ const struct glsl_type *type_b,
+ ast_operators op,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ if (state->language_version < 130) {
+ _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
+ return glsl_type::error_type;
+ }
+
+ /* From page 50 (page 56 of PDF) of GLSL 1.30 spec:
+ *
+ * "The bitwise operators and (&), exclusive-or (^), and inclusive-or
+ * (|). The operands must be of type signed or unsigned integers or
+ * integer vectors."
+ */
+ if (!type_a->is_integer()) {
+ _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer",
+ ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+ if (!type_b->is_integer()) {
+ _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer",
+ ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "The fundamental types of the operands (signed or unsigned) must
+ * match,"
+ */
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state, "operands of `%s' must have the same "
+ "base type", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "The operands cannot be vectors of differing size." */
+ if (type_a->is_vector() &&
+ type_b->is_vector() &&
+ type_a->vector_elements != type_b->vector_elements) {
+ _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of "
+ "different sizes", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "If one operand is a scalar and the other a vector, the scalar is
+ * applied component-wise to the vector, resulting in the same type as
+ * the vector. The fundamental types of the operands [...] will be the
+ * resulting fundamental type."
+ */
+ if (type_a->is_scalar())
+ return type_b;
+ else
+ return type_a;
+}
+
+static const struct glsl_type *
+modulus_result_type(const struct glsl_type *type_a,
+ const struct glsl_type *type_b,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ /* From GLSL 1.50 spec, page 56:
+ * "The operator modulus (%) operates on signed or unsigned integers or
+ * integer vectors. The operand types must both be signed or both be
+ * unsigned."
+ */
+ if (!type_a->is_integer() || !type_b->is_integer()
+ || (type_a->base_type != type_b->base_type)) {
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+ }
+
+ /* "The operands cannot be vectors of differing size. If one operand is
+ * a scalar and the other vector, then the scalar is applied component-
+ * wise to the vector, resulting in the same type as the vector. If both
+ * are vectors of the same size, the result is computed component-wise."
+ */
+ if (type_a->is_vector()) {
+ if (!type_b->is_vector()
+ || (type_a->vector_elements == type_b->vector_elements))
+ return type_a;
+ } else
+ return type_b;
+
+ /* "The operator modulus (%) is not defined for any other data types
+ * (non-integer types)."
+ */
+ _mesa_glsl_error(loc, state, "type mismatch");
+ return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ const glsl_type *type_a = value_a->type;
+ const glsl_type *type_b = value_b->type;
+
+ /* From GLSL 1.50 spec, page 56:
+ * "The relational operators greater than (>), less than (<), greater
+ * than or equal (>=), and less than or equal (<=) operate only on
+ * scalar integer and scalar floating-point expressions."
+ */
+ if (!type_a->is_numeric()
+ || !type_b->is_numeric()
+ || !type_a->is_scalar()
+ || !type_b->is_scalar()) {
+ _mesa_glsl_error(loc, state,
+ "Operands to relational operators must be scalar and "
+ "numeric");
+ return glsl_type::error_type;
+ }
+
+ /* "Either the operands' types must match, or the conversions from
+ * Section 4.1.10 "Implicit Conversions" will be applied to the integer
+ * operand, after which the types must match."
+ */
+ if (!apply_implicit_conversion(type_a, value_b, state)
+ && !apply_implicit_conversion(type_b, value_a, state)) {
+ _mesa_glsl_error(loc, state,
+ "Could not implicitly convert operands to "
+ "relational operator");
+ return glsl_type::error_type;
+ }
+ type_a = value_a->type;
+ type_b = value_b->type;
+
+ if (type_a->base_type != type_b->base_type) {
+ _mesa_glsl_error(loc, state, "base type mismatch");
+ return glsl_type::error_type;
+ }
+
+ /* "The result is scalar Boolean."
+ */
+ return glsl_type::bool_type;
+}
+
+/**
+ * \brief Return the result type of a bit-shift operation.
+ *
+ * If the given types to the bit-shift operator are invalid, return
+ * glsl_type::error_type.
+ *
+ * \param type_a Type of LHS of bit-shift op
+ * \param type_b Type of RHS of bit-shift op
+ */
+static const struct glsl_type *
+shift_result_type(const struct glsl_type *type_a,
+ const struct glsl_type *type_b,
+ ast_operators op,
+ struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+ if (state->language_version < 130) {
+ _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30");
+ return glsl_type::error_type;
+ }
+
+ /* From page 50 (page 56 of the PDF) of the GLSL 1.30 spec:
+ *
+ * "The shift operators (<<) and (>>). For both operators, the operands
+ * must be signed or unsigned integers or integer vectors. One operand
+ * can be signed while the other is unsigned."
+ */
+ if (!type_a->is_integer()) {
+ _mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or "
+ "integer vector", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+
+ }
+ if (!type_b->is_integer()) {
+ _mesa_glsl_error(loc, state, "RHS of operator %s must be an integer or "
+ "integer vector", ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "If the first operand is a scalar, the second operand has to be
+ * a scalar as well."
+ */
+ if (type_a->is_scalar() && !type_b->is_scalar()) {
+ _mesa_glsl_error(loc, state, "If the first operand of %s is scalar, the "
+ "second must be scalar as well",
+ ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* If both operands are vectors, check that they have same number of
+ * elements.
+ */
+ if (type_a->is_vector() &&
+ type_b->is_vector() &&
+ type_a->vector_elements != type_b->vector_elements) {
+ _mesa_glsl_error(loc, state, "Vector operands to operator %s must "
+ "have same number of elements",
+ ast_expression::operator_string(op));
+ return glsl_type::error_type;
+ }
+
+ /* "In all cases, the resulting type will be the same type as the left
+ * operand."
+ */
+ return type_a;
+}
+
+/**
+ * Validates that a value can be assigned to a location with a specified type
+ *
+ * Validates that \c rhs can be assigned to some location. If the types are
+ * not an exact match but an automatic conversion is possible, \c rhs will be
+ * converted.
+ *
+ * \return
+ * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type.
+ * Otherwise the actual RHS to be assigned will be returned. This may be
+ * \c rhs, or it may be \c rhs after some type conversion.
+ *
+ * \note
+ * In addition to being used for assignments, this function is used to
+ * type-check return values.
+ */
+ir_rvalue *
+validate_assignment(struct _mesa_glsl_parse_state *state,
+ const glsl_type *lhs_type, ir_rvalue *rhs)
+{
+ /* If there is already some error in the RHS, just return it. Anything
+ * else will lead to an avalanche of error message back to the user.
+ */
+ if (rhs->type->is_error())
+ return rhs;
+
+ /* If the types are identical, the assignment can trivially proceed.
+ */
+ if (rhs->type == lhs_type)
+ return rhs;
+
+ /* If the array element types are the same and the size of the LHS is zero,
+ * the assignment is okay.
+ *
+ * Note: Whole-array assignments are not permitted in GLSL 1.10, but this
+ * is handled by ir_dereference::is_lvalue.
+ */
+ if (lhs_type->is_array() && rhs->type->is_array()
+ && (lhs_type->element_type() == rhs->type->element_type())
+ && (lhs_type->array_size() == 0)) {
+ return rhs;
+ }
+
+ /* Check for implicit conversion in GLSL 1.20 */
+ if (apply_implicit_conversion(lhs_type, rhs, state)) {
+ if (rhs->type == lhs_type)
+ return rhs;
+ }
+
+ return NULL;
+}
+
+ir_rvalue *
+do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
+ ir_rvalue *lhs, ir_rvalue *rhs,
+ YYLTYPE lhs_loc)
+{
+ void *ctx = state;
+ bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+
+ if (!error_emitted) {
+ if (lhs->variable_referenced() != NULL
+ && lhs->variable_referenced()->read_only) {
+ _mesa_glsl_error(&lhs_loc, state,
+ "assignment to read-only variable '%s'",
+ lhs->variable_referenced()->name);
+ error_emitted = true;
+
+ } else if (!lhs->is_lvalue()) {
+ _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
+ error_emitted = true;
+ }
+
+ if (state->es_shader && lhs->type->is_array()) {
+ _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not "
+ "allowed in GLSL ES 1.00.");
+ error_emitted = true;
+ }
+ }
+
+ ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs);
+ if (new_rhs == NULL) {
+ _mesa_glsl_error(& lhs_loc, state, "type mismatch");
+ } else {
+ rhs = new_rhs;
+
+ /* If the LHS array was not declared with a size, it takes it size from
+ * the RHS. If the LHS is an l-value and a whole array, it must be a
+ * dereference of a variable. Any other case would require that the LHS
+ * is either not an l-value or not a whole array.
+ */
+ if (lhs->type->array_size() == 0) {
+ ir_dereference *const d = lhs->as_dereference();
+
+ assert(d != NULL);
+
+ ir_variable *const var = d->variable_referenced();
+
+ assert(var != NULL);
+
+ if (var->max_array_access >= unsigned(rhs->type->array_size())) {
+ /* FINISHME: This should actually log the location of the RHS. */
+ _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
+ "previous access",
+ var->max_array_access);
+ }
+
+ var->type = glsl_type::get_array_instance(lhs->type->element_type(),
+ rhs->type->array_size());
+ d->type = var->type;
+ }
+ }
+
+ /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+ * but not post_inc) need the converted assigned value as an rvalue
+ * to handle things like:
+ *
+ * i = j += 1;
+ *
+ * So we always just store the computed value being assigned to a
+ * temporary and return a deref of that temporary. If the rvalue
+ * ends up not being used, the temp will get copy-propagated out.
+ */
+ ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+ ir_var_temporary);
+ ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
+ instructions->push_tail(var);
+ instructions->push_tail(new(ctx) ir_assignment(deref_var,
+ rhs,
+ NULL));
+ deref_var = new(ctx) ir_dereference_variable(var);
+
+ if (!error_emitted)
+ instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+static ir_rvalue *
+get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
+{
+ void *ctx = talloc_parent(lvalue);
+ ir_variable *var;
+
+ var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
+ ir_var_temporary);
+ instructions->push_tail(var);
+ var->mode = ir_var_auto;
+
+ instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+ lvalue, NULL));
+
+ /* Once we've created this temporary, mark it read only so it's no
+ * longer considered an lvalue.
+ */
+ var->read_only = true;
+
+ return new(ctx) ir_dereference_variable(var);
+}
+
+
+ir_rvalue *
+ast_node::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ (void) instructions;
+ (void) state;
+
+ return NULL;
+}
+
+static void
+mark_whole_array_access(ir_rvalue *access)
+{
+ ir_dereference_variable *deref = access->as_dereference_variable();
+
+ if (deref) {
+ deref->var->max_array_access = deref->type->length - 1;
+ }
+}
+
+static ir_rvalue *
+do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
+{
+ int join_op;
+ ir_rvalue *cmp = NULL;
+
+ if (operation == ir_binop_all_equal)
+ join_op = ir_binop_logic_and;
+ else
+ join_op = ir_binop_logic_or;
+
+ switch (op0->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_BOOL:
+ return new(mem_ctx) ir_expression(operation, op0, op1);
+
+ case GLSL_TYPE_ARRAY: {
+ for (unsigned int i = 0; i < op0->type->length; i++) {
+ ir_rvalue *e0, *e1, *result;
+
+ e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL),
+ new(mem_ctx) ir_constant(i));
+ e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL),
+ new(mem_ctx) ir_constant(i));
+ result = do_comparison(mem_ctx, operation, e0, e1);
+
+ if (cmp) {
+ cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
+ } else {
+ cmp = result;
+ }
+ }
+
+ mark_whole_array_access(op0);
+ mark_whole_array_access(op1);
+ break;
+ }
+
+ case GLSL_TYPE_STRUCT: {
+ for (unsigned int i = 0; i < op0->type->length; i++) {
+ ir_rvalue *e0, *e1, *result;
+ const char *field_name = op0->type->fields.structure[i].name;
+
+ e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL),
+ field_name);
+ e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL),
+ field_name);
+ result = do_comparison(mem_ctx, operation, e0, e1);
+
+ if (cmp) {
+ cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
+ } else {
+ cmp = result;
+ }
+ }
+ break;
+ }
+
+ case GLSL_TYPE_ERROR:
+ case GLSL_TYPE_VOID:
+ case GLSL_TYPE_SAMPLER:
+ /* I assume a comparison of a struct containing a sampler just
+ * ignores the sampler present in the type.
+ */
+ break;
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+
+ if (cmp == NULL)
+ cmp = new(mem_ctx) ir_constant(true);
+
+ return cmp;
+}
+
+ir_rvalue *
+ast_expression::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ static const int operations[AST_NUM_OPERATORS] = {
+ -1, /* ast_assign doesn't convert to ir_expression. */
+ -1, /* ast_plus doesn't convert to ir_expression. */
+ ir_unop_neg,
+ ir_binop_add,
+ ir_binop_sub,
+ ir_binop_mul,
+ ir_binop_div,
+ ir_binop_mod,
+ ir_binop_lshift,
+ ir_binop_rshift,
+ ir_binop_less,
+ ir_binop_greater,
+ ir_binop_lequal,
+ ir_binop_gequal,
+ ir_binop_all_equal,
+ ir_binop_any_nequal,
+ ir_binop_bit_and,
+ ir_binop_bit_xor,
+ ir_binop_bit_or,
+ ir_unop_bit_not,
+ ir_binop_logic_and,
+ ir_binop_logic_xor,
+ ir_binop_logic_or,
+ ir_unop_logic_not,
+
+ /* Note: The following block of expression types actually convert
+ * to multiple IR instructions.
+ */
+ ir_binop_mul, /* ast_mul_assign */
+ ir_binop_div, /* ast_div_assign */
+ ir_binop_mod, /* ast_mod_assign */
+ ir_binop_add, /* ast_add_assign */
+ ir_binop_sub, /* ast_sub_assign */
+ ir_binop_lshift, /* ast_ls_assign */
+ ir_binop_rshift, /* ast_rs_assign */
+ ir_binop_bit_and, /* ast_and_assign */
+ ir_binop_bit_xor, /* ast_xor_assign */
+ ir_binop_bit_or, /* ast_or_assign */
+
+ -1, /* ast_conditional doesn't convert to ir_expression. */
+ ir_binop_add, /* ast_pre_inc. */
+ ir_binop_sub, /* ast_pre_dec. */
+ ir_binop_add, /* ast_post_inc. */
+ ir_binop_sub, /* ast_post_dec. */
+ -1, /* ast_field_selection doesn't conv to ir_expression. */
+ -1, /* ast_array_index doesn't convert to ir_expression. */
+ -1, /* ast_function_call doesn't conv to ir_expression. */
+ -1, /* ast_identifier doesn't convert to ir_expression. */
+ -1, /* ast_int_constant doesn't convert to ir_expression. */
+ -1, /* ast_uint_constant doesn't conv to ir_expression. */
+ -1, /* ast_float_constant doesn't conv to ir_expression. */
+ -1, /* ast_bool_constant doesn't conv to ir_expression. */
+ -1, /* ast_sequence doesn't convert to ir_expression. */
+ };
+ ir_rvalue *result = NULL;
+ ir_rvalue *op[3];
+ const struct glsl_type *type = glsl_type::error_type;
+ bool error_emitted = false;
+ YYLTYPE loc;
+
+ loc = this->get_location();
+
+ switch (this->oper) {
+ case ast_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ result = do_assignment(instructions, state, op[0], op[1],
+ this->subexpressions[0]->get_location());
+ error_emitted = result->type->is_error();
+ type = result->type;
+ break;
+ }
+
+ case ast_plus:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+ error_emitted = type->is_error();
+
+ result = op[0];
+ break;
+
+ case ast_neg:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+ error_emitted = type->is_error();
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], NULL);
+ break;
+
+ case ast_add:
+ case ast_sub:
+ case ast_mul:
+ case ast_div:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = arithmetic_result_type(op[0], op[1],
+ (this->oper == ast_mul),
+ state, & loc);
+ error_emitted = type->is_error();
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ break;
+
+ case ast_mod:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+ assert(operations[this->oper] == ir_binop_mod);
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = type->is_error();
+ break;
+
+ case ast_lshift:
+ case ast_rshift:
+ if (state->language_version < 130) {
+ _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+ type = shift_result_type(op[0]->type, op[1]->type, this->oper, state,
+ &loc);
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+ break;
+
+ case ast_less:
+ case ast_greater:
+ case ast_lequal:
+ case ast_gequal:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = relational_result_type(op[0], op[1], state, & loc);
+
+ /* The relational operators must either generate an error or result
+ * in a scalar boolean. See page 57 of the GLSL 1.50 spec.
+ */
+ assert(type->is_error()
+ || ((type->base_type == GLSL_TYPE_BOOL)
+ && type->is_scalar()));
+
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = type->is_error();
+ break;
+
+ case ast_nequal:
+ case ast_equal:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The equality operators equal (==), and not equal (!=)
+ * operate on all types. They result in a scalar Boolean. If
+ * the operand types do not match, then there must be a
+ * conversion from Section 4.1.10 "Implicit Conversions"
+ * applied to one operand that can make them match, in which
+ * case this conversion is done."
+ */
+ if ((!apply_implicit_conversion(op[0]->type, op[1], state)
+ && !apply_implicit_conversion(op[1]->type, op[0], state))
+ || (op[0]->type != op[1]->type)) {
+ _mesa_glsl_error(& loc, state, "operands of `%s' must have the same "
+ "type", (this->oper == ast_equal) ? "==" : "!=");
+ error_emitted = true;
+ } else if ((state->language_version <= 110)
+ && (op[0]->type->is_array() || op[1]->type->is_array())) {
+ _mesa_glsl_error(& loc, state, "array comparisons forbidden in "
+ "GLSL 1.10");
+ error_emitted = true;
+ }
+
+ result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
+ type = glsl_type::bool_type;
+
+ assert(error_emitted || (result->type == glsl_type::bool_type));
+ break;
+
+ case ast_bit_and:
+ case ast_bit_xor:
+ case ast_bit_or:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+ type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper,
+ state, &loc);
+ result = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+ break;
+
+ case ast_bit_not:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (state->language_version < 130) {
+ _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
+ error_emitted = true;
+ }
+
+ if (!op[0]->type->is_integer()) {
+ _mesa_glsl_error(&loc, state, "operand of `~' must be an integer");
+ error_emitted = true;
+ }
+
+ type = op[0]->type;
+ result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL);
+ break;
+
+ case ast_logic_and: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_constant *op0_const = op[0]->constant_expression_value();
+ if (op0_const) {
+ if (op0_const->value.b[0]) {
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+ result = op[1];
+ } else {
+ result = op0_const;
+ }
+ type = glsl_type::bool_type;
+ } else {
+ ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+ "and_tmp",
+ ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, op[1], NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ type = tmp->type;
+ }
+ break;
+ }
+
+ case ast_logic_or: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_constant *op0_const = op[0]->constant_expression_value();
+ if (op0_const) {
+ if (op0_const->value.b[0]) {
+ result = op0_const;
+ } else {
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+ result = op[1];
+ }
+ type = glsl_type::bool_type;
+ } else {
+ ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+ "or_tmp",
+ ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
+
+ if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
+ operator_string(this->oper));
+ error_emitted = true;
+ }
+
+ ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, op[1], NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ type = tmp->type;
+ }
+ break;
+ }
+
+ case ast_logic_xor:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+
+ result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+ op[0], op[1]);
+ type = glsl_type::bool_type;
+ break;
+
+ case ast_logic_not:
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "operand of `!' must be scalar boolean");
+ error_emitted = true;
+ }
+
+ result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+ op[0], NULL);
+ type = glsl_type::bool_type;
+ break;
+
+ case ast_mul_assign:
+ case ast_div_assign:
+ case ast_add_assign:
+ case ast_sub_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = arithmetic_result_type(op[0], op[1],
+ (this->oper == ast_mul_assign),
+ state, & loc);
+
+ ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = (op[0]->type->is_error());
+
+ /* GLSL 1.10 does not allow array assignment. However, we don't have to
+ * explicitly test for this because none of the binary expression
+ * operators allow array operands either.
+ */
+
+ break;
+ }
+
+ case ast_mod_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+
+ type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+ assert(operations[this->oper] == ir_binop_mod);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = type->is_error();
+ break;
+ }
+
+ case ast_ls_assign:
+ case ast_rs_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+ type = shift_result_type(op[0]->type, op[1]->type, this->oper, state,
+ &loc);
+ ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
+ type, op[0], op[1]);
+ result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
+ temp_rhs,
+ this->subexpressions[0]->get_location());
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+ break;
+ }
+
+ case ast_and_assign:
+ case ast_xor_assign:
+ case ast_or_assign: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ op[1] = this->subexpressions[1]->hir(instructions, state);
+ type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper,
+ state, &loc);
+ ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper],
+ type, op[0], op[1]);
+ result = do_assignment(instructions, state, op[0]->clone(ctx, NULL),
+ temp_rhs,
+ this->subexpressions[0]->get_location());
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+ break;
+ }
+
+ case ast_conditional: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+
+ /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The ternary selection operator (?:). It operates on three
+ * expressions (exp1 ? exp2 : exp3). This operator evaluates the
+ * first expression, which must result in a scalar Boolean."
+ */
+ if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+ YYLTYPE loc = this->subexpressions[0]->get_location();
+
+ _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean");
+ error_emitted = true;
+ }
+
+ /* The :? operator is implemented by generating an anonymous temporary
+ * followed by an if-statement. The last instruction in each branch of
+ * the if-statement assigns a value to the anonymous temporary. This
+ * temporary is the r-value of the expression.
+ */
+ exec_list then_instructions;
+ exec_list else_instructions;
+
+ op[1] = this->subexpressions[1]->hir(&then_instructions, state);
+ op[2] = this->subexpressions[2]->hir(&else_instructions, state);
+
+ /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "The second and third expressions can be any type, as
+ * long their types match, or there is a conversion in
+ * Section 4.1.10 "Implicit Conversions" that can be applied
+ * to one of the expressions to make their types match. This
+ * resulting matching type is the type of the entire
+ * expression."
+ */
+ if ((!apply_implicit_conversion(op[1]->type, op[2], state)
+ && !apply_implicit_conversion(op[2]->type, op[1], state))
+ || (op[1]->type != op[2]->type)) {
+ YYLTYPE loc = this->subexpressions[1]->get_location();
+
+ _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
+ "operator must have matching types.");
+ error_emitted = true;
+ type = glsl_type::error_type;
+ } else {
+ type = op[1]->type;
+ }
+
+ /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "The second and third expressions must be the same type, but can
+ * be of any type other than an array."
+ */
+ if ((state->language_version <= 110) && type->is_array()) {
+ _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
+ "operator must not be arrays.");
+ error_emitted = true;
+ }
+
+ ir_constant *cond_val = op[0]->constant_expression_value();
+ ir_constant *then_val = op[1]->constant_expression_value();
+ ir_constant *else_val = op[2]->constant_expression_value();
+
+ if (then_instructions.is_empty()
+ && else_instructions.is_empty()
+ && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
+ result = (cond_val->value.b[0]) ? then_val : else_val;
+ } else {
+ ir_variable *const tmp =
+ new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
+ instructions->push_tail(tmp);
+
+ ir_if *const stmt = new(ctx) ir_if(op[0]);
+ instructions->push_tail(stmt);
+
+ then_instructions.move_nodes_to(& stmt->then_instructions);
+ ir_dereference *const then_deref =
+ new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new(ctx) ir_assignment(then_deref, op[1], NULL);
+ stmt->then_instructions.push_tail(then_assign);
+
+ else_instructions.move_nodes_to(& stmt->else_instructions);
+ ir_dereference *const else_deref =
+ new(ctx) ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new(ctx) ir_assignment(else_deref, op[2], NULL);
+ stmt->else_instructions.push_tail(else_assign);
+
+ result = new(ctx) ir_dereference_variable(tmp);
+ }
+ break;
+ }
+
+ case ast_pre_inc:
+ case ast_pre_dec: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+ op[1] = new(ctx) ir_constant(1.0f);
+ else
+ op[1] = new(ctx) ir_constant(1);
+
+ type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ result = do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+ type = result->type;
+ error_emitted = op[0]->type->is_error();
+ break;
+ }
+
+ case ast_post_inc:
+ case ast_post_dec: {
+ op[0] = this->subexpressions[0]->hir(instructions, state);
+ if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+ op[1] = new(ctx) ir_constant(1.0f);
+ else
+ op[1] = new(ctx) ir_constant(1);
+
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+ type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+ ir_rvalue *temp_rhs;
+ temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+ op[0], op[1]);
+
+ /* Get a temporary of a copy of the lvalue before it's modified.
+ * This may get thrown away later.
+ */
+ result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
+
+ (void)do_assignment(instructions, state,
+ op[0]->clone(ctx, NULL), temp_rhs,
+ this->subexpressions[0]->get_location());
+
+ type = result->type;
+ error_emitted = op[0]->type->is_error();
+ break;
+ }
+
+ case ast_field_selection:
+ result = _mesa_ast_field_selection_to_hir(this, instructions, state);
+ type = result->type;
+ break;
+
+ case ast_array_index: {
+ YYLTYPE index_loc = subexpressions[1]->get_location();
+
+ op[0] = subexpressions[0]->hir(instructions, state);
+ op[1] = subexpressions[1]->hir(instructions, state);
+
+ error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+ ir_rvalue *const array = op[0];
+
+ result = new(ctx) ir_dereference_array(op[0], op[1]);
+
+ /* Do not use op[0] after this point. Use array.
+ */
+ op[0] = NULL;
+
+
+ if (error_emitted)
+ break;
+
+ if (!array->type->is_array()
+ && !array->type->is_matrix()
+ && !array->type->is_vector()) {
+ _mesa_glsl_error(& index_loc, state,
+ "cannot dereference non-array / non-matrix / "
+ "non-vector");
+ error_emitted = true;
+ }
+
+ if (!op[1]->type->is_integer()) {
+ _mesa_glsl_error(& index_loc, state,
+ "array index must be integer type");
+ error_emitted = true;
+ } else if (!op[1]->type->is_scalar()) {
+ _mesa_glsl_error(& index_loc, state,
+ "array index must be scalar");
+ error_emitted = true;
+ }
+
+ /* If the array index is a constant expression and the array has a
+ * declared size, ensure that the access is in-bounds. If the array
+ * index is not a constant expression, ensure that the array has a
+ * declared size.
+ */
+ ir_constant *const const_index = op[1]->constant_expression_value();
+ if (const_index != NULL) {
+ const int idx = const_index->value.i[0];
+ const char *type_name;
+ unsigned bound = 0;
+
+ if (array->type->is_matrix()) {
+ type_name = "matrix";
+ } else if (array->type->is_vector()) {
+ type_name = "vector";
+ } else {
+ type_name = "array";
+ }
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "It is illegal to declare an array with a size, and then
+ * later (in the same shader) index the same array with an
+ * integral constant expression greater than or equal to the
+ * declared size. It is also illegal to index an array with a
+ * negative constant expression."
+ */
+ if (array->type->is_matrix()) {
+ if (array->type->row_type()->vector_elements <= idx) {
+ bound = array->type->row_type()->vector_elements;
+ }
+ } else if (array->type->is_vector()) {
+ if (array->type->vector_elements <= idx) {
+ bound = array->type->vector_elements;
+ }
+ } else {
+ if ((array->type->array_size() > 0)
+ && (array->type->array_size() <= idx)) {
+ bound = array->type->array_size();
+ }
+ }
+
+ if (bound > 0) {
+ _mesa_glsl_error(& loc, state, "%s index must be < %u",
+ type_name, bound);
+ error_emitted = true;
+ } else if (idx < 0) {
+ _mesa_glsl_error(& loc, state, "%s index must be >= 0",
+ type_name);
+ error_emitted = true;
+ }
+
+ if (array->type->is_array()) {
+ /* If the array is a variable dereference, it dereferences the
+ * whole array, by definition. Use this to get the variable.
+ *
+ * FINISHME: Should some methods for getting / setting / testing
+ * FINISHME: array access limits be added to ir_dereference?
+ */
+ ir_variable *const v = array->whole_variable_referenced();
+ if ((v != NULL) && (unsigned(idx) > v->max_array_access))
+ v->max_array_access = idx;
+ }
+ } else if (array->type->array_size() == 0) {
+ _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+ } else {
+ if (array->type->is_array()) {
+ /* whole_variable_referenced can return NULL if the array is a
+ * member of a structure. In this case it is safe to not update
+ * the max_array_access field because it is never used for fields
+ * of structures.
+ */
+ ir_variable *v = array->whole_variable_referenced();
+ if (v != NULL)
+ v->max_array_access = array->type->array_size();
+ }
+ }
+
+ /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
+ *
+ * "Samplers aggregated into arrays within a shader (using square
+ * brackets [ ]) can only be indexed with integral constant
+ * expressions [...]."
+ *
+ * This restriction was added in GLSL 1.30. Shaders using earlier version
+ * of the language should not be rejected by the compiler front-end for
+ * using this construct. This allows useful things such as using a loop
+ * counter as the index to an array of samplers. If the loop in unrolled,
+ * the code should compile correctly. Instead, emit a warning.
+ */
+ if (array->type->is_array() &&
+ array->type->element_type()->is_sampler() &&
+ const_index == NULL) {
+
+ if (state->language_version == 100) {
+ _mesa_glsl_warning(&loc, state,
+ "sampler arrays indexed with non-constant "
+ "expressions is optional in GLSL ES 1.00");
+ } else if (state->language_version < 130) {
+ _mesa_glsl_warning(&loc, state,
+ "sampler arrays indexed with non-constant "
+ "expressions is forbidden in GLSL 1.30 and "
+ "later");
+ } else {
+ _mesa_glsl_error(&loc, state,
+ "sampler arrays indexed with non-constant "
+ "expressions is forbidden in GLSL 1.30 and "
+ "later");
+ error_emitted = true;
+ }
+ }
+
+ if (error_emitted)
+ result->type = glsl_type::error_type;
+
+ type = result->type;
+ break;
+ }
+
+ case ast_function_call:
+ /* Should *NEVER* get here. ast_function_call should always be handled
+ * by ast_function_expression::hir.
+ */
+ assert(0);
+ break;
+
+ case ast_identifier: {
+ /* ast_identifier can appear several places in a full abstract syntax
+ * tree. This particular use must be at location specified in the grammar
+ * as 'variable_identifier'.
+ */
+ ir_variable *var =
+ state->symbols->get_variable(this->primary_expression.identifier);
+
+ result = new(ctx) ir_dereference_variable(var);
+
+ if (var != NULL) {
+ var->used = true;
+ type = result->type;
+ } else {
+ _mesa_glsl_error(& loc, state, "`%s' undeclared",
+ this->primary_expression.identifier);
+
+ error_emitted = true;
+ }
+ break;
+ }
+
+ case ast_int_constant:
+ type = glsl_type::int_type;
+ result = new(ctx) ir_constant(this->primary_expression.int_constant);
+ break;
+
+ case ast_uint_constant:
+ type = glsl_type::uint_type;
+ result = new(ctx) ir_constant(this->primary_expression.uint_constant);
+ break;
+
+ case ast_float_constant:
+ type = glsl_type::float_type;
+ result = new(ctx) ir_constant(this->primary_expression.float_constant);
+ break;
+
+ case ast_bool_constant:
+ type = glsl_type::bool_type;
+ result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
+ break;
+
+ case ast_sequence: {
+ /* It should not be possible to generate a sequence in the AST without
+ * any expressions in it.
+ */
+ assert(!this->expressions.is_empty());
+
+ /* The r-value of a sequence is the last expression in the sequence. If
+ * the other expressions in the sequence do not have side-effects (and
+ * therefore add instructions to the instruction list), they get dropped
+ * on the floor.
+ */
+ foreach_list_typed (ast_node, ast, link, &this->expressions)
+ result = ast->hir(instructions, state);
+
+ type = result->type;
+
+ /* Any errors should have already been emitted in the loop above.
+ */
+ error_emitted = true;
+ break;
+ }
+ }
+
+ if (type->is_error() && !error_emitted)
+ _mesa_glsl_error(& loc, state, "type mismatch");
+
+ return result;
+}
+
+
+ir_rvalue *
+ast_expression_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ /* It is possible to have expression statements that don't have an
+ * expression. This is the solitary semicolon:
+ *
+ * for (i = 0; i < 5; i++)
+ * ;
+ *
+ * In this case the expression will be NULL. Test for NULL and don't do
+ * anything in that case.
+ */
+ if (expression != NULL)
+ expression->hir(instructions, state);
+
+ /* Statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_compound_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (new_scope)
+ state->symbols->push_scope();
+
+ foreach_list_typed (ast_node, ast, link, &this->statements)
+ ast->hir(instructions, state);
+
+ if (new_scope)
+ state->symbols->pop_scope();
+
+ /* Compound statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+static const glsl_type *
+process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
+ struct _mesa_glsl_parse_state *state)
+{
+ unsigned length = 0;
+
+ /* FINISHME: Reject delcarations of multidimensional arrays. */
+
+ if (array_size != NULL) {
+ exec_list dummy_instructions;
+ ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
+ YYLTYPE loc = array_size->get_location();
+
+ /* FINISHME: Verify that the grammar forbids side-effects in array
+ * FINISHME: sizes. i.e., 'vec4 [x = 12] data'
+ */
+ assert(dummy_instructions.is_empty());
+
+ if (ir != NULL) {
+ if (!ir->type->is_integer()) {
+ _mesa_glsl_error(& loc, state, "array size must be integer type");
+ } else if (!ir->type->is_scalar()) {
+ _mesa_glsl_error(& loc, state, "array size must be scalar type");
+ } else {
+ ir_constant *const size = ir->constant_expression_value();
+
+ if (size == NULL) {
+ _mesa_glsl_error(& loc, state, "array size must be a "
+ "constant valued expression");
+ } else if (size->value.i[0] <= 0) {
+ _mesa_glsl_error(& loc, state, "array size must be > 0");
+ } else {
+ assert(size->type == ir->type);
+ length = size->value.u[0];
+ }
+ }
+ }
+ } else if (state->es_shader) {
+ /* Section 10.17 of the GLSL ES 1.00 specification states that unsized
+ * array declarations have been removed from the language.
+ */
+ _mesa_glsl_error(loc, state, "unsized array declarations are not "
+ "allowed in GLSL ES 1.00.");
+ }
+
+ return glsl_type::get_array_instance(base, length);
+}
+
+
+const glsl_type *
+ast_type_specifier::glsl_type(const char **name,
+ struct _mesa_glsl_parse_state *state) const
+{
+ const struct glsl_type *type;
+
+ type = state->symbols->get_type(this->type_name);
+ *name = this->type_name;
+
+ if (this->is_array) {
+ YYLTYPE loc = this->get_location();
+ type = process_array_type(&loc, type, this->array_size, state);
+ }
+
+ return type;
+}
+
+
+static void
+apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ if (qual->flags.q.invariant) {
+ if (var->used) {
+ _mesa_glsl_error(loc, state,
+ "variable `%s' may not be redeclared "
+ "`invariant' after being used",
+ var->name);
+ } else {
+ var->invariant = 1;
+ }
+ }
+
+ if (qual->flags.q.constant || qual->flags.q.attribute
+ || qual->flags.q.uniform
+ || (qual->flags.q.varying && (state->target == fragment_shader)))
+ var->read_only = 1;
+
+ if (qual->flags.q.centroid)
+ var->centroid = 1;
+
+ if (qual->flags.q.attribute && state->target != vertex_shader) {
+ var->type = glsl_type::error_type;
+ _mesa_glsl_error(loc, state,
+ "`attribute' variables may not be declared in the "
+ "%s shader",
+ _mesa_glsl_shader_target_name(state->target));
+ }
+
+ /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "The varying qualifier can be used only with the data types
+ * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
+ * these."
+ */
+ if (qual->flags.q.varying) {
+ const glsl_type *non_array_type;
+
+ if (var->type && var->type->is_array())
+ non_array_type = var->type->fields.array;
+ else
+ non_array_type = var->type;
+
+ if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
+ var->type = glsl_type::error_type;
+ _mesa_glsl_error(loc, state,
+ "varying variables must be of base type float");
+ }
+ }
+
+ /* If there is no qualifier that changes the mode of the variable, leave
+ * the setting alone.
+ */
+ if (qual->flags.q.in && qual->flags.q.out)
+ var->mode = ir_var_inout;
+ else if (qual->flags.q.attribute || qual->flags.q.in
+ || (qual->flags.q.varying && (state->target == fragment_shader)))
+ var->mode = ir_var_in;
+ else if (qual->flags.q.out
+ || (qual->flags.q.varying && (state->target == vertex_shader)))
+ var->mode = ir_var_out;
+ else if (qual->flags.q.uniform)
+ var->mode = ir_var_uniform;
+
+ if (state->all_invariant && (state->current_function == NULL)) {
+ switch (state->target) {
+ case vertex_shader:
+ if (var->mode == ir_var_out)
+ var->invariant = true;
+ break;
+ case geometry_shader:
+ if ((var->mode == ir_var_in) || (var->mode == ir_var_out))
+ var->invariant = true;
+ break;
+ case fragment_shader:
+ if (var->mode == ir_var_in)
+ var->invariant = true;
+ break;
+ }
+ }
+
+ if (qual->flags.q.flat)
+ var->interpolation = ir_var_flat;
+ else if (qual->flags.q.noperspective)
+ var->interpolation = ir_var_noperspective;
+ else
+ var->interpolation = ir_var_smooth;
+
+ var->pixel_center_integer = qual->flags.q.pixel_center_integer;
+ var->origin_upper_left = qual->flags.q.origin_upper_left;
+ if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
+ && (strcmp(var->name, "gl_FragCoord") != 0)) {
+ const char *const qual_string = (qual->flags.q.origin_upper_left)
+ ? "origin_upper_left" : "pixel_center_integer";
+
+ _mesa_glsl_error(loc, state,
+ "layout qualifier `%s' can only be applied to "
+ "fragment shader input `gl_FragCoord'",
+ qual_string);
+ }
+
+ if (qual->flags.q.explicit_location) {
+ const bool global_scope = (state->current_function == NULL);
+ bool fail = false;
+ const char *string = "";
+
+ /* In the vertex shader only shader inputs can be given explicit
+ * locations.
+ *
+ * In the fragment shader only shader outputs can be given explicit
+ * locations.
+ */
+ switch (state->target) {
+ case vertex_shader:
+ if (!global_scope || (var->mode != ir_var_in)) {
+ fail = true;
+ string = "input";
+ }
+ break;
+
+ case geometry_shader:
+ _mesa_glsl_error(loc, state,
+ "geometry shader variables cannot be given "
+ "explicit locations\n");
+ break;
+
+ case fragment_shader:
+ if (!global_scope || (var->mode != ir_var_in)) {
+ fail = true;
+ string = "output";
+ }
+ break;
+ };
+
+ if (fail) {
+ _mesa_glsl_error(loc, state,
+ "only %s shader %s variables can be given an "
+ "explicit location\n",
+ _mesa_glsl_shader_target_name(state->target),
+ string);
+ } else {
+ var->explicit_location = true;
+
+ /* This bit of silliness is needed because invalid explicit locations
+ * are supposed to be flagged during linking. Small negative values
+ * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
+ * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
+ * The linker needs to be able to differentiate these cases. This
+ * ensures that negative values stay negative.
+ */
+ if (qual->location >= 0) {
+ var->location = (state->target == vertex_shader)
+ ? (qual->location + VERT_ATTRIB_GENERIC0)
+ : (qual->location + FRAG_RESULT_DATA0);
+ } else {
+ var->location = qual->location;
+ }
+ }
+ }
+
+ /* Does the declaration use the 'layout' keyword?
+ */
+ const bool uses_layout = qual->flags.q.pixel_center_integer
+ || qual->flags.q.origin_upper_left
+ || qual->flags.q.explicit_location;
+
+ /* Does the declaration use the deprecated 'attribute' or 'varying'
+ * keywords?
+ */
+ const bool uses_deprecated_qualifier = qual->flags.q.attribute
+ || qual->flags.q.varying;
+
+ /* Is the 'layout' keyword used with parameters that allow relaxed checking.
+ * Many implementations of GL_ARB_fragment_coord_conventions_enable and some
+ * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
+ * allowed the layout qualifier to be used with 'varying' and 'attribute'.
+ * These extensions and all following extensions that add the 'layout'
+ * keyword have been modified to require the use of 'in' or 'out'.
+ *
+ * The following extension do not allow the deprecated keywords:
+ *
+ * GL_AMD_conservative_depth
+ * GL_ARB_gpu_shader5
+ * GL_ARB_separate_shader_objects
+ * GL_ARB_tesselation_shader
+ * GL_ARB_transform_feedback3
+ * GL_ARB_uniform_buffer_object
+ *
+ * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5
+ * allow layout with the deprecated keywords.
+ */
+ const bool relaxed_layout_qualifier_checking =
+ state->ARB_fragment_coord_conventions_enable;
+
+ if (uses_layout && uses_deprecated_qualifier) {
+ if (relaxed_layout_qualifier_checking) {
+ _mesa_glsl_warning(loc, state,
+ "`layout' qualifier may not be used with "
+ "`attribute' or `varying'");
+ } else {
+ _mesa_glsl_error(loc, state,
+ "`layout' qualifier may not be used with "
+ "`attribute' or `varying'");
+ }
+ }
+
+ /* Layout qualifiers for gl_FragDepth, which are enabled by extension
+ * AMD_conservative_depth.
+ */
+ int depth_layout_count = qual->flags.q.depth_any
+ + qual->flags.q.depth_greater
+ + qual->flags.q.depth_less
+ + qual->flags.q.depth_unchanged;
+ if (depth_layout_count > 0
+ && !state->AMD_conservative_depth_enable) {
+ _mesa_glsl_error(loc, state,
+ "extension GL_AMD_conservative_depth must be enabled "
+ "to use depth layout qualifiers");
+ } else if (depth_layout_count > 0
+ && strcmp(var->name, "gl_FragDepth") != 0) {
+ _mesa_glsl_error(loc, state,
+ "depth layout qualifiers can be applied only to "
+ "gl_FragDepth");
+ } else if (depth_layout_count > 1
+ && strcmp(var->name, "gl_FragDepth") == 0) {
+ _mesa_glsl_error(loc, state,
+ "at most one depth layout qualifier can be applied to "
+ "gl_FragDepth");
+ }
+ if (qual->flags.q.depth_any)
+ var->depth_layout = ir_depth_layout_any;
+ else if (qual->flags.q.depth_greater)
+ var->depth_layout = ir_depth_layout_greater;
+ else if (qual->flags.q.depth_less)
+ var->depth_layout = ir_depth_layout_less;
+ else if (qual->flags.q.depth_unchanged)
+ var->depth_layout = ir_depth_layout_unchanged;
+ else
+ var->depth_layout = ir_depth_layout_none;
+
+ if (var->type->is_array() && state->language_version != 110) {
+ var->array_lvalue = true;
+ }
+}
+
+
+ir_rvalue *
+ast_declarator_list::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ const struct glsl_type *decl_type;
+ const char *type_name = NULL;
+ ir_rvalue *result = NULL;
+ YYLTYPE loc = this->get_location();
+
+ /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "To ensure that a particular output variable is invariant, it is
+ * necessary to use the invariant qualifier. It can either be used to
+ * qualify a previously declared variable as being invariant
+ *
+ * invariant gl_Position; // make existing gl_Position be invariant"
+ *
+ * In these cases the parser will set the 'invariant' flag in the declarator
+ * list, and the type will be NULL.
+ */
+ if (this->invariant) {
+ assert(this->type == NULL);
+
+ if (state->current_function != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "All uses of `invariant' keyword must be at global "
+ "scope\n");
+ }
+
+ foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+ assert(!decl->is_array);
+ assert(decl->array_size == NULL);
+ assert(decl->initializer == NULL);
+
+ ir_variable *const earlier =
+ state->symbols->get_variable(decl->identifier);
+ if (earlier == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "Undeclared variable `%s' cannot be marked "
+ "invariant\n", decl->identifier);
+ } else if ((state->target == vertex_shader)
+ && (earlier->mode != ir_var_out)) {
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, vertex shader "
+ "outputs only\n", decl->identifier);
+ } else if ((state->target == fragment_shader)
+ && (earlier->mode != ir_var_in)) {
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, fragment shader "
+ "inputs only\n", decl->identifier);
+ } else if (earlier->used) {
+ _mesa_glsl_error(& loc, state,
+ "variable `%s' may not be redeclared "
+ "`invariant' after being used",
+ earlier->name);
+ } else {
+ earlier->invariant = true;
+ }
+ }
+
+ /* Invariant redeclarations do not have r-values.
+ */
+ return NULL;
+ }
+
+ assert(this->type != NULL);
+ assert(!this->invariant);
+
+ /* The type specifier may contain a structure definition. Process that
+ * before any of the variable declarations.
+ */
+ (void) this->type->specifier->hir(instructions, state);
+
+ decl_type = this->type->specifier->glsl_type(& type_name, state);
+ if (this->declarations.is_empty()) {
+ /* The only valid case where the declaration list can be empty is when
+ * the declaration is setting the default precision of a built-in type
+ * (e.g., 'precision highp vec4;').
+ */
+
+ if (decl_type != NULL) {
+ } else {
+ _mesa_glsl_error(& loc, state, "incomplete declaration");
+ }
+ }
+
+ foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+ const struct glsl_type *var_type;
+ ir_variable *var;
+
+ /* FINISHME: Emit a warning if a variable declaration shadows a
+ * FINISHME: declaration at a higher scope.
+ */
+
+ if ((decl_type == NULL) || decl_type->is_void()) {
+ if (type_name != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "invalid type `%s' in declaration of `%s'",
+ type_name, decl->identifier);
+ } else {
+ _mesa_glsl_error(& loc, state,
+ "invalid type in declaration of `%s'",
+ decl->identifier);
+ }
+ continue;
+ }
+
+ if (decl->is_array) {
+ var_type = process_array_type(&loc, decl_type, decl->array_size,
+ state);
+ } else {
+ var_type = decl_type;
+ }
+
+ var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
+
+ /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
+ *
+ * "Global variables can only use the qualifiers const,
+ * attribute, uni form, or varying. Only one may be
+ * specified.
+ *
+ * Local variables can only use the qualifier const."
+ *
+ * This is relaxed in GLSL 1.30. It is also relaxed by any extension
+ * that adds the 'layout' keyword.
+ */
+ if ((state->language_version < 130)
+ && !state->ARB_explicit_attrib_location_enable
+ && !state->ARB_fragment_coord_conventions_enable) {
+ if (this->type->qualifier.flags.q.out) {
+ _mesa_glsl_error(& loc, state,
+ "`out' qualifier in declaration of `%s' "
+ "only valid for function parameters in %s.",
+ decl->identifier, state->version_string);
+ }
+ if (this->type->qualifier.flags.q.in) {
+ _mesa_glsl_error(& loc, state,
+ "`in' qualifier in declaration of `%s' "
+ "only valid for function parameters in %s.",
+ decl->identifier, state->version_string);
+ }
+ /* FINISHME: Test for other invalid qualifiers. */
+ }
+
+ apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
+ & loc);
+
+ if (this->type->qualifier.flags.q.invariant) {
+ if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
+ var->mode == ir_var_inout)) {
+ /* FINISHME: Note that this doesn't work for invariant on
+ * a function signature outval
+ */
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, vertex shader "
+ "outputs only\n", var->name);
+ } else if ((state->target == fragment_shader) &&
+ !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+ /* FINISHME: Note that this doesn't work for invariant on
+ * a function signature inval
+ */
+ _mesa_glsl_error(& loc, state,
+ "`%s' cannot be marked invariant, fragment shader "
+ "inputs only\n", var->name);
+ }
+ }
+
+ if (state->current_function != NULL) {
+ const char *mode = NULL;
+ const char *extra = "";
+
+ /* There is no need to check for 'inout' here because the parser will
+ * only allow that in function parameter lists.
+ */
+ if (this->type->qualifier.flags.q.attribute) {
+ mode = "attribute";
+ } else if (this->type->qualifier.flags.q.uniform) {
+ mode = "uniform";
+ } else if (this->type->qualifier.flags.q.varying) {
+ mode = "varying";
+ } else if (this->type->qualifier.flags.q.in) {
+ mode = "in";
+ extra = " or in function parameter list";
+ } else if (this->type->qualifier.flags.q.out) {
+ mode = "out";
+ extra = " or in function parameter list";
+ }
+
+ if (mode) {
+ _mesa_glsl_error(& loc, state,
+ "%s variable `%s' must be declared at "
+ "global scope%s",
+ mode, var->name, extra);
+ }
+ } else if (var->mode == ir_var_in) {
+ var->read_only = true;
+
+ if (state->target == vertex_shader) {
+ bool error_emitted = false;
+
+ /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Vertex shader inputs can only be float, floating-point
+ * vectors, matrices, signed and unsigned integers and integer
+ * vectors. Vertex shader inputs can also form arrays of these
+ * types, but not structures."
+ *
+ * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec:
+ *
+ * "Vertex shader inputs can only be float, floating-point
+ * vectors, matrices, signed and unsigned integers and integer
+ * vectors. They cannot be arrays or structures."
+ *
+ * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "The attribute qualifier can be used only with float,
+ * floating-point vectors, and matrices. Attribute variables
+ * cannot be declared as arrays or structures."
+ */
+ const glsl_type *check_type = var->type->is_array()
+ ? var->type->fields.array : var->type;
+
+ switch (check_type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ break;
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ if (state->language_version > 120)
+ break;
+ /* FALLTHROUGH */
+ default:
+ _mesa_glsl_error(& loc, state,
+ "vertex shader input / attribute cannot have "
+ "type %s`%s'",
+ var->type->is_array() ? "array of " : "",
+ check_type->name);
+ error_emitted = true;
+ }
+
+ if (!error_emitted && (state->language_version <= 130)
+ && var->type->is_array()) {
+ _mesa_glsl_error(& loc, state,
+ "vertex shader input / attribute cannot have "
+ "array type");
+ error_emitted = true;
+ }
+ }
+ }
+
+ /* Integer vertex outputs must be qualified with 'flat'.
+ *
+ * From section 4.3.6 of the GLSL 1.30 spec:
+ * "If a vertex output is a signed or unsigned integer or integer
+ * vector, then it must be qualified with the interpolation qualifier
+ * flat."
+ */
+ if (state->language_version >= 130
+ && state->target == vertex_shader
+ && state->current_function == NULL
+ && var->type->is_integer()
+ && var->mode == ir_var_out
+ && var->interpolation != ir_var_flat) {
+
+ _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
+ "then it must be qualified with 'flat'");
+ }
+
+
+ /* Interpolation qualifiers cannot be applied to 'centroid' and
+ * 'centroid varying'.
+ *
+ * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
+ * "interpolation qualifiers may only precede the qualifiers in,
+ * centroid in, out, or centroid out in a declaration. They do not apply
+ * to the deprecated storage qualifiers varying or centroid varying."
+ */
+ if (state->language_version >= 130
+ && this->type->qualifier.has_interpolation()
+ && this->type->qualifier.flags.q.varying) {
+
+ const char *i = this->type->qualifier.interpolation_string();
+ assert(i != NULL);
+ const char *s;
+ if (this->type->qualifier.flags.q.centroid)
+ s = "centroid varying";
+ else
+ s = "varying";
+
+ _mesa_glsl_error(&loc, state,
+ "qualifier '%s' cannot be applied to the "
+ "deprecated storage qualifier '%s'", i, s);
+ }
+
+
+ /* Interpolation qualifiers can only apply to vertex shader outputs and
+ * fragment shader inputs.
+ *
+ * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
+ * "Outputs from a vertex shader (out) and inputs to a fragment
+ * shader (in) can be further qualified with one or more of these
+ * interpolation qualifiers"
+ */
+ if (state->language_version >= 130
+ && this->type->qualifier.has_interpolation()) {
+
+ const char *i = this->type->qualifier.interpolation_string();
+ assert(i != NULL);
+
+ switch (state->target) {
+ case vertex_shader:
+ if (this->type->qualifier.flags.q.in) {
+ _mesa_glsl_error(&loc, state,
+ "qualifier '%s' cannot be applied to vertex "
+ "shader inputs", i);
+ }
+ break;
+ case fragment_shader:
+ if (this->type->qualifier.flags.q.out) {
+ _mesa_glsl_error(&loc, state,
+ "qualifier '%s' cannot be applied to fragment "
+ "shader outputs", i);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+
+ /* From section 4.3.4 of the GLSL 1.30 spec:
+ * "It is an error to use centroid in in a vertex shader."
+ */
+ if (state->language_version >= 130
+ && this->type->qualifier.flags.q.centroid
+ && this->type->qualifier.flags.q.in
+ && state->target == vertex_shader) {
+
+ _mesa_glsl_error(&loc, state,
+ "'centroid in' cannot be used in a vertex shader");
+ }
+
+
+ /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
+ */
+ if (this->type->specifier->precision != ast_precision_none
+ && state->language_version != 100
+ && state->language_version < 130) {
+
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers are supported only in GLSL ES "
+ "1.00, and GLSL 1.30 and later");
+ }
+
+
+ /* Precision qualifiers only apply to floating point and integer types.
+ *
+ * From section 4.5.2 of the GLSL 1.30 spec:
+ * "Any floating point or any integer declaration can have the type
+ * preceded by one of these precision qualifiers [...] Literal
+ * constants do not have precision qualifiers. Neither do Boolean
+ * variables.
+ */
+ if (this->type->specifier->precision != ast_precision_none
+ && !var->type->is_float()
+ && !var->type->is_integer()
+ && !(var->type->is_array()
+ && (var->type->fields.array->is_float()
+ || var->type->fields.array->is_integer()))) {
+
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers apply only to floating point "
+ "and integer types");
+ }
+
+ /* Process the initializer and add its instructions to a temporary
+ * list. This list will be added to the instruction stream (below) after
+ * the declaration is added. This is done because in some cases (such as
+ * redeclarations) the declaration may not actually be added to the
+ * instruction stream.
+ */
+ exec_list initializer_instructions;
+ if (decl->initializer != NULL) {
+ YYLTYPE initializer_loc = decl->initializer->get_location();
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "All uniform variables are read-only and are initialized either
+ * directly by an application via API commands, or indirectly by
+ * OpenGL."
+ */
+ if ((state->language_version <= 110)
+ && (var->mode == ir_var_uniform)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize uniforms in GLSL 1.10");
+ }
+
+ if (var->type->is_sampler()) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize samplers");
+ }
+
+ if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize %s shader input / %s",
+ _mesa_glsl_shader_target_name(state->target),
+ (state->target == vertex_shader)
+ ? "attribute" : "varying");
+ }
+
+ ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
+ ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
+ state);
+
+ /* Calculate the constant value if this is a const or uniform
+ * declaration.
+ */
+ if (this->type->qualifier.flags.q.constant
+ || this->type->qualifier.flags.q.uniform) {
+ ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
+ if (new_rhs != NULL) {
+ rhs = new_rhs;
+
+ ir_constant *constant_value = rhs->constant_expression_value();
+ if (!constant_value) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "initializer of %s variable `%s' must be a "
+ "constant expression",
+ (this->type->qualifier.flags.q.constant)
+ ? "const" : "uniform",
+ decl->identifier);
+ if (var->type->is_numeric()) {
+ /* Reduce cascading errors. */
+ var->constant_value = ir_constant::zero(ctx, var->type);
+ }
+ } else {
+ rhs = constant_value;
+ var->constant_value = constant_value;
+ }
+ } else {
+ _mesa_glsl_error(&initializer_loc, state,
+ "initializer of type %s cannot be assigned to "
+ "variable of type %s",
+ rhs->type->name, var->type->name);
+ if (var->type->is_numeric()) {
+ /* Reduce cascading errors. */
+ var->constant_value = ir_constant::zero(ctx, var->type);
+ }
+ }
+ }
+
+ if (rhs && !rhs->type->is_error()) {
+ bool temp = var->read_only;
+ if (this->type->qualifier.flags.q.constant)
+ var->read_only = false;
+
+ /* Never emit code to initialize a uniform.
+ */
+ const glsl_type *initializer_type;
+ if (!this->type->qualifier.flags.q.uniform) {
+ result = do_assignment(&initializer_instructions, state,
+ lhs, rhs,
+ this->get_location());
+ initializer_type = result->type;
+ } else
+ initializer_type = rhs->type;
+
+ /* If the declared variable is an unsized array, it must inherrit
+ * its full type from the initializer. A declaration such as
+ *
+ * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
+ *
+ * becomes
+ *
+ * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
+ *
+ * The assignment generated in the if-statement (below) will also
+ * automatically handle this case for non-uniforms.
+ *
+ * If the declared variable is not an array, the types must
+ * already match exactly. As a result, the type assignment
+ * here can be done unconditionally. For non-uniforms the call
+ * to do_assignment can change the type of the initializer (via
+ * the implicit conversion rules). For uniforms the initializer
+ * must be a constant expression, and the type of that expression
+ * was validated above.
+ */
+ var->type = initializer_type;
+
+ var->read_only = temp;
+ }
+ }
+
+ /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "It is an error to write to a const variable outside of
+ * its declaration, so they must be initialized when
+ * declared."
+ */
+ if (this->type->qualifier.flags.q.constant && decl->initializer == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "const declaration of `%s' must be initialized",
+ decl->identifier);
+ }
+
+ /* Check if this declaration is actually a re-declaration, either to
+ * resize an array or add qualifiers to an existing variable.
+ *
+ * This is allowed for variables in the current scope, or when at
+ * global scope (for built-ins in the implicit outer scope).
+ */
+ ir_variable *earlier = state->symbols->get_variable(decl->identifier);
+ if (earlier != NULL && (state->current_function == NULL ||
+ state->symbols->name_declared_this_scope(decl->identifier))) {
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
+ *
+ * "It is legal to declare an array without a size and then
+ * later re-declare the same name as an array of the same
+ * type and specify a size."
+ */
+ if ((earlier->type->array_size() == 0)
+ && var->type->is_array()
+ && (var->type->element_type() == earlier->type->element_type())) {
+ /* FINISHME: This doesn't match the qualifiers on the two
+ * FINISHME: declarations. It's not 100% clear whether this is
+ * FINISHME: required or not.
+ */
+
+ /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "The size [of gl_TexCoord] can be at most
+ * gl_MaxTextureCoords."
+ */
+ const unsigned size = unsigned(var->type->array_size());
+ if ((strcmp("gl_TexCoord", var->name) == 0)
+ && (size > state->Const.MaxTextureCoords)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
+ "be larger than gl_MaxTextureCoords (%u)\n",
+ state->Const.MaxTextureCoords);
+ } else if ((size > 0) && (size <= earlier->max_array_access)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "array size must be > %u due to "
+ "previous access",
+ earlier->max_array_access);
+ }
+
+ earlier->type = var->type;
+ delete var;
+ var = NULL;
+ } else if (state->ARB_fragment_coord_conventions_enable
+ && strcmp(var->name, "gl_FragCoord") == 0
+ && earlier->type == var->type
+ && earlier->mode == var->mode) {
+ /* Allow redeclaration of gl_FragCoord for ARB_fcc layout
+ * qualifiers.
+ */
+ earlier->origin_upper_left = var->origin_upper_left;
+ earlier->pixel_center_integer = var->pixel_center_integer;
+
+ /* According to section 4.3.7 of the GLSL 1.30 spec,
+ * the following built-in varaibles can be redeclared with an
+ * interpolation qualifier:
+ * * gl_FrontColor
+ * * gl_BackColor
+ * * gl_FrontSecondaryColor
+ * * gl_BackSecondaryColor
+ * * gl_Color
+ * * gl_SecondaryColor
+ */
+ } else if (state->language_version >= 130
+ && (strcmp(var->name, "gl_FrontColor") == 0
+ || strcmp(var->name, "gl_BackColor") == 0
+ || strcmp(var->name, "gl_FrontSecondaryColor") == 0
+ || strcmp(var->name, "gl_BackSecondaryColor") == 0
+ || strcmp(var->name, "gl_Color") == 0
+ || strcmp(var->name, "gl_SecondaryColor") == 0)
+ && earlier->type == var->type
+ && earlier->mode == var->mode) {
+ earlier->interpolation = var->interpolation;
+
+ /* Layout qualifiers for gl_FragDepth. */
+ } else if (state->AMD_conservative_depth_enable
+ && strcmp(var->name, "gl_FragDepth") == 0
+ && earlier->type == var->type
+ && earlier->mode == var->mode) {
+
+ /** From the AMD_conservative_depth spec:
+ * Within any shader, the first redeclarations of gl_FragDepth
+ * must appear before any use of gl_FragDepth.
+ */
+ if (earlier->used) {
+ _mesa_glsl_error(&loc, state,
+ "the first redeclaration of gl_FragDepth "
+ "must appear before any use of gl_FragDepth");
+ }
+
+ /* Prevent inconsistent redeclaration of depth layout qualifier. */
+ if (earlier->depth_layout != ir_depth_layout_none
+ && earlier->depth_layout != var->depth_layout) {
+ _mesa_glsl_error(&loc, state,
+ "gl_FragDepth: depth layout is declared here "
+ "as '%s, but it was previously declared as "
+ "'%s'",
+ depth_layout_string(var->depth_layout),
+ depth_layout_string(earlier->depth_layout));
+ }
+
+ earlier->depth_layout = var->depth_layout;
+
+ } else {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
+ }
+
+ continue;
+ }
+
+ /* By now, we know it's a new variable declaration (we didn't hit the
+ * above "continue").
+ *
+ * From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+ *
+ * "Identifiers starting with "gl_" are reserved for use by
+ * OpenGL, and may not be declared in a shader as either a
+ * variable or a function."
+ */
+ if (strncmp(decl->identifier, "gl_", 3) == 0)
+ _mesa_glsl_error(& loc, state,
+ "identifier `%s' uses reserved `gl_' prefix",
+ decl->identifier);
+
+ /* Add the variable to the symbol table. Note that the initializer's
+ * IR was already processed earlier (though it hasn't been emitted yet),
+ * without the variable in scope.
+ *
+ * This differs from most C-like languages, but it follows the GLSL
+ * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50
+ * spec:
+ *
+ * "Within a declaration, the scope of a name starts immediately
+ * after the initializer if present or immediately after the name
+ * being declared if not."
+ */
+ if (!state->symbols->add_variable(var)) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
+ "current scope", decl->identifier);
+ continue;
+ }
+
+ /* Push the variable declaration to the top. It means that all
+ * the variable declarations will appear in a funny
+ * last-to-first order, but otherwise we run into trouble if a
+ * function is prototyped, a global var is decled, then the
+ * function is defined with usage of the global var. See
+ * glslparsertest's CorrectModule.frag.
+ */
+ instructions->push_head(var);
+ instructions->append_list(&initializer_instructions);
+ }
+
+
+ /* Generally, variable declarations do not have r-values. However,
+ * one is used for the declaration in
+ *
+ * while (bool b = some_condition()) {
+ * ...
+ * }
+ *
+ * so we return the rvalue from the last seen declaration here.
+ */
+ return result;
+}
+
+
+ir_rvalue *
+ast_parameter_declarator::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ const struct glsl_type *type;
+ const char *name = NULL;
+ YYLTYPE loc = this->get_location();
+
+ type = this->type->specifier->glsl_type(& name, state);
+
+ if (type == NULL) {
+ if (name != NULL) {
+ _mesa_glsl_error(& loc, state,
+ "invalid type `%s' in declaration of `%s'",
+ name, this->identifier);
+ } else {
+ _mesa_glsl_error(& loc, state,
+ "invalid type in declaration of `%s'",
+ this->identifier);
+ }
+
+ type = glsl_type::error_type;
+ }
+
+ /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Functions that accept no input arguments need not use void in the
+ * argument list because prototypes (or definitions) are required and
+ * therefore there is no ambiguity when an empty argument list "( )" is
+ * declared. The idiom "(void)" as a parameter list is provided for
+ * convenience."
+ *
+ * Placing this check here prevents a void parameter being set up
+ * for a function, which avoids tripping up checks for main taking
+ * parameters and lookups of an unnamed symbol.
+ */
+ if (type->is_void()) {
+ if (this->identifier != NULL)
+ _mesa_glsl_error(& loc, state,
+ "named parameter cannot have type `void'");
+
+ is_void = true;
+ return NULL;
+ }
+
+ if (formal_parameter && (this->identifier == NULL)) {
+ _mesa_glsl_error(& loc, state, "formal parameter lacks a name");
+ return NULL;
+ }
+
+ /* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...)
+ * call already handled the "vec4[..] foo" case.
+ */
+ if (this->is_array) {
+ type = process_array_type(&loc, type, this->array_size, state);
+ }
+
+ if (type->array_size() == 0) {
+ _mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
+ "a declared size.");
+ type = glsl_type::error_type;
+ }
+
+ is_void = false;
+ ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
+
+ /* Apply any specified qualifiers to the parameter declaration. Note that
+ * for function parameters the default mode is 'in'.
+ */
+ apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
+
+ instructions->push_tail(var);
+
+ /* Parameter declarations do not have r-values.
+ */
+ return NULL;
+}
+
+
+void
+ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
+ bool formal,
+ exec_list *ir_parameters,
+ _mesa_glsl_parse_state *state)
+{
+ ast_parameter_declarator *void_param = NULL;
+ unsigned count = 0;
+
+ foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) {
+ param->formal_parameter = formal;
+ param->hir(ir_parameters, state);
+
+ if (param->is_void)
+ void_param = param;
+
+ count++;
+ }
+
+ if ((void_param != NULL) && (count > 1)) {
+ YYLTYPE loc = void_param->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`void' parameter must be only parameter");
+ }
+}
+
+
+void
+emit_function(_mesa_glsl_parse_state *state, exec_list *instructions,
+ ir_function *f)
+{
+ /* Emit the new function header */
+ if (state->current_function == NULL) {
+ instructions->push_tail(f);
+ } else {
+ /* IR invariants disallow function declarations or definitions nested
+ * within other function definitions. Insert the new ir_function
+ * block in the instruction sequence before the ir_function block
+ * containing the current ir_function_signature.
+ */
+ ir_function *const curr =
+ const_cast<ir_function *>(state->current_function->function());
+
+ curr->insert_before(f);
+ }
+}
+
+
+ir_rvalue *
+ast_function::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ ir_function *f = NULL;
+ ir_function_signature *sig = NULL;
+ exec_list hir_parameters;
+
+ const char *const name = identifier;
+
+ /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec,
+ *
+ * "Function declarations (prototypes) cannot occur inside of functions;
+ * they must be at global scope, or for the built-in functions, outside
+ * the global scope."
+ *
+ * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec,
+ *
+ * "User defined functions may only be defined within the global scope."
+ *
+ * Note that this language does not appear in GLSL 1.10.
+ */
+ if ((state->current_function != NULL) && (state->language_version != 110)) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state,
+ "declaration of function `%s' not allowed within "
+ "function body", name);
+ }
+
+ /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+ *
+ * "Identifiers starting with "gl_" are reserved for use by
+ * OpenGL, and may not be declared in a shader as either a
+ * variable or a function."
+ */
+ if (strncmp(name, "gl_", 3) == 0) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state,
+ "identifier `%s' uses reserved `gl_' prefix", name);
+ }
+
+ /* Convert the list of function parameters to HIR now so that they can be
+ * used below to compare this function's signature with previously seen
+ * signatures for functions with the same name.
+ */
+ ast_parameter_declarator::parameters_to_hir(& this->parameters,
+ is_definition,
+ & hir_parameters, state);
+
+ const char *return_type_name;
+ const glsl_type *return_type =
+ this->return_type->specifier->glsl_type(& return_type_name, state);
+
+ if (!return_type) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state,
+ "function `%s' has undeclared return type `%s'",
+ name, return_type_name);
+ return_type = glsl_type::error_type;
+ }
+
+ /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec:
+ * "No qualifier is allowed on the return type of a function."
+ */
+ if (this->return_type->has_qualifiers()) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state,
+ "function `%s' return type has qualifiers", name);
+ }
+
+ /* Verify that this function's signature either doesn't match a previously
+ * seen signature for a function with the same name, or, if a match is found,
+ * that the previously seen signature does not have an associated definition.
+ */
+ f = state->symbols->get_function(name);
+ if (f != NULL && (state->es_shader || f->has_user_signature())) {
+ sig = f->exact_matching_signature(&hir_parameters);
+ if (sig != NULL) {
+ const char *badvar = sig->qualifiers_match(&hir_parameters);
+ if (badvar != NULL) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
+ "qualifiers don't match prototype", name, badvar);
+ }
+
+ if (sig->return_type != return_type) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
+ "match prototype", name);
+ }
+
+ if (is_definition && sig->is_defined) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+ }
+ }
+ } else {
+ f = new(ctx) ir_function(name);
+ if (!state->symbols->add_function(f)) {
+ /* This function name shadows a non-function use of the same name. */
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
+ "non-function", name);
+ return NULL;
+ }
+
+ emit_function(state, instructions, f);
+ }
+
+ /* Verify the return type of main() */
+ if (strcmp(name, "main") == 0) {
+ if (! return_type->is_void()) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "main() must return void");
+ }
+
+ if (!hir_parameters.is_empty()) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "main() must not take any parameters");
+ }
+ }
+
+ /* Finish storing the information about this new function in its signature.
+ */
+ if (sig == NULL) {
+ sig = new(ctx) ir_function_signature(return_type);
+ f->add_signature(sig);
+ }
+
+ sig->replace_parameters(&hir_parameters);
+ signature = sig;
+
+ /* Function declarations (prototypes) do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_function_definition::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ prototype->is_definition = true;
+ prototype->hir(instructions, state);
+
+ ir_function_signature *signature = prototype->signature;
+ if (signature == NULL)
+ return NULL;
+
+ assert(state->current_function == NULL);
+ state->current_function = signature;
+ state->found_return = false;
+
+ /* Duplicate parameters declared in the prototype as concrete variables.
+ * Add these to the symbol table.
+ */
+ state->symbols->push_scope();
+ foreach_iter(exec_list_iterator, iter, signature->parameters) {
+ ir_variable *const var = ((ir_instruction *) iter.get())->as_variable();
+
+ assert(var != NULL);
+
+ /* The only way a parameter would "exist" is if two parameters have
+ * the same name.
+ */
+ if (state->symbols->name_declared_this_scope(var->name)) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name);
+ } else {
+ state->symbols->add_variable(var);
+ }
+ }
+
+ /* Convert the body of the function to HIR. */
+ this->body->hir(&signature->body, state);
+ signature->is_defined = true;
+
+ state->symbols->pop_scope();
+
+ assert(state->current_function == signature);
+ state->current_function = NULL;
+
+ if (!signature->return_type->is_void() && !state->found_return) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(& loc, state, "function `%s' has non-void return type "
+ "%s, but no return statement",
+ signature->function_name(),
+ signature->return_type->name);
+ }
+
+ /* Function definitions do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_jump_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ switch (mode) {
+ case ast_return: {
+ ir_return *inst;
+ assert(state->current_function);
+
+ if (opt_return_value) {
+ ir_rvalue *const ret = opt_return_value->hir(instructions, state);
+
+ /* The value of the return type can be NULL if the shader says
+ * 'return foo();' and foo() is a function that returns void.
+ *
+ * NOTE: The GLSL spec doesn't say that this is an error. The type
+ * of the return value is void. If the return type of the function is
+ * also void, then this should compile without error. Seriously.
+ */
+ const glsl_type *const ret_type =
+ (ret == NULL) ? glsl_type::void_type : ret->type;
+
+ /* Implicit conversions are not allowed for return values. */
+ if (state->current_function->return_type != ret_type) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`return' with wrong type %s, in function `%s' "
+ "returning %s",
+ ret_type->name,
+ state->current_function->function_name(),
+ state->current_function->return_type->name);
+ }
+
+ inst = new(ctx) ir_return(ret);
+ } else {
+ if (state->current_function->return_type->base_type !=
+ GLSL_TYPE_VOID) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`return' with no value, in function %s returning "
+ "non-void",
+ state->current_function->function_name());
+ }
+ inst = new(ctx) ir_return;
+ }
+
+ state->found_return = true;
+ instructions->push_tail(inst);
+ break;
+ }
+
+ case ast_discard:
+ if (state->target != fragment_shader) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`discard' may only appear in a fragment shader");
+ }
+ instructions->push_tail(new(ctx) ir_discard);
+ break;
+
+ case ast_break:
+ case ast_continue:
+ /* FINISHME: Handle switch-statements. They cannot contain 'continue',
+ * FINISHME: and they use a different IR instruction for 'break'.
+ */
+ /* FINISHME: Correctly handle the nesting. If a switch-statement is
+ * FINISHME: inside a loop, a 'continue' is valid and will bind to the
+ * FINISHME: loop.
+ */
+ if (state->loop_or_switch_nesting == NULL) {
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "`%s' may only appear in a loop",
+ (mode == ast_break) ? "break" : "continue");
+ } else {
+ ir_loop *const loop = state->loop_or_switch_nesting->as_loop();
+
+ /* Inline the for loop expression again, since we don't know
+ * where near the end of the loop body the normal copy of it
+ * is going to be placed.
+ */
+ if (mode == ast_continue &&
+ state->loop_or_switch_nesting_ast->rest_expression) {
+ state->loop_or_switch_nesting_ast->rest_expression->hir(instructions,
+ state);
+ }
+
+ if (loop != NULL) {
+ ir_loop_jump *const jump =
+ new(ctx) ir_loop_jump((mode == ast_break)
+ ? ir_loop_jump::jump_break
+ : ir_loop_jump::jump_continue);
+ instructions->push_tail(jump);
+ }
+ }
+
+ break;
+ }
+
+ /* Jump instructions do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_selection_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ ir_rvalue *const condition = this->condition->hir(instructions, state);
+
+ /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Any expression whose type evaluates to a Boolean can be used as the
+ * conditional expression bool-expression. Vector types are not accepted
+ * as the expression to if."
+ *
+ * The checks are separated so that higher quality diagnostics can be
+ * generated for cases where both rules are violated.
+ */
+ if (!condition->type->is_boolean() || !condition->type->is_scalar()) {
+ YYLTYPE loc = this->condition->get_location();
+
+ _mesa_glsl_error(& loc, state, "if-statement condition must be scalar "
+ "boolean");
+ }
+
+ ir_if *const stmt = new(ctx) ir_if(condition);
+
+ if (then_statement != NULL) {
+ state->symbols->push_scope();
+ then_statement->hir(& stmt->then_instructions, state);
+ state->symbols->pop_scope();
+ }
+
+ if (else_statement != NULL) {
+ state->symbols->push_scope();
+ else_statement->hir(& stmt->else_instructions, state);
+ state->symbols->pop_scope();
+ }
+
+ instructions->push_tail(stmt);
+
+ /* if-statements do not have r-values.
+ */
+ return NULL;
+}
+
+
+void
+ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ if (condition != NULL) {
+ ir_rvalue *const cond =
+ condition->hir(& stmt->body_instructions, state);
+
+ if ((cond == NULL)
+ || !cond->type->is_boolean() || !cond->type->is_scalar()) {
+ YYLTYPE loc = condition->get_location();
+
+ _mesa_glsl_error(& loc, state,
+ "loop condition must be scalar boolean");
+ } else {
+ /* As the first code in the loop body, generate a block that looks
+ * like 'if (!condition) break;' as the loop termination condition.
+ */
+ ir_rvalue *const not_cond =
+ new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
+ NULL);
+
+ ir_if *const if_stmt = new(ctx) ir_if(not_cond);
+
+ ir_jump *const break_stmt =
+ new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(break_stmt);
+ stmt->body_instructions.push_tail(if_stmt);
+ }
+ }
+}
+
+
+ir_rvalue *
+ast_iteration_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+
+ /* For-loops and while-loops start a new scope, but do-while loops do not.
+ */
+ if (mode != ast_do_while)
+ state->symbols->push_scope();
+
+ if (init_statement != NULL)
+ init_statement->hir(instructions, state);
+
+ ir_loop *const stmt = new(ctx) ir_loop();
+ instructions->push_tail(stmt);
+
+ /* Track the current loop and / or switch-statement nesting.
+ */
+ ir_instruction *const nesting = state->loop_or_switch_nesting;
+ ast_iteration_statement *nesting_ast = state->loop_or_switch_nesting_ast;
+
+ state->loop_or_switch_nesting = stmt;
+ state->loop_or_switch_nesting_ast = this;
+
+ if (mode != ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (body != NULL)
+ body->hir(& stmt->body_instructions, state);
+
+ if (rest_expression != NULL)
+ rest_expression->hir(& stmt->body_instructions, state);
+
+ if (mode == ast_do_while)
+ condition_to_hir(stmt, state);
+
+ if (mode != ast_do_while)
+ state->symbols->pop_scope();
+
+ /* Restore previous nesting before returning.
+ */
+ state->loop_or_switch_nesting = nesting;
+ state->loop_or_switch_nesting_ast = nesting_ast;
+
+ /* Loops do not have r-values.
+ */
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_type_specifier::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ if (!this->is_precision_statement && this->structure == NULL)
+ return NULL;
+
+ YYLTYPE loc = this->get_location();
+
+ if (this->precision != ast_precision_none
+ && state->language_version != 100
+ && state->language_version < 130) {
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers exist only in "
+ "GLSL ES 1.00, and GLSL 1.30 and later");
+ return NULL;
+ }
+ if (this->precision != ast_precision_none
+ && this->structure != NULL) {
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers do not apply to structures");
+ return NULL;
+ }
+
+ /* If this is a precision statement, check that the type to which it is
+ * applied is either float or int.
+ *
+ * From section 4.5.3 of the GLSL 1.30 spec:
+ * "The precision statement
+ * precision precision-qualifier type;
+ * can be used to establish a default precision qualifier. The type
+ * field can be either int or float [...]. Any other types or
+ * qualifiers will result in an error.
+ */
+ if (this->is_precision_statement) {
+ assert(this->precision != ast_precision_none);
+ assert(this->structure == NULL); /* The check for structures was
+ * performed above. */
+ if (this->is_array) {
+ _mesa_glsl_error(&loc, state,
+ "default precision statements do not apply to "
+ "arrays");
+ return NULL;
+ }
+ if (this->type_specifier != ast_float
+ && this->type_specifier != ast_int) {
+ _mesa_glsl_error(&loc, state,
+ "default precision statements apply only to types "
+ "float and int");
+ return NULL;
+ }
+
+ /* FINISHME: Translate precision statements into IR. */
+ return NULL;
+ }
+
+ if (this->structure != NULL)
+ return this->structure->hir(instructions, state);
+
+ return NULL;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ unsigned decl_count = 0;
+
+ /* Make an initial pass over the list of structure fields to determine how
+ * many there are. Each element in this list is an ast_declarator_list.
+ * This means that we actually need to count the number of elements in the
+ * 'declarations' list in each of the elements.
+ */
+ foreach_list_typed (ast_declarator_list, decl_list, link,
+ &this->declarations) {
+ foreach_list_const (decl_ptr, & decl_list->declarations) {
+ decl_count++;
+ }
+ }
+
+ /* Allocate storage for the structure fields and process the field
+ * declarations. As the declarations are processed, try to also convert
+ * the types to HIR. This ensures that structure definitions embedded in
+ * other structure definitions are processed.
+ */
+ glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
+ decl_count);
+
+ unsigned i = 0;
+ foreach_list_typed (ast_declarator_list, decl_list, link,
+ &this->declarations) {
+ const char *type_name;
+
+ decl_list->type->specifier->hir(instructions, state);
+
+ /* Section 10.9 of the GLSL ES 1.00 specification states that
+ * embedded structure definitions have been removed from the language.
+ */
+ if (state->es_shader && decl_list->type->specifier->structure != NULL) {
+ YYLTYPE loc = this->get_location();
+ _mesa_glsl_error(&loc, state, "Embedded structure definitions are "
+ "not allowed in GLSL ES 1.00.");
+ }
+
+ const glsl_type *decl_type =
+ decl_list->type->specifier->glsl_type(& type_name, state);
+
+ foreach_list_typed (ast_declaration, decl, link,
+ &decl_list->declarations) {
+ const struct glsl_type *field_type = decl_type;
+ if (decl->is_array) {
+ YYLTYPE loc = decl->get_location();
+ field_type = process_array_type(&loc, decl_type, decl->array_size,
+ state);
+ }
+ fields[i].type = (field_type != NULL)
+ ? field_type : glsl_type::error_type;
+ fields[i].name = decl->identifier;
+ i++;
+ }
+ }
+
+ assert(i == decl_count);
+
+ const glsl_type *t =
+ glsl_type::get_record_instance(fields, decl_count, this->name);
+
+ YYLTYPE loc = this->get_location();
+ if (!state->symbols->add_type(name, t)) {
+ _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
+ } else {
+
+ const glsl_type **s = (const glsl_type **)
+ realloc(state->user_structures,
+ sizeof(state->user_structures[0]) *
+ (state->num_user_structures + 1));
+ if (s != NULL) {
+ s[state->num_user_structures] = t;
+ state->user_structures = s;
+ state->num_user_structures++;
+ }
+ }
+
+ /* Structure type definitions do not have r-values.
+ */
+ return NULL;
+}
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.c b/mesalib/src/glsl/glcpp/glcpp-parse.c
index 04e75dd6f..8567bda1e 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.c
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.c
@@ -1,4214 +1,4216 @@
-/* A Bison parser, made by GNU Bison 2.4.3. */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2009, 2010 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.4.3"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 1
-
-/* Push parsers. */
-#define YYPUSH 0
-
-/* Pull parsers. */
-#define YYPULL 1
-
-/* Using locations. */
-#define YYLSP_NEEDED 1
-
-
-
-/* Copy the first part of user declarations. */
-
-/* Line 189 of yacc.c */
-#line 1 "glcpp/glcpp-parse.y"
-
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#include "glcpp.h"
-#include "main/core.h" /* for struct gl_extensions */
-#include "main/mtypes.h" /* for gl_api enum */
-
-#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
-#define glcpp_printf(stream, fmt, args, ...) \
- stream = talloc_asprintf_append(stream, fmt, args)
-
-static void
-yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
-
-static void
-_define_object_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *macro,
- token_list_t *replacements);
-
-static void
-_define_function_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *macro,
- string_list_t *parameters,
- token_list_t *replacements);
-
-static string_list_t *
-_string_list_create (void *ctx);
-
-static void
-_string_list_append_item (string_list_t *list, const char *str);
-
-static int
-_string_list_contains (string_list_t *list, const char *member, int *index);
-
-static int
-_string_list_length (string_list_t *list);
-
-static int
-_string_list_equal (string_list_t *a, string_list_t *b);
-
-static argument_list_t *
-_argument_list_create (void *ctx);
-
-static void
-_argument_list_append (argument_list_t *list, token_list_t *argument);
-
-static int
-_argument_list_length (argument_list_t *list);
-
-static token_list_t *
-_argument_list_member_at (argument_list_t *list, int index);
-
-/* Note: This function talloc_steal()s the str pointer. */
-static token_t *
-_token_create_str (void *ctx, int type, char *str);
-
-static token_t *
-_token_create_ival (void *ctx, int type, int ival);
-
-static token_list_t *
-_token_list_create (void *ctx);
-
-/* Note: This function calls talloc_steal on token. */
-static void
-_token_list_append (token_list_t *list, token_t *token);
-
-static void
-_token_list_append_list (token_list_t *list, token_list_t *tail);
-
-static int
-_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
-
-static active_list_t *
-_active_list_push (active_list_t *list,
- const char *identifier,
- token_node_t *marker);
-
-static active_list_t *
-_active_list_pop (active_list_t *list);
-
-int
-_active_list_contains (active_list_t *list, const char *identifier);
-
-static void
-_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
-
-static void
-_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list);
-
-static void
-_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
- token_list_t *list);
-
-static void
-_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
- int condition);
-
-static void
-_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *type, int condition);
-
-static void
-_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
-
-#define yylex glcpp_parser_lex
-
-static int
-glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
-
-static void
-glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
-
-static void
-add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
-
-
-
-/* Line 189 of yacc.c */
-#line 220 "glcpp/glcpp-parse.c"
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- COMMA_FINAL = 258,
- DEFINED = 259,
- ELIF_EXPANDED = 260,
- HASH = 261,
- HASH_DEFINE_FUNC = 262,
- HASH_DEFINE_OBJ = 263,
- HASH_ELIF = 264,
- HASH_ELSE = 265,
- HASH_ENDIF = 266,
- HASH_IF = 267,
- HASH_IFDEF = 268,
- HASH_IFNDEF = 269,
- HASH_UNDEF = 270,
- HASH_VERSION = 271,
- IDENTIFIER = 272,
- IF_EXPANDED = 273,
- INTEGER = 274,
- INTEGER_STRING = 275,
- NEWLINE = 276,
- OTHER = 277,
- PLACEHOLDER = 278,
- SPACE = 279,
- PASTE = 280,
- OR = 281,
- AND = 282,
- NOT_EQUAL = 283,
- EQUAL = 284,
- GREATER_OR_EQUAL = 285,
- LESS_OR_EQUAL = 286,
- RIGHT_SHIFT = 287,
- LEFT_SHIFT = 288,
- UNARY = 289
- };
-#endif
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 264 of yacc.c */
-#line 308 "glcpp/glcpp-parse.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
- int yyi;
-#endif
-{
- return yyi;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
- && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss_alloc;
- YYSTYPE yyvs_alloc;
- YYLTYPE yyls_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
- + 2 * YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 2
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 606
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 57
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 17
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 101
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 162
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 289
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 47, 2, 2, 2, 43, 30, 2,
- 45, 46, 41, 39, 49, 40, 54, 42, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 55,
- 33, 56, 34, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 50, 2, 51, 29, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 52, 28, 53, 48, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 31, 32, 35, 36, 37, 38, 44
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint16 yyprhs[] =
-{
- 0, 0, 3, 4, 7, 9, 11, 13, 16, 20,
- 24, 29, 36, 44, 48, 52, 55, 60, 65, 69,
- 72, 75, 78, 82, 85, 87, 89, 91, 95, 99,
- 103, 107, 111, 115, 119, 123, 127, 131, 135, 139,
- 143, 147, 151, 155, 159, 163, 166, 169, 172, 175,
- 179, 181, 185, 187, 190, 193, 194, 196, 197, 199,
- 202, 207, 209, 211, 214, 216, 219, 221, 223, 225,
- 227, 229, 231, 233, 235, 237, 239, 241, 243, 245,
- 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
- 267, 269, 271, 273, 275, 277, 279, 281, 283, 285,
- 287, 289
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 58, 0, -1, -1, 58, 59, -1, 61, -1, 65,
- -1, 60, -1, 6, 66, -1, 18, 63, 21, -1,
- 5, 63, 21, -1, 8, 17, 67, 21, -1, 7,
- 17, 45, 46, 67, 21, -1, 7, 17, 45, 64,
- 46, 67, 21, -1, 15, 17, 21, -1, 12, 70,
- 21, -1, 12, 21, -1, 13, 17, 68, 21, -1,
- 14, 17, 68, 21, -1, 9, 70, 21, -1, 9,
- 21, -1, 10, 21, -1, 11, 21, -1, 16, 62,
- 21, -1, 6, 21, -1, 20, -1, 19, -1, 62,
- -1, 63, 26, 63, -1, 63, 27, 63, -1, 63,
- 28, 63, -1, 63, 29, 63, -1, 63, 30, 63,
- -1, 63, 31, 63, -1, 63, 32, 63, -1, 63,
- 35, 63, -1, 63, 36, 63, -1, 63, 34, 63,
- -1, 63, 33, 63, -1, 63, 37, 63, -1, 63,
- 38, 63, -1, 63, 40, 63, -1, 63, 39, 63,
- -1, 63, 43, 63, -1, 63, 42, 63, -1, 63,
- 41, 63, -1, 47, 63, -1, 48, 63, -1, 40,
- 63, -1, 39, 63, -1, 45, 63, 46, -1, 17,
- -1, 64, 49, 17, -1, 21, -1, 71, 21, -1,
- 71, 21, -1, -1, 71, -1, -1, 71, -1, 4,
- 17, -1, 4, 45, 17, 46, -1, 72, -1, 69,
- -1, 70, 69, -1, 72, -1, 71, 72, -1, 17,
- -1, 20, -1, 73, -1, 22, -1, 24, -1, 50,
- -1, 51, -1, 45, -1, 46, -1, 52, -1, 53,
- -1, 54, -1, 30, -1, 41, -1, 39, -1, 40,
- -1, 48, -1, 47, -1, 42, -1, 43, -1, 38,
- -1, 37, -1, 33, -1, 34, -1, 36, -1, 35,
- -1, 32, -1, 31, -1, 29, -1, 28, -1, 27,
- -1, 26, -1, 55, -1, 49, -1, 56, -1, 25,
- -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 185, 185, 187, 191, 194, 199, 200, 204, 207,
- 213, 216, 219, 222, 230, 249, 259, 264, 269, 288,
- 303, 306, 309, 330, 334, 343, 348, 349, 352, 355,
- 358, 361, 364, 367, 370, 373, 376, 379, 382, 385,
- 388, 391, 394, 397, 405, 408, 411, 414, 417, 420,
- 426, 431, 439, 440, 444, 450, 451, 454, 456, 463,
- 467, 471, 476, 480, 487, 492, 499, 503, 507, 511,
- 515, 522, 523, 524, 525, 526, 527, 528, 529, 530,
- 531, 532, 533, 534, 535, 536, 537, 538, 539, 540,
- 541, 542, 543, 544, 545, 546, 547, 548, 549, 550,
- 551, 552
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "COMMA_FINAL", "DEFINED",
- "ELIF_EXPANDED", "HASH", "HASH_DEFINE_FUNC", "HASH_DEFINE_OBJ",
- "HASH_ELIF", "HASH_ELSE", "HASH_ENDIF", "HASH_IF", "HASH_IFDEF",
- "HASH_IFNDEF", "HASH_UNDEF", "HASH_VERSION", "IDENTIFIER", "IF_EXPANDED",
- "INTEGER", "INTEGER_STRING", "NEWLINE", "OTHER", "PLACEHOLDER", "SPACE",
- "PASTE", "OR", "AND", "'|'", "'^'", "'&'", "NOT_EQUAL", "EQUAL", "'<'",
- "'>'", "GREATER_OR_EQUAL", "LESS_OR_EQUAL", "RIGHT_SHIFT", "LEFT_SHIFT",
- "'+'", "'-'", "'*'", "'/'", "'%'", "UNARY", "'('", "')'", "'!'", "'~'",
- "','", "'['", "']'", "'{'", "'}'", "'.'", "';'", "'='", "$accept",
- "input", "line", "expanded_line", "control_line", "integer_constant",
- "expression", "identifier_list", "text_line", "non_directive",
- "replacement_list", "junk", "conditional_token", "conditional_tokens",
- "pp_tokens", "preprocessing_token", "operator", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
- 275, 276, 277, 278, 279, 280, 281, 282, 124, 94,
- 38, 283, 284, 60, 62, 285, 286, 287, 288, 43,
- 45, 42, 47, 37, 289, 40, 41, 33, 126, 44,
- 91, 93, 123, 125, 46, 59, 61
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 57, 58, 58, 59, 59, 59, 59, 60, 60,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 62, 62, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 64, 64, 65, 65, 66, 67, 67, 68, 68, 69,
- 69, 69, 70, 70, 71, 71, 72, 72, 72, 72,
- 72, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 0, 2, 1, 1, 1, 2, 3, 3,
- 4, 6, 7, 3, 3, 2, 4, 4, 3, 2,
- 2, 2, 3, 2, 1, 1, 1, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 2, 2, 2, 3,
- 1, 3, 1, 2, 2, 0, 1, 0, 1, 2,
- 4, 1, 1, 2, 1, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
-{
- 2, 0, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 66, 0, 67, 52, 69,
- 70, 101, 97, 96, 95, 94, 78, 93, 92, 88,
- 89, 91, 90, 87, 86, 80, 81, 79, 84, 85,
- 73, 74, 83, 82, 99, 71, 72, 75, 76, 77,
- 98, 100, 3, 6, 4, 5, 0, 64, 68, 25,
- 24, 0, 0, 0, 0, 0, 26, 0, 23, 7,
- 0, 0, 55, 0, 19, 62, 0, 61, 20, 21,
- 15, 0, 57, 57, 0, 0, 0, 53, 65, 48,
- 47, 0, 45, 46, 9, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 54, 0, 0, 56, 59, 0, 18,
- 63, 14, 0, 58, 0, 13, 22, 8, 49, 27,
- 28, 29, 30, 31, 32, 33, 37, 36, 34, 35,
- 38, 39, 41, 40, 44, 43, 42, 50, 55, 0,
- 10, 0, 16, 17, 0, 55, 0, 60, 11, 0,
- 51, 12
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int16 yydefgoto[] =
-{
- -1, 1, 52, 53, 54, 66, 67, 149, 55, 69,
- 115, 122, 75, 76, 116, 57, 58
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -147
-static const yytype_int16 yypact[] =
-{
- -147, 112, -147, 28, -10, 55, 62, 152, -15, 59,
- 192, 85, 86, 87, 51, -147, 28, -147, -147, -147,
- -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
- -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
- -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
- -147, -147, -147, -147, -147, -147, 312, -147, -147, -147,
- -147, 28, 28, 28, 28, 28, -147, 428, -147, -147,
- 352, 63, 392, 17, -147, -147, 232, -147, -147, -147,
- -147, 272, 392, 392, 84, 89, 451, -147, -147, -147,
- -147, 469, -147, -147, -147, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, -147, 60, 90, 392, -147, 96, -147,
- -147, -147, 93, 392, 94, -147, -147, -147, -147, 489,
- 505, 520, 534, 547, 558, 558, 18, 18, 18, 18,
- 563, 563, 23, 23, -147, -147, -147, -147, 392, 32,
- -147, 61, -147, -147, 110, 392, 118, -147, -147, 149,
- -147, -147
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int16 yypgoto[] =
-{
- -147, -147, -147, -147, -147, 157, -11, -147, -147, -147,
- -146, 92, -68, 200, 0, -7, -147
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
- 77, 56, 154, 77, 70, 86, 78, 15, 120, 159,
- 17, 68, 19, 120, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 117, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 59, 60, 88,
- 89, 90, 91, 92, 93, 106, 107, 108, 109, 110,
- 111, 112, 118, 88, 110, 111, 112, 61, 62, 77,
- 59, 60, 71, 63, 77, 64, 65, 147, 155, 72,
- 79, 156, 123, 123, 129, 130, 131, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
- 145, 146, 82, 83, 84, 125, 148, 157, 114, 88,
- 126, 150, 2, 151, 152, 153, 88, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 158, 17, 18, 19, 160, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 161, 85, 17, 74, 19, 124, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 81, 0, 17, 80, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 0, 0, 17, 119, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 0, 0, 17, 121, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 0, 0, 17, 87, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 0, 0, 17, 113, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
- 0, 0, 17, 0, 19, 0, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 94,
- 0, 0, 0, 0, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 111, 112, 127, 0, 0, 0, 0, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 111, 112, 95, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- 110, 111, 112, 0, 0, 128, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- 110, 111, 112, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111, 112, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
- 109, 110, 111, 112, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 100, 101,
- 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 111, 112, 108, 109, 110, 111, 112
-};
-
-static const yytype_int16 yycheck[] =
-{
- 7, 1, 148, 10, 4, 16, 21, 17, 76, 155,
- 20, 21, 22, 81, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 17, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 19, 20, 56,
- 61, 62, 63, 64, 65, 37, 38, 39, 40, 41,
- 42, 43, 45, 70, 41, 42, 43, 39, 40, 76,
- 19, 20, 17, 45, 81, 47, 48, 17, 46, 17,
- 21, 49, 82, 83, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 111, 112, 17, 17, 17, 21, 46, 46, 45, 116,
- 21, 21, 0, 17, 21, 21, 123, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 21, 20, 21, 22, 17, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- 21, 14, 20, 21, 22, 83, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- 10, -1, 20, 21, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
- -1, -1, 20, -1, 22, -1, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 21,
- -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 21, -1, -1, -1, -1, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, -1, -1, 46, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
- 43, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 39, 40, 41, 42, 43
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 58, 0, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 20, 21, 22,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 59, 60, 61, 65, 71, 72, 73, 19,
- 20, 39, 40, 45, 47, 48, 62, 63, 21, 66,
- 71, 17, 17, 4, 21, 69, 70, 72, 21, 21,
- 21, 70, 17, 17, 17, 62, 63, 21, 72, 63,
- 63, 63, 63, 63, 21, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 21, 45, 67, 71, 17, 45, 21,
- 69, 21, 68, 71, 68, 21, 21, 21, 46, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 17, 46, 64,
- 21, 17, 21, 21, 67, 46, 49, 46, 21, 67,
- 17, 21
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
-
-#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (&yylloc, parser, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, &yylloc, parser)
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value, Location, parser); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- YYLTYPE const * const yylocationp;
- glcpp_parser_t *parser;
-#endif
-{
- if (!yyvaluep)
- return;
- YYUSE (yylocationp);
- YYUSE (parser);
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- YYLTYPE const * const yylocationp;
- glcpp_parser_t *parser;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- YY_LOCATION_PRINT (yyoutput, *yylocationp);
- YYFPRINTF (yyoutput, ": ");
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser);
- YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; yybottom <= yytop; yybottom++)
- {
- int yybot = *yybottom;
- YYFPRINTF (stderr, " %d", yybot);
- }
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, glcpp_parser_t *parser)
-#else
-static void
-yy_reduce_print (yyvsp, yylsp, yyrule, parser)
- YYSTYPE *yyvsp;
- YYLTYPE *yylsp;
- int yyrule;
- glcpp_parser_t *parser;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- , &(yylsp[(yyi + 1) - (yynrhs)]) , parser);
- YYFPRINTF (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, yylsp, Rule, parser); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYSIZE_T yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
-
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
-
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
-
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
-
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- }
- return yysize;
- }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, glcpp_parser_t *parser)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, yylocationp, parser)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
- YYLTYPE *yylocationp;
- glcpp_parser_t *parser;
-#endif
-{
- YYUSE (yyvaluep);
- YYUSE (yylocationp);
- YYUSE (parser);
-
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-
-/* Prevent warnings from -Wmissing-prototypes. */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (glcpp_parser_t *parser);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-/*-------------------------.
-| yyparse or yypush_parse. |
-`-------------------------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (glcpp_parser_t *parser)
-#else
-int
-yyparse (parser)
- glcpp_parser_t *parser;
-#endif
-#endif
-{
-/* The lookahead symbol. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-
-/* Location data for the lookahead symbol. */
-YYLTYPE yylloc;
-
- /* Number of syntax errors so far. */
- int yynerrs;
-
- int yystate;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
-
- /* The location stack. */
- YYLTYPE yylsa[YYINITDEPTH];
- YYLTYPE *yyls;
- YYLTYPE *yylsp;
-
- /* The locations where the error started and ended. */
- YYLTYPE yyerror_range[3];
-
- YYSIZE_T yystacksize;
-
- int yyn;
- int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken;
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
- YYLTYPE yyloc;
-
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- yytoken = 0;
- yyss = yyssa;
- yyvs = yyvsa;
- yyls = yylsa;
- yystacksize = YYINITDEPTH;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;
- yylsp = yyls;
-
-#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
- /* Initialize the default location before parsing starts. */
- yylloc.first_line = yylloc.last_line = 1;
- yylloc.first_column = yylloc.last_column = 1;
-#endif
-
-/* User initialization code. */
-
-/* Line 1251 of yacc.c */
-#line 152 "glcpp/glcpp-parse.y"
-{
- yylloc.first_line = 1;
- yylloc.first_column = 1;
- yylloc.last_line = 1;
- yylloc.last_column = 1;
- yylloc.source = 0;
-}
-
-/* Line 1251 of yacc.c */
-#line 1622 "glcpp/glcpp-parse.c"
- yylsp[0] = yylloc;
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
- YYLTYPE *yyls1 = yyls;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yyls1, yysize * sizeof (*yylsp),
- &yystacksize);
-
- yyls = yyls1;
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
- YYSTACK_RELOCATE (yyls_alloc, yyls);
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
- yylsp = yyls + yysize - 1;
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- if (yystate == YYFINAL)
- YYACCEPT;
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- lookahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to lookahead token. */
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the lookahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
- yystate = yyn;
- *++yyvsp = yylval;
- *++yylsp = yylloc;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
- /* Default location. */
- YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 4:
-
-/* Line 1464 of yacc.c */
-#line 191 "glcpp/glcpp-parse.y"
- {
- glcpp_print(parser->output, "\n");
- ;}
- break;
-
- case 5:
-
-/* Line 1464 of yacc.c */
-#line 194 "glcpp/glcpp-parse.y"
- {
- _glcpp_parser_print_expanded_token_list (parser, (yyvsp[(1) - (1)].token_list));
- glcpp_print(parser->output, "\n");
- talloc_free ((yyvsp[(1) - (1)].token_list));
- ;}
- break;
-
- case 8:
-
-/* Line 1464 of yacc.c */
-#line 204 "glcpp/glcpp-parse.y"
- {
- _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival));
- ;}
- break;
-
- case 9:
-
-/* Line 1464 of yacc.c */
-#line 207 "glcpp/glcpp-parse.y"
- {
- _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival));
- ;}
- break;
-
- case 10:
-
-/* Line 1464 of yacc.c */
-#line 213 "glcpp/glcpp-parse.y"
- {
- _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list));
- ;}
- break;
-
- case 11:
-
-/* Line 1464 of yacc.c */
-#line 216 "glcpp/glcpp-parse.y"
- {
- _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list));
- ;}
- break;
-
- case 12:
-
-/* Line 1464 of yacc.c */
-#line 219 "glcpp/glcpp-parse.y"
- {
- _define_function_macro (parser, & (yylsp[(2) - (7)]), (yyvsp[(2) - (7)].str), (yyvsp[(4) - (7)].string_list), (yyvsp[(6) - (7)].token_list));
- ;}
- break;
-
- case 13:
-
-/* Line 1464 of yacc.c */
-#line 222 "glcpp/glcpp-parse.y"
- {
- macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (3)].str));
- if (macro) {
- hash_table_remove (parser->defines, (yyvsp[(2) - (3)].str));
- talloc_free (macro);
- }
- talloc_free ((yyvsp[(2) - (3)].str));
- ;}
- break;
-
- case 14:
-
-/* Line 1464 of yacc.c */
-#line 230 "glcpp/glcpp-parse.y"
- {
- /* Be careful to only evaluate the 'if' expression if
- * we are not skipping. When we are skipping, we
- * simply push a new 0-valued 'if' onto the skip
- * stack.
- *
- * This avoids generating diagnostics for invalid
- * expressions that are being skipped. */
- if (parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- _glcpp_parser_expand_if (parser, IF_EXPANDED, (yyvsp[(2) - (3)].token_list));
- }
- else
- {
- _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), 0);
- parser->skip_stack->type = SKIP_TO_ENDIF;
- }
- ;}
- break;
-
- case 15:
-
-/* Line 1464 of yacc.c */
-#line 249 "glcpp/glcpp-parse.y"
- {
- /* #if without an expression is only an error if we
- * are not skipping */
- if (parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- glcpp_error(& (yylsp[(1) - (2)]), parser, "#if with no expression");
- }
- _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (2)]), 0);
- ;}
- break;
-
- case 16:
-
-/* Line 1464 of yacc.c */
-#line 259 "glcpp/glcpp-parse.y"
- {
- macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
- talloc_free ((yyvsp[(2) - (4)].str));
- _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro != NULL);
- ;}
- break;
-
- case 17:
-
-/* Line 1464 of yacc.c */
-#line 264 "glcpp/glcpp-parse.y"
- {
- macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
- talloc_free ((yyvsp[(2) - (4)].str));
- _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro == NULL);
- ;}
- break;
-
- case 18:
-
-/* Line 1464 of yacc.c */
-#line 269 "glcpp/glcpp-parse.y"
- {
- /* Be careful to only evaluate the 'elif' expression
- * if we are not skipping. When we are skipping, we
- * simply change to a 0-valued 'elif' on the skip
- * stack.
- *
- * This avoids generating diagnostics for invalid
- * expressions that are being skipped. */
- if (parser->skip_stack &&
- parser->skip_stack->type == SKIP_TO_ELSE)
- {
- _glcpp_parser_expand_if (parser, ELIF_EXPANDED, (yyvsp[(2) - (3)].token_list));
- }
- else
- {
- _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]),
- "elif", 0);
- }
- ;}
- break;
-
- case 19:
-
-/* Line 1464 of yacc.c */
-#line 288 "glcpp/glcpp-parse.y"
- {
- /* #elif without an expression is an error unless we
- * are skipping. */
- if (parser->skip_stack &&
- parser->skip_stack->type == SKIP_TO_ELSE)
- {
- glcpp_error(& (yylsp[(1) - (2)]), parser, "#elif with no expression");
- }
- else
- {
- _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]),
- "elif", 0);
- glcpp_warning(& (yylsp[(1) - (2)]), parser, "ignoring illegal #elif without expression");
- }
- ;}
- break;
-
- case 20:
-
-/* Line 1464 of yacc.c */
-#line 303 "glcpp/glcpp-parse.y"
- {
- _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1);
- ;}
- break;
-
- case 21:
-
-/* Line 1464 of yacc.c */
-#line 306 "glcpp/glcpp-parse.y"
- {
- _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)]));
- ;}
- break;
-
- case 22:
-
-/* Line 1464 of yacc.c */
-#line 309 "glcpp/glcpp-parse.y"
- {
- macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
- if (macro) {
- hash_table_remove (parser->defines, "__VERSION__");
- talloc_free (macro);
- }
- add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival));
-
- if ((yyvsp[(2) - (3)].ival) == 100)
- add_builtin_define (parser, "GL_ES", 1);
-
- /* Currently, all ES2 implementations support highp in the
- * fragment shader, so we always define this macro in ES2.
- * If we ever get a driver that doesn't support highp, we'll
- * need to add a flag to the gl_context and check that here.
- */
- if ((yyvsp[(2) - (3)].ival) >= 130 || (yyvsp[(2) - (3)].ival) == 100)
- add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
-
- glcpp_printf(parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival));
- ;}
- break;
-
- case 24:
-
-/* Line 1464 of yacc.c */
-#line 334 "glcpp/glcpp-parse.y"
- {
- if (strlen ((yyvsp[(1) - (1)].str)) >= 3 && strncmp ((yyvsp[(1) - (1)].str), "0x", 2) == 0) {
- (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str) + 2, NULL, 16);
- } else if ((yyvsp[(1) - (1)].str)[0] == '0') {
- (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 8);
- } else {
- (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 10);
- }
- ;}
- break;
-
- case 25:
-
-/* Line 1464 of yacc.c */
-#line 343 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (1)].ival);
- ;}
- break;
-
- case 27:
-
-/* Line 1464 of yacc.c */
-#line 349 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 28:
-
-/* Line 1464 of yacc.c */
-#line 352 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 29:
-
-/* Line 1464 of yacc.c */
-#line 355 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 30:
-
-/* Line 1464 of yacc.c */
-#line 358 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 31:
-
-/* Line 1464 of yacc.c */
-#line 361 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 32:
-
-/* Line 1464 of yacc.c */
-#line 364 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 33:
-
-/* Line 1464 of yacc.c */
-#line 367 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 34:
-
-/* Line 1464 of yacc.c */
-#line 370 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 35:
-
-/* Line 1464 of yacc.c */
-#line 373 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 36:
-
-/* Line 1464 of yacc.c */
-#line 376 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 37:
-
-/* Line 1464 of yacc.c */
-#line 379 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 38:
-
-/* Line 1464 of yacc.c */
-#line 382 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 39:
-
-/* Line 1464 of yacc.c */
-#line 385 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 40:
-
-/* Line 1464 of yacc.c */
-#line 388 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 41:
-
-/* Line 1464 of yacc.c */
-#line 391 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 42:
-
-/* Line 1464 of yacc.c */
-#line 394 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 43:
-
-/* Line 1464 of yacc.c */
-#line 397 "glcpp/glcpp-parse.y"
- {
- if ((yyvsp[(3) - (3)].ival) == 0) {
- yyerror (& (yylsp[(1) - (3)]), parser,
- "division by 0 in preprocessor directive");
- } else {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) / (yyvsp[(3) - (3)].ival);
- }
- ;}
- break;
-
- case 44:
-
-/* Line 1464 of yacc.c */
-#line 405 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival);
- ;}
- break;
-
- case 45:
-
-/* Line 1464 of yacc.c */
-#line 408 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = ! (yyvsp[(2) - (2)].ival);
- ;}
- break;
-
- case 46:
-
-/* Line 1464 of yacc.c */
-#line 411 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = ~ (yyvsp[(2) - (2)].ival);
- ;}
- break;
-
- case 47:
-
-/* Line 1464 of yacc.c */
-#line 414 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = - (yyvsp[(2) - (2)].ival);
- ;}
- break;
-
- case 48:
-
-/* Line 1464 of yacc.c */
-#line 417 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = + (yyvsp[(2) - (2)].ival);
- ;}
- break;
-
- case 49:
-
-/* Line 1464 of yacc.c */
-#line 420 "glcpp/glcpp-parse.y"
- {
- (yyval.ival) = (yyvsp[(2) - (3)].ival);
- ;}
- break;
-
- case 50:
-
-/* Line 1464 of yacc.c */
-#line 426 "glcpp/glcpp-parse.y"
- {
- (yyval.string_list) = _string_list_create (parser);
- _string_list_append_item ((yyval.string_list), (yyvsp[(1) - (1)].str));
- talloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str));
- ;}
- break;
-
- case 51:
-
-/* Line 1464 of yacc.c */
-#line 431 "glcpp/glcpp-parse.y"
- {
- (yyval.string_list) = (yyvsp[(1) - (3)].string_list);
- _string_list_append_item ((yyval.string_list), (yyvsp[(3) - (3)].str));
- talloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str));
- ;}
- break;
-
- case 52:
-
-/* Line 1464 of yacc.c */
-#line 439 "glcpp/glcpp-parse.y"
- { (yyval.token_list) = NULL; ;}
- break;
-
- case 54:
-
-/* Line 1464 of yacc.c */
-#line 444 "glcpp/glcpp-parse.y"
- {
- yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #");
- ;}
- break;
-
- case 55:
-
-/* Line 1464 of yacc.c */
-#line 450 "glcpp/glcpp-parse.y"
- { (yyval.token_list) = NULL; ;}
- break;
-
- case 58:
-
-/* Line 1464 of yacc.c */
-#line 456 "glcpp/glcpp-parse.y"
- {
- glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive");
- ;}
- break;
-
- case 59:
-
-/* Line 1464 of yacc.c */
-#line 463 "glcpp/glcpp-parse.y"
- {
- int v = hash_table_find (parser->defines, (yyvsp[(2) - (2)].str)) ? 1 : 0;
- (yyval.token) = _token_create_ival (parser, INTEGER, v);
- ;}
- break;
-
- case 60:
-
-/* Line 1464 of yacc.c */
-#line 467 "glcpp/glcpp-parse.y"
- {
- int v = hash_table_find (parser->defines, (yyvsp[(3) - (4)].str)) ? 1 : 0;
- (yyval.token) = _token_create_ival (parser, INTEGER, v);
- ;}
- break;
-
- case 62:
-
-/* Line 1464 of yacc.c */
-#line 476 "glcpp/glcpp-parse.y"
- {
- (yyval.token_list) = _token_list_create (parser);
- _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
- ;}
- break;
-
- case 63:
-
-/* Line 1464 of yacc.c */
-#line 480 "glcpp/glcpp-parse.y"
- {
- (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
- _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
- ;}
- break;
-
- case 64:
-
-/* Line 1464 of yacc.c */
-#line 487 "glcpp/glcpp-parse.y"
- {
- parser->space_tokens = 1;
- (yyval.token_list) = _token_list_create (parser);
- _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
- ;}
- break;
-
- case 65:
-
-/* Line 1464 of yacc.c */
-#line 492 "glcpp/glcpp-parse.y"
- {
- (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
- _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
- ;}
- break;
-
- case 66:
-
-/* Line 1464 of yacc.c */
-#line 499 "glcpp/glcpp-parse.y"
- {
- (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str));
- (yyval.token)->location = yylloc;
- ;}
- break;
-
- case 67:
-
-/* Line 1464 of yacc.c */
-#line 503 "glcpp/glcpp-parse.y"
- {
- (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str));
- (yyval.token)->location = yylloc;
- ;}
- break;
-
- case 68:
-
-/* Line 1464 of yacc.c */
-#line 507 "glcpp/glcpp-parse.y"
- {
- (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival));
- (yyval.token)->location = yylloc;
- ;}
- break;
-
- case 69:
-
-/* Line 1464 of yacc.c */
-#line 511 "glcpp/glcpp-parse.y"
- {
- (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str));
- (yyval.token)->location = yylloc;
- ;}
- break;
-
- case 70:
-
-/* Line 1464 of yacc.c */
-#line 515 "glcpp/glcpp-parse.y"
- {
- (yyval.token) = _token_create_ival (parser, SPACE, SPACE);
- (yyval.token)->location = yylloc;
- ;}
- break;
-
- case 71:
-
-/* Line 1464 of yacc.c */
-#line 522 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '['; ;}
- break;
-
- case 72:
-
-/* Line 1464 of yacc.c */
-#line 523 "glcpp/glcpp-parse.y"
- { (yyval.ival) = ']'; ;}
- break;
-
- case 73:
-
-/* Line 1464 of yacc.c */
-#line 524 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '('; ;}
- break;
-
- case 74:
-
-/* Line 1464 of yacc.c */
-#line 525 "glcpp/glcpp-parse.y"
- { (yyval.ival) = ')'; ;}
- break;
-
- case 75:
-
-/* Line 1464 of yacc.c */
-#line 526 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '{'; ;}
- break;
-
- case 76:
-
-/* Line 1464 of yacc.c */
-#line 527 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '}'; ;}
- break;
-
- case 77:
-
-/* Line 1464 of yacc.c */
-#line 528 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '.'; ;}
- break;
-
- case 78:
-
-/* Line 1464 of yacc.c */
-#line 529 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '&'; ;}
- break;
-
- case 79:
-
-/* Line 1464 of yacc.c */
-#line 530 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '*'; ;}
- break;
-
- case 80:
-
-/* Line 1464 of yacc.c */
-#line 531 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '+'; ;}
- break;
-
- case 81:
-
-/* Line 1464 of yacc.c */
-#line 532 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '-'; ;}
- break;
-
- case 82:
-
-/* Line 1464 of yacc.c */
-#line 533 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '~'; ;}
- break;
-
- case 83:
-
-/* Line 1464 of yacc.c */
-#line 534 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '!'; ;}
- break;
-
- case 84:
-
-/* Line 1464 of yacc.c */
-#line 535 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '/'; ;}
- break;
-
- case 85:
-
-/* Line 1464 of yacc.c */
-#line 536 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '%'; ;}
- break;
-
- case 86:
-
-/* Line 1464 of yacc.c */
-#line 537 "glcpp/glcpp-parse.y"
- { (yyval.ival) = LEFT_SHIFT; ;}
- break;
-
- case 87:
-
-/* Line 1464 of yacc.c */
-#line 538 "glcpp/glcpp-parse.y"
- { (yyval.ival) = RIGHT_SHIFT; ;}
- break;
-
- case 88:
-
-/* Line 1464 of yacc.c */
-#line 539 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '<'; ;}
- break;
-
- case 89:
-
-/* Line 1464 of yacc.c */
-#line 540 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '>'; ;}
- break;
-
- case 90:
-
-/* Line 1464 of yacc.c */
-#line 541 "glcpp/glcpp-parse.y"
- { (yyval.ival) = LESS_OR_EQUAL; ;}
- break;
-
- case 91:
-
-/* Line 1464 of yacc.c */
-#line 542 "glcpp/glcpp-parse.y"
- { (yyval.ival) = GREATER_OR_EQUAL; ;}
- break;
-
- case 92:
-
-/* Line 1464 of yacc.c */
-#line 543 "glcpp/glcpp-parse.y"
- { (yyval.ival) = EQUAL; ;}
- break;
-
- case 93:
-
-/* Line 1464 of yacc.c */
-#line 544 "glcpp/glcpp-parse.y"
- { (yyval.ival) = NOT_EQUAL; ;}
- break;
-
- case 94:
-
-/* Line 1464 of yacc.c */
-#line 545 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '^'; ;}
- break;
-
- case 95:
-
-/* Line 1464 of yacc.c */
-#line 546 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '|'; ;}
- break;
-
- case 96:
-
-/* Line 1464 of yacc.c */
-#line 547 "glcpp/glcpp-parse.y"
- { (yyval.ival) = AND; ;}
- break;
-
- case 97:
-
-/* Line 1464 of yacc.c */
-#line 548 "glcpp/glcpp-parse.y"
- { (yyval.ival) = OR; ;}
- break;
-
- case 98:
-
-/* Line 1464 of yacc.c */
-#line 549 "glcpp/glcpp-parse.y"
- { (yyval.ival) = ';'; ;}
- break;
-
- case 99:
-
-/* Line 1464 of yacc.c */
-#line 550 "glcpp/glcpp-parse.y"
- { (yyval.ival) = ','; ;}
- break;
-
- case 100:
-
-/* Line 1464 of yacc.c */
-#line 551 "glcpp/glcpp-parse.y"
- { (yyval.ival) = '='; ;}
- break;
-
- case 101:
-
-/* Line 1464 of yacc.c */
-#line 552 "glcpp/glcpp-parse.y"
- { (yyval.ival) = PASTE; ;}
- break;
-
-
-
-/* Line 1464 of yacc.c */
-#line 2661 "glcpp/glcpp-parse.c"
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
- *++yylsp = yyloc;
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (&yylloc, parser, YY_("syntax error"));
-#else
- {
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (&yylloc, parser, yymsg);
- }
- else
- {
- yyerror (&yylloc, parser, YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
- }
-#endif
- }
-
- yyerror_range[1] = yylloc;
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval, &yylloc, parser);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- yyerror_range[1] = yylsp[1-yylen];
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
- yyerror_range[1] = *yylsp;
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yylsp, parser);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- *++yyvsp = yylval;
-
- yyerror_range[2] = yylloc;
- /* Using YYLLOC is tempting, but would change the location of
- the lookahead. YYLOC is available though. */
- YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
- *++yylsp = yyloc;
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#if !defined(yyoverflow) || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (&yylloc, parser, YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
- if (yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval, &yylloc, parser);
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yylsp, parser);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
-}
-
-
-
-/* Line 1684 of yacc.c */
-#line 555 "glcpp/glcpp-parse.y"
-
-
-string_list_t *
-_string_list_create (void *ctx)
-{
- string_list_t *list;
-
- list = talloc (ctx, string_list_t);
- list->head = NULL;
- list->tail = NULL;
-
- return list;
-}
-
-void
-_string_list_append_item (string_list_t *list, const char *str)
-{
- string_node_t *node;
-
- node = talloc (list, string_node_t);
- node->str = talloc_strdup (node, str);
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
-}
-
-int
-_string_list_contains (string_list_t *list, const char *member, int *index)
-{
- string_node_t *node;
- int i;
-
- if (list == NULL)
- return 0;
-
- for (i = 0, node = list->head; node; i++, node = node->next) {
- if (strcmp (node->str, member) == 0) {
- if (index)
- *index = i;
- return 1;
- }
- }
-
- return 0;
-}
-
-int
-_string_list_length (string_list_t *list)
-{
- int length = 0;
- string_node_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list->head; node; node = node->next)
- length++;
-
- return length;
-}
-
-int
-_string_list_equal (string_list_t *a, string_list_t *b)
-{
- string_node_t *node_a, *node_b;
-
- if (a == NULL && b == NULL)
- return 1;
-
- if (a == NULL || b == NULL)
- return 0;
-
- for (node_a = a->head, node_b = b->head;
- node_a && node_b;
- node_a = node_a->next, node_b = node_b->next)
- {
- if (strcmp (node_a->str, node_b->str))
- return 0;
- }
-
- /* Catch the case of lists being different lengths, (which
- * would cause the loop above to terminate after the shorter
- * list). */
- return node_a == node_b;
-}
-
-argument_list_t *
-_argument_list_create (void *ctx)
-{
- argument_list_t *list;
-
- list = talloc (ctx, argument_list_t);
- list->head = NULL;
- list->tail = NULL;
-
- return list;
-}
-
-void
-_argument_list_append (argument_list_t *list, token_list_t *argument)
-{
- argument_node_t *node;
-
- node = talloc (list, argument_node_t);
- node->argument = argument;
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
-}
-
-int
-_argument_list_length (argument_list_t *list)
-{
- int length = 0;
- argument_node_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list->head; node; node = node->next)
- length++;
-
- return length;
-}
-
-token_list_t *
-_argument_list_member_at (argument_list_t *list, int index)
-{
- argument_node_t *node;
- int i;
-
- if (list == NULL)
- return NULL;
-
- node = list->head;
- for (i = 0; i < index; i++) {
- node = node->next;
- if (node == NULL)
- break;
- }
-
- if (node)
- return node->argument;
-
- return NULL;
-}
-
-/* Note: This function talloc_steal()s the str pointer. */
-token_t *
-_token_create_str (void *ctx, int type, char *str)
-{
- token_t *token;
-
- token = talloc (ctx, token_t);
- token->type = type;
- token->value.str = talloc_steal (token, str);
-
- return token;
-}
-
-token_t *
-_token_create_ival (void *ctx, int type, int ival)
-{
- token_t *token;
-
- token = talloc (ctx, token_t);
- token->type = type;
- token->value.ival = ival;
-
- return token;
-}
-
-token_list_t *
-_token_list_create (void *ctx)
-{
- token_list_t *list;
-
- list = talloc (ctx, token_list_t);
- list->head = NULL;
- list->tail = NULL;
- list->non_space_tail = NULL;
-
- return list;
-}
-
-void
-_token_list_append (token_list_t *list, token_t *token)
-{
- token_node_t *node;
-
- node = talloc (list, token_node_t);
- node->token = talloc_steal (list, token);
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
- if (token->type != SPACE)
- list->non_space_tail = node;
-}
-
-void
-_token_list_append_list (token_list_t *list, token_list_t *tail)
-{
- if (tail == NULL || tail->head == NULL)
- return;
-
- if (list->head == NULL) {
- list->head = tail->head;
- } else {
- list->tail->next = tail->head;
- }
-
- list->tail = tail->tail;
- list->non_space_tail = tail->non_space_tail;
-}
-
-static token_list_t *
-_token_list_copy (void *ctx, token_list_t *other)
-{
- token_list_t *copy;
- token_node_t *node;
-
- if (other == NULL)
- return NULL;
-
- copy = _token_list_create (ctx);
- for (node = other->head; node; node = node->next) {
- token_t *new_token = talloc (copy, token_t);
- *new_token = *node->token;
- _token_list_append (copy, new_token);
- }
-
- return copy;
-}
-
-static void
-_token_list_trim_trailing_space (token_list_t *list)
-{
- token_node_t *tail, *next;
-
- if (list->non_space_tail) {
- tail = list->non_space_tail->next;
- list->non_space_tail->next = NULL;
- list->tail = list->non_space_tail;
-
- while (tail) {
- next = tail->next;
- talloc_free (tail);
- tail = next;
- }
- }
-}
-
-int
-_token_list_is_empty_ignoring_space (token_list_t *l)
-{
- token_node_t *n;
-
- if (l == NULL)
- return 1;
-
- n = l->head;
- while (n != NULL && n->token->type == SPACE)
- n = n->next;
-
- return n == NULL;
-}
-
-int
-_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
-{
- token_node_t *node_a, *node_b;
-
- if (a == NULL || b == NULL) {
- int a_empty = _token_list_is_empty_ignoring_space(a);
- int b_empty = _token_list_is_empty_ignoring_space(b);
- return a_empty == b_empty;
- }
-
- node_a = a->head;
- node_b = b->head;
-
- while (1)
- {
- if (node_a == NULL && node_b == NULL)
- break;
-
- if (node_a == NULL || node_b == NULL)
- return 0;
-
- if (node_a->token->type == SPACE) {
- node_a = node_a->next;
- continue;
- }
-
- if (node_b->token->type == SPACE) {
- node_b = node_b->next;
- continue;
- }
-
- if (node_a->token->type != node_b->token->type)
- return 0;
-
- switch (node_a->token->type) {
- case INTEGER:
- if (node_a->token->value.ival !=
- node_b->token->value.ival)
- {
- return 0;
- }
- break;
- case IDENTIFIER:
- case INTEGER_STRING:
- case OTHER:
- if (strcmp (node_a->token->value.str,
- node_b->token->value.str))
- {
- return 0;
- }
- break;
- }
-
- node_a = node_a->next;
- node_b = node_b->next;
- }
-
- return 1;
-}
-
-static void
-_token_print (char **out, token_t *token)
-{
- if (token->type < 256) {
- glcpp_printf (*out, "%c", token->type);
- return;
- }
-
- switch (token->type) {
- case INTEGER:
- glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
- break;
- case IDENTIFIER:
- case INTEGER_STRING:
- case OTHER:
- glcpp_print (*out, token->value.str);
- break;
- case SPACE:
- glcpp_print (*out, " ");
- break;
- case LEFT_SHIFT:
- glcpp_print (*out, "<<");
- break;
- case RIGHT_SHIFT:
- glcpp_print (*out, ">>");
- break;
- case LESS_OR_EQUAL:
- glcpp_print (*out, "<=");
- break;
- case GREATER_OR_EQUAL:
- glcpp_print (*out, ">=");
- break;
- case EQUAL:
- glcpp_print (*out, "==");
- break;
- case NOT_EQUAL:
- glcpp_print (*out, "!=");
- break;
- case AND:
- glcpp_print (*out, "&&");
- break;
- case OR:
- glcpp_print (*out, "||");
- break;
- case PASTE:
- glcpp_print (*out, "##");
- break;
- case COMMA_FINAL:
- glcpp_print (*out, ",");
- break;
- case PLACEHOLDER:
- /* Nothing to print. */
- break;
- default:
- assert(!"Error: Don't know how to print token.");
- break;
- }
-}
-
-/* Return a new token (talloc()ed off of 'token') formed by pasting
- * 'token' and 'other'. Note that this function may return 'token' or
- * 'other' directly rather than allocating anything new.
- *
- * Caution: Only very cursory error-checking is performed to see if
- * the final result is a valid single token. */
-static token_t *
-_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
-{
- token_t *combined = NULL;
-
- /* Pasting a placeholder onto anything makes no change. */
- if (other->type == PLACEHOLDER)
- return token;
-
- /* When 'token' is a placeholder, just return 'other'. */
- if (token->type == PLACEHOLDER)
- return other;
-
- /* A very few single-character punctuators can be combined
- * with another to form a multi-character punctuator. */
- switch (token->type) {
- case '<':
- if (other->type == '<')
- combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
- else if (other->type == '=')
- combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
- break;
- case '>':
- if (other->type == '>')
- combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
- else if (other->type == '=')
- combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
- break;
- case '=':
- if (other->type == '=')
- combined = _token_create_ival (token, EQUAL, EQUAL);
- break;
- case '!':
- if (other->type == '=')
- combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
- break;
- case '&':
- if (other->type == '&')
- combined = _token_create_ival (token, AND, AND);
- break;
- case '|':
- if (other->type == '|')
- combined = _token_create_ival (token, OR, OR);
- break;
- }
-
- if (combined != NULL) {
- /* Inherit the location from the first token */
- combined->location = token->location;
- return combined;
- }
-
- /* Two string-valued tokens can usually just be mashed
- * together.
- *
- * XXX: This isn't actually legitimate. Several things here
- * should result in a diagnostic since the result cannot be a
- * valid, single pre-processing token. For example, pasting
- * "123" and "abc" is not legal, but we don't catch that
- * here. */
- if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
- (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
- {
- char *str;
-
- str = talloc_asprintf (token, "%s%s", token->value.str,
- other->value.str);
- combined = _token_create_str (token, token->type, str);
- combined->location = token->location;
- return combined;
- }
-
- glcpp_error (&token->location, parser, "");
- glcpp_print (parser->info_log, "Pasting \"");
- _token_print (&parser->info_log, token);
- glcpp_print (parser->info_log, "\" and \"");
- _token_print (&parser->info_log, other);
- glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
-
- return token;
-}
-
-static void
-_token_list_print (glcpp_parser_t *parser, token_list_t *list)
-{
- token_node_t *node;
-
- if (list == NULL)
- return;
-
- for (node = list->head; node; node = node->next)
- _token_print (&parser->output, node->token);
-}
-
-void
-yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
-{
- glcpp_error(locp, parser, "%s", error);
-}
-
-static void add_builtin_define(glcpp_parser_t *parser,
- const char *name, int value)
-{
- token_t *tok;
- token_list_t *list;
-
- tok = _token_create_ival (parser, INTEGER, value);
-
- list = _token_list_create(parser);
- _token_list_append(list, tok);
- _define_object_macro(parser, NULL, name, list);
-}
-
-glcpp_parser_t *
-glcpp_parser_create (const struct gl_extensions *extensions, int api)
-{
- glcpp_parser_t *parser;
- int language_version;
-
- parser = talloc (NULL, glcpp_parser_t);
-
- glcpp_lex_init_extra (parser, &parser->scanner);
- parser->defines = hash_table_ctor (32, hash_table_string_hash,
- hash_table_string_compare);
- parser->active = NULL;
- parser->lexing_if = 0;
- parser->space_tokens = 1;
- parser->newline_as_space = 0;
- parser->in_control_line = 0;
- parser->paren_count = 0;
-
- parser->skip_stack = NULL;
-
- parser->lex_from_list = NULL;
- parser->lex_from_node = NULL;
-
- parser->output = talloc_strdup(parser, "");
- parser->info_log = talloc_strdup(parser, "");
- parser->error = 0;
-
- /* Add pre-defined macros. */
- add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
- add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
-
- if (api == API_OPENGLES2)
- add_builtin_define(parser, "GL_ES", 1);
-
- if (extensions != NULL) {
- if (extensions->EXT_texture_array) {
- add_builtin_define(parser, "GL_EXT_texture_array", 1);
- }
-
- if (extensions->ARB_fragment_coord_conventions)
- add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
- 1);
-
- if (extensions->ARB_explicit_attrib_location)
- add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
- }
-
- language_version = 110;
- add_builtin_define(parser, "__VERSION__", language_version);
-
- return parser;
-}
-
-int
-glcpp_parser_parse (glcpp_parser_t *parser)
-{
- return yyparse (parser);
-}
-
-void
-glcpp_parser_destroy (glcpp_parser_t *parser)
-{
- glcpp_lex_destroy (parser->scanner);
- hash_table_dtor (parser->defines);
- talloc_free (parser);
-}
-
-typedef enum function_status
-{
- FUNCTION_STATUS_SUCCESS,
- FUNCTION_NOT_A_FUNCTION,
- FUNCTION_UNBALANCED_PARENTHESES
-} function_status_t;
-
-/* Find a set of function-like macro arguments by looking for a
- * balanced set of parentheses.
- *
- * When called, 'node' should be the opening-parenthesis token, (or
- * perhaps preceeding SPACE tokens). Upon successful return *last will
- * be the last consumed node, (corresponding to the closing right
- * parenthesis).
- *
- * Return values:
- *
- * FUNCTION_STATUS_SUCCESS:
- *
- * Successfully parsed a set of function arguments.
- *
- * FUNCTION_NOT_A_FUNCTION:
- *
- * Macro name not followed by a '('. This is not an error, but
- * simply that the macro name should be treated as a non-macro.
- *
- * FUNCTION_UNBALANCED_PARENTHESES
- *
- * Macro name is not followed by a balanced set of parentheses.
- */
-static function_status_t
-_arguments_parse (argument_list_t *arguments,
- token_node_t *node,
- token_node_t **last)
-{
- token_list_t *argument;
- int paren_count;
-
- node = node->next;
-
- /* Ignore whitespace before first parenthesis. */
- while (node && node->token->type == SPACE)
- node = node->next;
-
- if (node == NULL || node->token->type != '(')
- return FUNCTION_NOT_A_FUNCTION;
-
- node = node->next;
-
- argument = _token_list_create (arguments);
- _argument_list_append (arguments, argument);
-
- for (paren_count = 1; node; node = node->next) {
- if (node->token->type == '(')
- {
- paren_count++;
- }
- else if (node->token->type == ')')
- {
- paren_count--;
- if (paren_count == 0)
- break;
- }
-
- if (node->token->type == ',' &&
- paren_count == 1)
- {
- _token_list_trim_trailing_space (argument);
- argument = _token_list_create (arguments);
- _argument_list_append (arguments, argument);
- }
- else {
- if (argument->head == NULL) {
- /* Don't treat initial whitespace as
- * part of the arguement. */
- if (node->token->type == SPACE)
- continue;
- }
- _token_list_append (argument, node->token);
- }
- }
-
- if (paren_count)
- return FUNCTION_UNBALANCED_PARENTHESES;
-
- *last = node;
-
- return FUNCTION_STATUS_SUCCESS;
-}
-
-static token_list_t *
-_token_list_create_with_one_space (void *ctx)
-{
- token_list_t *list;
- token_t *space;
-
- list = _token_list_create (ctx);
- space = _token_create_ival (list, SPACE, SPACE);
- _token_list_append (list, space);
-
- return list;
-}
-
-static void
-_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
-{
- token_list_t *expanded;
- token_t *token;
-
- expanded = _token_list_create (parser);
- token = _token_create_ival (parser, type, type);
- _token_list_append (expanded, token);
- _glcpp_parser_expand_token_list (parser, list);
- _token_list_append_list (expanded, list);
- glcpp_parser_lex_from (parser, expanded);
-}
-
-/* This is a helper function that's essentially part of the
- * implementation of _glcpp_parser_expand_node. It shouldn't be called
- * except for by that function.
- *
- * Returns NULL if node is a simple token with no expansion, (that is,
- * although 'node' corresponds to an identifier defined as a
- * function-like macro, it is not followed with a parenthesized
- * argument list).
- *
- * Compute the complete expansion of node (which is a function-like
- * macro) and subsequent nodes which are arguments.
- *
- * Returns the token list that results from the expansion and sets
- * *last to the last node in the list that was consumed by the
- * expansion. Specifically, *last will be set as follows: as the
- * token of the closing right parenthesis.
- */
-static token_list_t *
-_glcpp_parser_expand_function (glcpp_parser_t *parser,
- token_node_t *node,
- token_node_t **last)
-
-{
- macro_t *macro;
- const char *identifier;
- argument_list_t *arguments;
- function_status_t status;
- token_list_t *substituted;
- int parameter_index;
-
- identifier = node->token->value.str;
-
- macro = hash_table_find (parser->defines, identifier);
-
- assert (macro->is_function);
-
- arguments = _argument_list_create (parser);
- status = _arguments_parse (arguments, node, last);
-
- switch (status) {
- case FUNCTION_STATUS_SUCCESS:
- break;
- case FUNCTION_NOT_A_FUNCTION:
- return NULL;
- case FUNCTION_UNBALANCED_PARENTHESES:
- glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
- return NULL;
- }
-
- /* Replace a macro defined as empty with a SPACE token. */
- if (macro->replacements == NULL) {
- talloc_free (arguments);
- return _token_list_create_with_one_space (parser);
- }
-
- if (! ((_argument_list_length (arguments) ==
- _string_list_length (macro->parameters)) ||
- (_string_list_length (macro->parameters) == 0 &&
- _argument_list_length (arguments) == 1 &&
- arguments->head->argument->head == NULL)))
- {
- glcpp_error (&node->token->location, parser,
- "Error: macro %s invoked with %d arguments (expected %d)\n",
- identifier,
- _argument_list_length (arguments),
- _string_list_length (macro->parameters));
- return NULL;
- }
-
- /* Perform argument substitution on the replacement list. */
- substituted = _token_list_create (arguments);
-
- for (node = macro->replacements->head; node; node = node->next)
- {
- if (node->token->type == IDENTIFIER &&
- _string_list_contains (macro->parameters,
- node->token->value.str,
- &parameter_index))
- {
- token_list_t *argument;
- argument = _argument_list_member_at (arguments,
- parameter_index);
- /* Before substituting, we expand the argument
- * tokens, or append a placeholder token for
- * an empty argument. */
- if (argument->head) {
- token_list_t *expanded_argument;
- expanded_argument = _token_list_copy (parser,
- argument);
- _glcpp_parser_expand_token_list (parser,
- expanded_argument);
- _token_list_append_list (substituted,
- expanded_argument);
- } else {
- token_t *new_token;
-
- new_token = _token_create_ival (substituted,
- PLACEHOLDER,
- PLACEHOLDER);
- _token_list_append (substituted, new_token);
- }
- } else {
- _token_list_append (substituted, node->token);
- }
- }
-
- /* After argument substitution, and before further expansion
- * below, implement token pasting. */
-
- _token_list_trim_trailing_space (substituted);
-
- node = substituted->head;
- while (node)
- {
- token_node_t *next_non_space;
-
- /* Look ahead for a PASTE token, skipping space. */
- next_non_space = node->next;
- while (next_non_space && next_non_space->token->type == SPACE)
- next_non_space = next_non_space->next;
-
- if (next_non_space == NULL)
- break;
-
- if (next_non_space->token->type != PASTE) {
- node = next_non_space;
- continue;
- }
-
- /* Now find the next non-space token after the PASTE. */
- next_non_space = next_non_space->next;
- while (next_non_space && next_non_space->token->type == SPACE)
- next_non_space = next_non_space->next;
-
- if (next_non_space == NULL) {
- yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
- return NULL;
- }
-
- node->token = _token_paste (parser, node->token, next_non_space->token);
- node->next = next_non_space->next;
- if (next_non_space == substituted->tail)
- substituted->tail = node;
-
- node = node->next;
- }
-
- substituted->non_space_tail = substituted->tail;
-
- return substituted;
-}
-
-/* Compute the complete expansion of node, (and subsequent nodes after
- * 'node' in the case that 'node' is a function-like macro and
- * subsequent nodes are arguments).
- *
- * Returns NULL if node is a simple token with no expansion.
- *
- * Otherwise, returns the token list that results from the expansion
- * and sets *last to the last node in the list that was consumed by
- * the expansion. Specifically, *last will be set as follows:
- *
- * As 'node' in the case of object-like macro expansion.
- *
- * As the token of the closing right parenthesis in the case of
- * function-like macro expansion.
- */
-static token_list_t *
-_glcpp_parser_expand_node (glcpp_parser_t *parser,
- token_node_t *node,
- token_node_t **last)
-{
- token_t *token = node->token;
- const char *identifier;
- macro_t *macro;
-
- /* We only expand identifiers */
- if (token->type != IDENTIFIER) {
- /* We change any COMMA into a COMMA_FINAL to prevent
- * it being mistaken for an argument separator
- * later. */
- if (token->type == ',') {
- token->type = COMMA_FINAL;
- token->value.ival = COMMA_FINAL;
- }
-
- return NULL;
- }
-
- /* Look up this identifier in the hash table. */
- identifier = token->value.str;
- macro = hash_table_find (parser->defines, identifier);
-
- /* Not a macro, so no expansion needed. */
- if (macro == NULL)
- return NULL;
-
- /* Finally, don't expand this macro if we're already actively
- * expanding it, (to avoid infinite recursion). */
- if (_active_list_contains (parser->active, identifier)) {
- /* We change the token type here from IDENTIFIER to
- * OTHER to prevent any future expansion of this
- * unexpanded token. */
- char *str;
- token_list_t *expansion;
- token_t *final;
-
- str = talloc_strdup (parser, token->value.str);
- final = _token_create_str (parser, OTHER, str);
- expansion = _token_list_create (parser);
- _token_list_append (expansion, final);
- *last = node;
- return expansion;
- }
-
- if (! macro->is_function)
- {
- *last = node;
-
- /* Replace a macro defined as empty with a SPACE token. */
- if (macro->replacements == NULL)
- return _token_list_create_with_one_space (parser);
-
- return _token_list_copy (parser, macro->replacements);
- }
-
- return _glcpp_parser_expand_function (parser, node, last);
-}
-
-/* Push a new identifier onto the active list, returning the new list.
- *
- * Here, 'marker' is the token node that appears in the list after the
- * expansion of 'identifier'. That is, when the list iterator begins
- * examinging 'marker', then it is time to pop this node from the
- * active stack.
- */
-active_list_t *
-_active_list_push (active_list_t *list,
- const char *identifier,
- token_node_t *marker)
-{
- active_list_t *node;
-
- node = talloc (list, active_list_t);
- node->identifier = talloc_strdup (node, identifier);
- node->marker = marker;
- node->next = list;
-
- return node;
-}
-
-active_list_t *
-_active_list_pop (active_list_t *list)
-{
- active_list_t *node = list;
-
- if (node == NULL)
- return NULL;
-
- node = list->next;
- talloc_free (list);
-
- return node;
-}
-
-int
-_active_list_contains (active_list_t *list, const char *identifier)
-{
- active_list_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list; node; node = node->next)
- if (strcmp (node->identifier, identifier) == 0)
- return 1;
-
- return 0;
-}
-
-/* Walk over the token list replacing nodes with their expansion.
- * Whenever nodes are expanded the walking will walk over the new
- * nodes, continuing to expand as necessary. The results are placed in
- * 'list' itself;
- */
-static void
-_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list)
-{
- token_node_t *node_prev;
- token_node_t *node, *last = NULL;
- token_list_t *expansion;
-
- if (list == NULL)
- return;
-
- _token_list_trim_trailing_space (list);
-
- node_prev = NULL;
- node = list->head;
-
- while (node) {
-
- while (parser->active && parser->active->marker == node)
- parser->active = _active_list_pop (parser->active);
-
- /* Find the expansion for node, which will replace all
- * nodes from node to last, inclusive. */
- expansion = _glcpp_parser_expand_node (parser, node, &last);
- if (expansion) {
- token_node_t *n;
-
- for (n = node; n != last->next; n = n->next)
- while (parser->active &&
- parser->active->marker == n)
- {
- parser->active = _active_list_pop (parser->active);
- }
-
- parser->active = _active_list_push (parser->active,
- node->token->value.str,
- last->next);
-
- /* Splice expansion into list, supporting a
- * simple deletion if the expansion is
- * empty. */
- if (expansion->head) {
- if (node_prev)
- node_prev->next = expansion->head;
- else
- list->head = expansion->head;
- expansion->tail->next = last->next;
- if (last == list->tail)
- list->tail = expansion->tail;
- } else {
- if (node_prev)
- node_prev->next = last->next;
- else
- list->head = last->next;
- if (last == list->tail)
- list->tail = NULL;
- }
- } else {
- node_prev = node;
- }
- node = node_prev ? node_prev->next : list->head;
- }
-
- while (parser->active)
- parser->active = _active_list_pop (parser->active);
-
- list->non_space_tail = list->tail;
-}
-
-void
-_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
- token_list_t *list)
-{
- if (list == NULL)
- return;
-
- _glcpp_parser_expand_token_list (parser, list);
-
- _token_list_trim_trailing_space (list);
-
- _token_list_print (parser, list);
-}
-
-static void
-_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *identifier)
-{
- /* According to the GLSL specification, macro names starting with "__"
- * or "GL_" are reserved for future use. So, don't allow them.
- */
- if (strncmp(identifier, "__", 2) == 0) {
- glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
- }
- if (strncmp(identifier, "GL_", 3) == 0) {
- glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
- }
-}
-
-static int
-_macro_equal (macro_t *a, macro_t *b)
-{
- if (a->is_function != b->is_function)
- return 0;
-
- if (a->is_function) {
- if (! _string_list_equal (a->parameters, b->parameters))
- return 0;
- }
-
- return _token_list_equal_ignoring_space (a->replacements,
- b->replacements);
-}
-
-void
-_define_object_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *identifier,
- token_list_t *replacements)
-{
- macro_t *macro, *previous;
-
- if (loc != NULL)
- _check_for_reserved_macro_name(parser, loc, identifier);
-
- macro = talloc (parser, macro_t);
-
- macro->is_function = 0;
- macro->parameters = NULL;
- macro->identifier = talloc_strdup (macro, identifier);
- macro->replacements = talloc_steal (macro, replacements);
-
- previous = hash_table_find (parser->defines, identifier);
- if (previous) {
- if (_macro_equal (macro, previous)) {
- talloc_free (macro);
- return;
- }
- glcpp_error (loc, parser, "Redefinition of macro %s\n",
- identifier);
- }
-
- hash_table_insert (parser->defines, macro, identifier);
-}
-
-void
-_define_function_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *identifier,
- string_list_t *parameters,
- token_list_t *replacements)
-{
- macro_t *macro, *previous;
-
- _check_for_reserved_macro_name(parser, loc, identifier);
-
- macro = talloc (parser, macro_t);
-
- macro->is_function = 1;
- macro->parameters = talloc_steal (macro, parameters);
- macro->identifier = talloc_strdup (macro, identifier);
- macro->replacements = talloc_steal (macro, replacements);
-
- previous = hash_table_find (parser->defines, identifier);
- if (previous) {
- if (_macro_equal (macro, previous)) {
- talloc_free (macro);
- return;
- }
- glcpp_error (loc, parser, "Redefinition of macro %s\n",
- identifier);
- }
-
- hash_table_insert (parser->defines, macro, identifier);
-}
-
-static int
-glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
-{
- token_node_t *node;
- int ret;
-
- if (parser->lex_from_list == NULL) {
- ret = glcpp_lex (yylval, yylloc, parser->scanner);
-
- /* XXX: This ugly block of code exists for the sole
- * purpose of converting a NEWLINE token into a SPACE
- * token, but only in the case where we have seen a
- * function-like macro name, but have not yet seen its
- * closing parenthesis.
- *
- * There's perhaps a more compact way to do this with
- * mid-rule actions in the grammar.
- *
- * I'm definitely not pleased with the complexity of
- * this code here.
- */
- if (parser->newline_as_space)
- {
- if (ret == '(') {
- parser->paren_count++;
- } else if (ret == ')') {
- parser->paren_count--;
- if (parser->paren_count == 0)
- parser->newline_as_space = 0;
- } else if (ret == NEWLINE) {
- ret = SPACE;
- } else if (ret != SPACE) {
- if (parser->paren_count == 0)
- parser->newline_as_space = 0;
- }
- }
- else if (parser->in_control_line)
- {
- if (ret == NEWLINE)
- parser->in_control_line = 0;
- }
- else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
- ret == HASH_UNDEF || ret == HASH_IF ||
- ret == HASH_IFDEF || ret == HASH_IFNDEF ||
- ret == HASH_ELIF || ret == HASH_ELSE ||
- ret == HASH_ENDIF || ret == HASH)
- {
- parser->in_control_line = 1;
- }
- else if (ret == IDENTIFIER)
- {
- macro_t *macro;
- macro = hash_table_find (parser->defines,
- yylval->str);
- if (macro && macro->is_function) {
- parser->newline_as_space = 1;
- parser->paren_count = 0;
- }
- }
-
- return ret;
- }
-
- node = parser->lex_from_node;
-
- if (node == NULL) {
- talloc_free (parser->lex_from_list);
- parser->lex_from_list = NULL;
- return NEWLINE;
- }
-
- *yylval = node->token->value;
- ret = node->token->type;
-
- parser->lex_from_node = node->next;
-
- return ret;
-}
-
-static void
-glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
-{
- token_node_t *node;
-
- assert (parser->lex_from_list == NULL);
-
- /* Copy list, eliminating any space tokens. */
- parser->lex_from_list = _token_list_create (parser);
-
- for (node = list->head; node; node = node->next) {
- if (node->token->type == SPACE)
- continue;
- _token_list_append (parser->lex_from_list, node->token);
- }
-
- talloc_free (list);
-
- parser->lex_from_node = parser->lex_from_list->head;
-
- /* It's possible the list consisted of nothing but whitespace. */
- if (parser->lex_from_node == NULL) {
- talloc_free (parser->lex_from_list);
- parser->lex_from_list = NULL;
- }
-}
-
-static void
-_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
- int condition)
-{
- skip_type_t current = SKIP_NO_SKIP;
- skip_node_t *node;
-
- if (parser->skip_stack)
- current = parser->skip_stack->type;
-
- node = talloc (parser, skip_node_t);
- node->loc = *loc;
-
- if (current == SKIP_NO_SKIP) {
- if (condition)
- node->type = SKIP_NO_SKIP;
- else
- node->type = SKIP_TO_ELSE;
- } else {
- node->type = SKIP_TO_ENDIF;
- }
-
- node->next = parser->skip_stack;
- parser->skip_stack = node;
-}
-
-static void
-_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *type, int condition)
-{
- if (parser->skip_stack == NULL) {
- glcpp_error (loc, parser, "%s without #if\n", type);
- return;
- }
-
- if (parser->skip_stack->type == SKIP_TO_ELSE) {
- if (condition)
- parser->skip_stack->type = SKIP_NO_SKIP;
- } else {
- parser->skip_stack->type = SKIP_TO_ENDIF;
- }
-}
-
-static void
-_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
-{
- skip_node_t *node;
-
- if (parser->skip_stack == NULL) {
- glcpp_error (loc, parser, "#endif without #if\n");
- return;
- }
-
- node = parser->skip_stack;
- parser->skip_stack = node->next;
- talloc_free (node);
-}
-
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "glcpp/glcpp-parse.y"
+
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.h"
+#include "main/core.h" /* for struct gl_extensions */
+#include "main/mtypes.h" /* for gl_api enum */
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+ stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ string_list_t *parameters,
+ token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static int
+_string_list_equal (string_list_t *a, string_list_t *b);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function calls talloc_steal on token. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+
+
+/* Line 189 of yacc.c */
+#line 220 "glcpp/glcpp-parse.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ COMMA_FINAL = 258,
+ DEFINED = 259,
+ ELIF_EXPANDED = 260,
+ HASH = 261,
+ HASH_DEFINE_FUNC = 262,
+ HASH_DEFINE_OBJ = 263,
+ HASH_ELIF = 264,
+ HASH_ELSE = 265,
+ HASH_ENDIF = 266,
+ HASH_IF = 267,
+ HASH_IFDEF = 268,
+ HASH_IFNDEF = 269,
+ HASH_UNDEF = 270,
+ HASH_VERSION = 271,
+ IDENTIFIER = 272,
+ IF_EXPANDED = 273,
+ INTEGER = 274,
+ INTEGER_STRING = 275,
+ NEWLINE = 276,
+ OTHER = 277,
+ PLACEHOLDER = 278,
+ SPACE = 279,
+ PASTE = 280,
+ OR = 281,
+ AND = 282,
+ NOT_EQUAL = 283,
+ EQUAL = 284,
+ GREATER_OR_EQUAL = 285,
+ LESS_OR_EQUAL = 286,
+ RIGHT_SHIFT = 287,
+ LEFT_SHIFT = 288,
+ UNARY = 289
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 308 "glcpp/glcpp-parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 606
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 57
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 17
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 101
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 162
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 289
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 47, 2, 2, 2, 43, 30, 2,
+ 45, 46, 41, 39, 49, 40, 54, 42, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 55,
+ 33, 56, 34, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 50, 2, 51, 29, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 52, 28, 53, 48, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 31, 32, 35, 36, 37, 38, 44
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 4, 7, 9, 11, 13, 16, 20,
+ 24, 29, 36, 44, 48, 52, 55, 60, 65, 69,
+ 72, 75, 78, 82, 85, 87, 89, 91, 95, 99,
+ 103, 107, 111, 115, 119, 123, 127, 131, 135, 139,
+ 143, 147, 151, 155, 159, 163, 166, 169, 172, 175,
+ 179, 181, 185, 187, 190, 193, 194, 196, 197, 199,
+ 202, 207, 209, 211, 214, 216, 219, 221, 223, 225,
+ 227, 229, 231, 233, 235, 237, 239, 241, 243, 245,
+ 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
+ 267, 269, 271, 273, 275, 277, 279, 281, 283, 285,
+ 287, 289
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 58, 0, -1, -1, 58, 59, -1, 61, -1, 65,
+ -1, 60, -1, 6, 66, -1, 18, 63, 21, -1,
+ 5, 63, 21, -1, 8, 17, 67, 21, -1, 7,
+ 17, 45, 46, 67, 21, -1, 7, 17, 45, 64,
+ 46, 67, 21, -1, 15, 17, 21, -1, 12, 70,
+ 21, -1, 12, 21, -1, 13, 17, 68, 21, -1,
+ 14, 17, 68, 21, -1, 9, 70, 21, -1, 9,
+ 21, -1, 10, 21, -1, 11, 21, -1, 16, 62,
+ 21, -1, 6, 21, -1, 20, -1, 19, -1, 62,
+ -1, 63, 26, 63, -1, 63, 27, 63, -1, 63,
+ 28, 63, -1, 63, 29, 63, -1, 63, 30, 63,
+ -1, 63, 31, 63, -1, 63, 32, 63, -1, 63,
+ 35, 63, -1, 63, 36, 63, -1, 63, 34, 63,
+ -1, 63, 33, 63, -1, 63, 37, 63, -1, 63,
+ 38, 63, -1, 63, 40, 63, -1, 63, 39, 63,
+ -1, 63, 43, 63, -1, 63, 42, 63, -1, 63,
+ 41, 63, -1, 47, 63, -1, 48, 63, -1, 40,
+ 63, -1, 39, 63, -1, 45, 63, 46, -1, 17,
+ -1, 64, 49, 17, -1, 21, -1, 71, 21, -1,
+ 71, 21, -1, -1, 71, -1, -1, 71, -1, 4,
+ 17, -1, 4, 45, 17, 46, -1, 72, -1, 69,
+ -1, 70, 69, -1, 72, -1, 71, 72, -1, 17,
+ -1, 20, -1, 73, -1, 22, -1, 24, -1, 50,
+ -1, 51, -1, 45, -1, 46, -1, 52, -1, 53,
+ -1, 54, -1, 30, -1, 41, -1, 39, -1, 40,
+ -1, 48, -1, 47, -1, 42, -1, 43, -1, 38,
+ -1, 37, -1, 33, -1, 34, -1, 36, -1, 35,
+ -1, 32, -1, 31, -1, 29, -1, 28, -1, 27,
+ -1, 26, -1, 55, -1, 49, -1, 56, -1, 25,
+ -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 185, 185, 187, 191, 194, 199, 200, 204, 207,
+ 213, 216, 219, 222, 230, 249, 259, 264, 269, 288,
+ 303, 306, 309, 330, 334, 343, 348, 349, 352, 355,
+ 358, 361, 364, 367, 370, 373, 376, 379, 382, 385,
+ 388, 391, 394, 397, 405, 408, 411, 414, 417, 420,
+ 426, 431, 439, 440, 444, 450, 451, 454, 456, 463,
+ 467, 471, 476, 480, 487, 492, 499, 503, 507, 511,
+ 515, 522, 523, 524, 525, 526, 527, 528, 529, 530,
+ 531, 532, 533, 534, 535, 536, 537, 538, 539, 540,
+ 541, 542, 543, 544, 545, 546, 547, 548, 549, 550,
+ 551, 552
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "COMMA_FINAL", "DEFINED",
+ "ELIF_EXPANDED", "HASH", "HASH_DEFINE_FUNC", "HASH_DEFINE_OBJ",
+ "HASH_ELIF", "HASH_ELSE", "HASH_ENDIF", "HASH_IF", "HASH_IFDEF",
+ "HASH_IFNDEF", "HASH_UNDEF", "HASH_VERSION", "IDENTIFIER", "IF_EXPANDED",
+ "INTEGER", "INTEGER_STRING", "NEWLINE", "OTHER", "PLACEHOLDER", "SPACE",
+ "PASTE", "OR", "AND", "'|'", "'^'", "'&'", "NOT_EQUAL", "EQUAL", "'<'",
+ "'>'", "GREATER_OR_EQUAL", "LESS_OR_EQUAL", "RIGHT_SHIFT", "LEFT_SHIFT",
+ "'+'", "'-'", "'*'", "'/'", "'%'", "UNARY", "'('", "')'", "'!'", "'~'",
+ "','", "'['", "']'", "'{'", "'}'", "'.'", "';'", "'='", "$accept",
+ "input", "line", "expanded_line", "control_line", "integer_constant",
+ "expression", "identifier_list", "text_line", "non_directive",
+ "replacement_list", "junk", "conditional_token", "conditional_tokens",
+ "pp_tokens", "preprocessing_token", "operator", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 124, 94,
+ 38, 283, 284, 60, 62, 285, 286, 287, 288, 43,
+ 45, 42, 47, 37, 289, 40, 41, 33, 126, 44,
+ 91, 93, 123, 125, 46, 59, 61
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 57, 58, 58, 59, 59, 59, 59, 60, 60,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 62, 62, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 64, 64, 65, 65, 66, 67, 67, 68, 68, 69,
+ 69, 69, 70, 70, 71, 71, 72, 72, 72, 72,
+ 72, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+ 73, 73
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 1, 2, 3, 3,
+ 4, 6, 7, 3, 3, 2, 4, 4, 3, 2,
+ 2, 2, 3, 2, 1, 1, 1, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 2, 2, 2, 2, 3,
+ 1, 3, 1, 2, 2, 0, 1, 0, 1, 2,
+ 4, 1, 1, 2, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 66, 0, 67, 52, 69,
+ 70, 101, 97, 96, 95, 94, 78, 93, 92, 88,
+ 89, 91, 90, 87, 86, 80, 81, 79, 84, 85,
+ 73, 74, 83, 82, 99, 71, 72, 75, 76, 77,
+ 98, 100, 3, 6, 4, 5, 0, 64, 68, 25,
+ 24, 0, 0, 0, 0, 0, 26, 0, 23, 7,
+ 0, 0, 55, 0, 19, 62, 0, 61, 20, 21,
+ 15, 0, 57, 57, 0, 0, 0, 53, 65, 48,
+ 47, 0, 45, 46, 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 56, 59, 0, 18,
+ 63, 14, 0, 58, 0, 13, 22, 8, 49, 27,
+ 28, 29, 30, 31, 32, 33, 37, 36, 34, 35,
+ 38, 39, 41, 40, 44, 43, 42, 50, 55, 0,
+ 10, 0, 16, 17, 0, 55, 0, 60, 11, 0,
+ 51, 12
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 52, 53, 54, 66, 67, 149, 55, 69,
+ 115, 122, 75, 76, 116, 57, 58
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -147
+static const yytype_int16 yypact[] =
+{
+ -147, 112, -147, 28, -10, 55, 62, 152, -15, 59,
+ 192, 85, 86, 87, 51, -147, 28, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+ -147, -147, -147, -147, -147, -147, 312, -147, -147, -147,
+ -147, 28, 28, 28, 28, 28, -147, 428, -147, -147,
+ 352, 63, 392, 17, -147, -147, 232, -147, -147, -147,
+ -147, 272, 392, 392, 84, 89, 451, -147, -147, -147,
+ -147, 469, -147, -147, -147, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, -147, 60, 90, 392, -147, 96, -147,
+ -147, -147, 93, 392, 94, -147, -147, -147, -147, 489,
+ 505, 520, 534, 547, 558, 558, 18, 18, 18, 18,
+ 563, 563, 23, 23, -147, -147, -147, -147, 392, 32,
+ -147, 61, -147, -147, 110, 392, 118, -147, -147, 149,
+ -147, -147
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -147, -147, -147, -147, -147, 157, -11, -147, -147, -147,
+ -146, 92, -68, 200, 0, -7, -147
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 77, 56, 154, 77, 70, 86, 78, 15, 120, 159,
+ 17, 68, 19, 120, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 117, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 59, 60, 88,
+ 89, 90, 91, 92, 93, 106, 107, 108, 109, 110,
+ 111, 112, 118, 88, 110, 111, 112, 61, 62, 77,
+ 59, 60, 71, 63, 77, 64, 65, 147, 155, 72,
+ 79, 156, 123, 123, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 82, 83, 84, 125, 148, 157, 114, 88,
+ 126, 150, 2, 151, 152, 153, 88, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 158, 17, 18, 19, 160, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 161, 85, 17, 74, 19, 124, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 81, 0, 17, 80, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 119, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 73, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 121, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 87, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 113, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 15,
+ 0, 0, 17, 0, 19, 0, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 0, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 94,
+ 0, 0, 0, 0, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 127, 0, 0, 0, 0, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 0, 0, 128, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 108, 109, 110, 111, 112
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 7, 1, 148, 10, 4, 16, 21, 17, 76, 155,
+ 20, 21, 22, 81, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 17, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 19, 20, 56,
+ 61, 62, 63, 64, 65, 37, 38, 39, 40, 41,
+ 42, 43, 45, 70, 41, 42, 43, 39, 40, 76,
+ 19, 20, 17, 45, 81, 47, 48, 17, 46, 17,
+ 21, 49, 82, 83, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 17, 17, 17, 21, 46, 46, 45, 116,
+ 21, 21, 0, 17, 21, 21, 123, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 21, 20, 21, 22, 17, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ 21, 14, 20, 21, 22, 83, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ 10, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 4, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, 21, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 17,
+ -1, -1, 20, -1, 22, -1, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, -1, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 21,
+ -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 21, -1, -1, -1, -1, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, -1, -1, 46, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 39, 40, 41, 42, 43
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 58, 0, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 20, 21, 22,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 59, 60, 61, 65, 71, 72, 73, 19,
+ 20, 39, 40, 45, 47, 48, 62, 63, 21, 66,
+ 71, 17, 17, 4, 21, 69, 70, 72, 21, 21,
+ 21, 70, 17, 17, 17, 62, 63, 21, 72, 63,
+ 63, 63, 63, 63, 21, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 21, 45, 67, 71, 17, 45, 21,
+ 69, 21, 68, 71, 68, 21, 21, 21, 46, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 17, 46, 64,
+ 21, 17, 21, 21, 67, 46, 49, 46, 21, 67,
+ 17, 21
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, parser, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, parser)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, parser); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (parser);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, glcpp_parser_t *parser)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, parser)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ glcpp_parser_t *parser;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , parser);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, parser); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, parser)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ glcpp_parser_t *parser;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (parser);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (glcpp_parser_t *parser);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (glcpp_parser_t *parser)
+#else
+int
+yyparse (parser)
+ glcpp_parser_t *parser;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[3];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+/* User initialization code. */
+
+/* Line 1251 of yacc.c */
+#line 152 "glcpp/glcpp-parse.y"
+{
+ yylloc.first_line = 1;
+ yylloc.first_column = 1;
+ yylloc.last_line = 1;
+ yylloc.last_column = 1;
+ yylloc.source = 0;
+}
+
+/* Line 1251 of yacc.c */
+#line 1622 "glcpp/glcpp-parse.c"
+ yylsp[0] = yylloc;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+
+/* Line 1464 of yacc.c */
+#line 191 "glcpp/glcpp-parse.y"
+ {
+ glcpp_print(parser->output, "\n");
+ ;}
+ break;
+
+ case 5:
+
+/* Line 1464 of yacc.c */
+#line 194 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_print_expanded_token_list (parser, (yyvsp[(1) - (1)].token_list));
+ glcpp_print(parser->output, "\n");
+ talloc_free ((yyvsp[(1) - (1)].token_list));
+ ;}
+ break;
+
+ case 8:
+
+/* Line 1464 of yacc.c */
+#line 204 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 9:
+
+/* Line 1464 of yacc.c */
+#line 207 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 10:
+
+/* Line 1464 of yacc.c */
+#line 213 "glcpp/glcpp-parse.y"
+ {
+ _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list));
+ ;}
+ break;
+
+ case 11:
+
+/* Line 1464 of yacc.c */
+#line 216 "glcpp/glcpp-parse.y"
+ {
+ _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list));
+ ;}
+ break;
+
+ case 12:
+
+/* Line 1464 of yacc.c */
+#line 219 "glcpp/glcpp-parse.y"
+ {
+ _define_function_macro (parser, & (yylsp[(2) - (7)]), (yyvsp[(2) - (7)].str), (yyvsp[(4) - (7)].string_list), (yyvsp[(6) - (7)].token_list));
+ ;}
+ break;
+
+ case 13:
+
+/* Line 1464 of yacc.c */
+#line 222 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (3)].str));
+ if (macro) {
+ hash_table_remove (parser->defines, (yyvsp[(2) - (3)].str));
+ talloc_free (macro);
+ }
+ talloc_free ((yyvsp[(2) - (3)].str));
+ ;}
+ break;
+
+ case 14:
+
+/* Line 1464 of yacc.c */
+#line 230 "glcpp/glcpp-parse.y"
+ {
+ /* Be careful to only evaluate the 'if' expression if
+ * we are not skipping. When we are skipping, we
+ * simply push a new 0-valued 'if' onto the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_if (parser, IF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), 0);
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+ ;}
+ break;
+
+ case 15:
+
+/* Line 1464 of yacc.c */
+#line 249 "glcpp/glcpp-parse.y"
+ {
+ /* #if without an expression is only an error if we
+ * are not skipping */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ glcpp_error(& (yylsp[(1) - (2)]), parser, "#if with no expression");
+ }
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (2)]), 0);
+ ;}
+ break;
+
+ case 16:
+
+/* Line 1464 of yacc.c */
+#line 259 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+ talloc_free ((yyvsp[(2) - (4)].str));
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro != NULL);
+ ;}
+ break;
+
+ case 17:
+
+/* Line 1464 of yacc.c */
+#line 264 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+ talloc_free ((yyvsp[(2) - (4)].str));
+ _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro == NULL);
+ ;}
+ break;
+
+ case 18:
+
+/* Line 1464 of yacc.c */
+#line 269 "glcpp/glcpp-parse.y"
+ {
+ /* Be careful to only evaluate the 'elif' expression
+ * if we are not skipping. When we are skipping, we
+ * simply change to a 0-valued 'elif' on the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ _glcpp_parser_expand_if (parser, ELIF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]),
+ "elif", 0);
+ }
+ ;}
+ break;
+
+ case 19:
+
+/* Line 1464 of yacc.c */
+#line 288 "glcpp/glcpp-parse.y"
+ {
+ /* #elif without an expression is an error unless we
+ * are skipping. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ glcpp_error(& (yylsp[(1) - (2)]), parser, "#elif with no expression");
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]),
+ "elif", 0);
+ glcpp_warning(& (yylsp[(1) - (2)]), parser, "ignoring illegal #elif without expression");
+ }
+ ;}
+ break;
+
+ case 20:
+
+/* Line 1464 of yacc.c */
+#line 303 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1);
+ ;}
+ break;
+
+ case 21:
+
+/* Line 1464 of yacc.c */
+#line 306 "glcpp/glcpp-parse.y"
+ {
+ _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)]));
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1464 of yacc.c */
+#line 309 "glcpp/glcpp-parse.y"
+ {
+ macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+ if (macro) {
+ hash_table_remove (parser->defines, "__VERSION__");
+ talloc_free (macro);
+ }
+ add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival));
+
+ if ((yyvsp[(2) - (3)].ival) == 100)
+ add_builtin_define (parser, "GL_ES", 1);
+
+ /* Currently, all ES2 implementations support highp in the
+ * fragment shader, so we always define this macro in ES2.
+ * If we ever get a driver that doesn't support highp, we'll
+ * need to add a flag to the gl_context and check that here.
+ */
+ if ((yyvsp[(2) - (3)].ival) >= 130 || (yyvsp[(2) - (3)].ival) == 100)
+ add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
+
+ glcpp_printf(parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival));
+ ;}
+ break;
+
+ case 24:
+
+/* Line 1464 of yacc.c */
+#line 334 "glcpp/glcpp-parse.y"
+ {
+ if (strlen ((yyvsp[(1) - (1)].str)) >= 3 && strncmp ((yyvsp[(1) - (1)].str), "0x", 2) == 0) {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str) + 2, NULL, 16);
+ } else if ((yyvsp[(1) - (1)].str)[0] == '0') {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 8);
+ } else {
+ (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 10);
+ }
+ ;}
+ break;
+
+ case 25:
+
+/* Line 1464 of yacc.c */
+#line 343 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (1)].ival);
+ ;}
+ break;
+
+ case 27:
+
+/* Line 1464 of yacc.c */
+#line 349 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 28:
+
+/* Line 1464 of yacc.c */
+#line 352 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 29:
+
+/* Line 1464 of yacc.c */
+#line 355 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 30:
+
+/* Line 1464 of yacc.c */
+#line 358 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 31:
+
+/* Line 1464 of yacc.c */
+#line 361 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 32:
+
+/* Line 1464 of yacc.c */
+#line 364 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 33:
+
+/* Line 1464 of yacc.c */
+#line 367 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 34:
+
+/* Line 1464 of yacc.c */
+#line 370 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 35:
+
+/* Line 1464 of yacc.c */
+#line 373 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 36:
+
+/* Line 1464 of yacc.c */
+#line 376 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 37:
+
+/* Line 1464 of yacc.c */
+#line 379 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 38:
+
+/* Line 1464 of yacc.c */
+#line 382 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 39:
+
+/* Line 1464 of yacc.c */
+#line 385 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 40:
+
+/* Line 1464 of yacc.c */
+#line 388 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 41:
+
+/* Line 1464 of yacc.c */
+#line 391 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 42:
+
+/* Line 1464 of yacc.c */
+#line 394 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 43:
+
+/* Line 1464 of yacc.c */
+#line 397 "glcpp/glcpp-parse.y"
+ {
+ if ((yyvsp[(3) - (3)].ival) == 0) {
+ yyerror (& (yylsp[(1) - (3)]), parser,
+ "division by 0 in preprocessor directive");
+ } else {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) / (yyvsp[(3) - (3)].ival);
+ }
+ ;}
+ break;
+
+ case 44:
+
+/* Line 1464 of yacc.c */
+#line 405 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival);
+ ;}
+ break;
+
+ case 45:
+
+/* Line 1464 of yacc.c */
+#line 408 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = ! (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 46:
+
+/* Line 1464 of yacc.c */
+#line 411 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = ~ (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 47:
+
+/* Line 1464 of yacc.c */
+#line 414 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = - (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 48:
+
+/* Line 1464 of yacc.c */
+#line 417 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = + (yyvsp[(2) - (2)].ival);
+ ;}
+ break;
+
+ case 49:
+
+/* Line 1464 of yacc.c */
+#line 420 "glcpp/glcpp-parse.y"
+ {
+ (yyval.ival) = (yyvsp[(2) - (3)].ival);
+ ;}
+ break;
+
+ case 50:
+
+/* Line 1464 of yacc.c */
+#line 426 "glcpp/glcpp-parse.y"
+ {
+ (yyval.string_list) = _string_list_create (parser);
+ _string_list_append_item ((yyval.string_list), (yyvsp[(1) - (1)].str));
+ talloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str));
+ ;}
+ break;
+
+ case 51:
+
+/* Line 1464 of yacc.c */
+#line 431 "glcpp/glcpp-parse.y"
+ {
+ (yyval.string_list) = (yyvsp[(1) - (3)].string_list);
+ _string_list_append_item ((yyval.string_list), (yyvsp[(3) - (3)].str));
+ talloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str));
+ ;}
+ break;
+
+ case 52:
+
+/* Line 1464 of yacc.c */
+#line 439 "glcpp/glcpp-parse.y"
+ { (yyval.token_list) = NULL; ;}
+ break;
+
+ case 54:
+
+/* Line 1464 of yacc.c */
+#line 444 "glcpp/glcpp-parse.y"
+ {
+ yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #");
+ ;}
+ break;
+
+ case 55:
+
+/* Line 1464 of yacc.c */
+#line 450 "glcpp/glcpp-parse.y"
+ { (yyval.token_list) = NULL; ;}
+ break;
+
+ case 58:
+
+/* Line 1464 of yacc.c */
+#line 456 "glcpp/glcpp-parse.y"
+ {
+ glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive");
+ ;}
+ break;
+
+ case 59:
+
+/* Line 1464 of yacc.c */
+#line 463 "glcpp/glcpp-parse.y"
+ {
+ int v = hash_table_find (parser->defines, (yyvsp[(2) - (2)].str)) ? 1 : 0;
+ (yyval.token) = _token_create_ival (parser, INTEGER, v);
+ ;}
+ break;
+
+ case 60:
+
+/* Line 1464 of yacc.c */
+#line 467 "glcpp/glcpp-parse.y"
+ {
+ int v = hash_table_find (parser->defines, (yyvsp[(3) - (4)].str)) ? 1 : 0;
+ (yyval.token) = _token_create_ival (parser, INTEGER, v);
+ ;}
+ break;
+
+ case 62:
+
+/* Line 1464 of yacc.c */
+#line 476 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token_list) = _token_list_create (parser);
+ _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+ ;}
+ break;
+
+ case 63:
+
+/* Line 1464 of yacc.c */
+#line 480 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+ _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+ ;}
+ break;
+
+ case 64:
+
+/* Line 1464 of yacc.c */
+#line 487 "glcpp/glcpp-parse.y"
+ {
+ parser->space_tokens = 1;
+ (yyval.token_list) = _token_list_create (parser);
+ _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+ ;}
+ break;
+
+ case 65:
+
+/* Line 1464 of yacc.c */
+#line 492 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+ _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+ ;}
+ break;
+
+ case 66:
+
+/* Line 1464 of yacc.c */
+#line 499 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 67:
+
+/* Line 1464 of yacc.c */
+#line 503 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 68:
+
+/* Line 1464 of yacc.c */
+#line 507 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 69:
+
+/* Line 1464 of yacc.c */
+#line 511 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str));
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 70:
+
+/* Line 1464 of yacc.c */
+#line 515 "glcpp/glcpp-parse.y"
+ {
+ (yyval.token) = _token_create_ival (parser, SPACE, SPACE);
+ (yyval.token)->location = yylloc;
+ ;}
+ break;
+
+ case 71:
+
+/* Line 1464 of yacc.c */
+#line 522 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '['; ;}
+ break;
+
+ case 72:
+
+/* Line 1464 of yacc.c */
+#line 523 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ']'; ;}
+ break;
+
+ case 73:
+
+/* Line 1464 of yacc.c */
+#line 524 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '('; ;}
+ break;
+
+ case 74:
+
+/* Line 1464 of yacc.c */
+#line 525 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ')'; ;}
+ break;
+
+ case 75:
+
+/* Line 1464 of yacc.c */
+#line 526 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '{'; ;}
+ break;
+
+ case 76:
+
+/* Line 1464 of yacc.c */
+#line 527 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '}'; ;}
+ break;
+
+ case 77:
+
+/* Line 1464 of yacc.c */
+#line 528 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '.'; ;}
+ break;
+
+ case 78:
+
+/* Line 1464 of yacc.c */
+#line 529 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '&'; ;}
+ break;
+
+ case 79:
+
+/* Line 1464 of yacc.c */
+#line 530 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '*'; ;}
+ break;
+
+ case 80:
+
+/* Line 1464 of yacc.c */
+#line 531 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '+'; ;}
+ break;
+
+ case 81:
+
+/* Line 1464 of yacc.c */
+#line 532 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '-'; ;}
+ break;
+
+ case 82:
+
+/* Line 1464 of yacc.c */
+#line 533 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '~'; ;}
+ break;
+
+ case 83:
+
+/* Line 1464 of yacc.c */
+#line 534 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '!'; ;}
+ break;
+
+ case 84:
+
+/* Line 1464 of yacc.c */
+#line 535 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '/'; ;}
+ break;
+
+ case 85:
+
+/* Line 1464 of yacc.c */
+#line 536 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '%'; ;}
+ break;
+
+ case 86:
+
+/* Line 1464 of yacc.c */
+#line 537 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = LEFT_SHIFT; ;}
+ break;
+
+ case 87:
+
+/* Line 1464 of yacc.c */
+#line 538 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = RIGHT_SHIFT; ;}
+ break;
+
+ case 88:
+
+/* Line 1464 of yacc.c */
+#line 539 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '<'; ;}
+ break;
+
+ case 89:
+
+/* Line 1464 of yacc.c */
+#line 540 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '>'; ;}
+ break;
+
+ case 90:
+
+/* Line 1464 of yacc.c */
+#line 541 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = LESS_OR_EQUAL; ;}
+ break;
+
+ case 91:
+
+/* Line 1464 of yacc.c */
+#line 542 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = GREATER_OR_EQUAL; ;}
+ break;
+
+ case 92:
+
+/* Line 1464 of yacc.c */
+#line 543 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = EQUAL; ;}
+ break;
+
+ case 93:
+
+/* Line 1464 of yacc.c */
+#line 544 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = NOT_EQUAL; ;}
+ break;
+
+ case 94:
+
+/* Line 1464 of yacc.c */
+#line 545 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '^'; ;}
+ break;
+
+ case 95:
+
+/* Line 1464 of yacc.c */
+#line 546 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '|'; ;}
+ break;
+
+ case 96:
+
+/* Line 1464 of yacc.c */
+#line 547 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = AND; ;}
+ break;
+
+ case 97:
+
+/* Line 1464 of yacc.c */
+#line 548 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = OR; ;}
+ break;
+
+ case 98:
+
+/* Line 1464 of yacc.c */
+#line 549 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ';'; ;}
+ break;
+
+ case 99:
+
+/* Line 1464 of yacc.c */
+#line 550 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = ','; ;}
+ break;
+
+ case 100:
+
+/* Line 1464 of yacc.c */
+#line 551 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = '='; ;}
+ break;
+
+ case 101:
+
+/* Line 1464 of yacc.c */
+#line 552 "glcpp/glcpp-parse.y"
+ { (yyval.ival) = PASTE; ;}
+ break;
+
+
+
+/* Line 1464 of yacc.c */
+#line 2661 "glcpp/glcpp-parse.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, parser, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, parser, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, parser, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[1] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, parser);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[1] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[1] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, parser);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+ yyerror_range[2] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, parser, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, parser);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, parser);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1684 of yacc.c */
+#line 555 "glcpp/glcpp-parse.y"
+
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = talloc (ctx, string_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = talloc (list, string_node_t);
+ node->str = talloc_strdup (node, str);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+ string_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0, node = list->head; node; i++, node = node->next) {
+ if (strcmp (node->str, member) == 0) {
+ if (index)
+ *index = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+ int length = 0;
+ string_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+int
+_string_list_equal (string_list_t *a, string_list_t *b)
+{
+ string_node_t *node_a, *node_b;
+
+ if (a == NULL && b == NULL)
+ return 1;
+
+ if (a == NULL || b == NULL)
+ return 0;
+
+ for (node_a = a->head, node_b = b->head;
+ node_a && node_b;
+ node_a = node_a->next, node_b = node_b->next)
+ {
+ if (strcmp (node_a->str, node_b->str))
+ return 0;
+ }
+
+ /* Catch the case of lists being different lengths, (which
+ * would cause the loop above to terminate after the shorter
+ * list). */
+ return node_a == node_b;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+ argument_list_t *list;
+
+ list = talloc (ctx, argument_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+ argument_node_t *node;
+
+ node = talloc (list, argument_node_t);
+ node->argument = argument;
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+ int length = 0;
+ argument_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+ argument_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return NULL;
+
+ node = list->head;
+ for (i = 0; i < index; i++) {
+ node = node->next;
+ if (node == NULL)
+ break;
+ }
+
+ if (node)
+ return node->argument;
+
+ return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.str = talloc_steal (token, str);
+
+ return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.ival = ival;
+
+ return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+ token_list_t *list;
+
+ list = talloc (ctx, token_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+ list->non_space_tail = NULL;
+
+ return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+ token_node_t *node;
+
+ node = talloc (list, token_node_t);
+ node->token = talloc_steal (list, token);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+ if (token->type != SPACE)
+ list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+ if (tail == NULL || tail->head == NULL)
+ return;
+
+ if (list->head == NULL) {
+ list->head = tail->head;
+ } else {
+ list->tail->next = tail->head;
+ }
+
+ list->tail = tail->tail;
+ list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+ token_list_t *copy;
+ token_node_t *node;
+
+ if (other == NULL)
+ return NULL;
+
+ copy = _token_list_create (ctx);
+ for (node = other->head; node; node = node->next) {
+ token_t *new_token = talloc (copy, token_t);
+ *new_token = *node->token;
+ _token_list_append (copy, new_token);
+ }
+
+ return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+ token_node_t *tail, *next;
+
+ if (list->non_space_tail) {
+ tail = list->non_space_tail->next;
+ list->non_space_tail->next = NULL;
+ list->tail = list->non_space_tail;
+
+ while (tail) {
+ next = tail->next;
+ talloc_free (tail);
+ tail = next;
+ }
+ }
+}
+
+int
+_token_list_is_empty_ignoring_space (token_list_t *l)
+{
+ token_node_t *n;
+
+ if (l == NULL)
+ return 1;
+
+ n = l->head;
+ while (n != NULL && n->token->type == SPACE)
+ n = n->next;
+
+ return n == NULL;
+}
+
+int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
+{
+ token_node_t *node_a, *node_b;
+
+ if (a == NULL || b == NULL) {
+ int a_empty = _token_list_is_empty_ignoring_space(a);
+ int b_empty = _token_list_is_empty_ignoring_space(b);
+ return a_empty == b_empty;
+ }
+
+ node_a = a->head;
+ node_b = b->head;
+
+ while (1)
+ {
+ if (node_a == NULL && node_b == NULL)
+ break;
+
+ if (node_a == NULL || node_b == NULL)
+ return 0;
+
+ if (node_a->token->type == SPACE) {
+ node_a = node_a->next;
+ continue;
+ }
+
+ if (node_b->token->type == SPACE) {
+ node_b = node_b->next;
+ continue;
+ }
+
+ if (node_a->token->type != node_b->token->type)
+ return 0;
+
+ switch (node_a->token->type) {
+ case INTEGER:
+ if (node_a->token->value.ival !=
+ node_b->token->value.ival)
+ {
+ return 0;
+ }
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ if (strcmp (node_a->token->value.str,
+ node_b->token->value.str))
+ {
+ return 0;
+ }
+ break;
+ }
+
+ node_a = node_a->next;
+ node_b = node_b->next;
+ }
+
+ return 1;
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+ if (token->type < 256) {
+ glcpp_printf (*out, "%c", token->type);
+ return;
+ }
+
+ switch (token->type) {
+ case INTEGER:
+ glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ glcpp_print (*out, token->value.str);
+ break;
+ case SPACE:
+ glcpp_print (*out, " ");
+ break;
+ case LEFT_SHIFT:
+ glcpp_print (*out, "<<");
+ break;
+ case RIGHT_SHIFT:
+ glcpp_print (*out, ">>");
+ break;
+ case LESS_OR_EQUAL:
+ glcpp_print (*out, "<=");
+ break;
+ case GREATER_OR_EQUAL:
+ glcpp_print (*out, ">=");
+ break;
+ case EQUAL:
+ glcpp_print (*out, "==");
+ break;
+ case NOT_EQUAL:
+ glcpp_print (*out, "!=");
+ break;
+ case AND:
+ glcpp_print (*out, "&&");
+ break;
+ case OR:
+ glcpp_print (*out, "||");
+ break;
+ case PASTE:
+ glcpp_print (*out, "##");
+ break;
+ case COMMA_FINAL:
+ glcpp_print (*out, ",");
+ break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
+ default:
+ assert(!"Error: Don't know how to print token.");
+ break;
+ }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+ token_t *combined = NULL;
+
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return token;
+
+ /* When 'token' is a placeholder, just return 'other'. */
+ if (token->type == PLACEHOLDER)
+ return other;
+
+ /* A very few single-character punctuators can be combined
+ * with another to form a multi-character punctuator. */
+ switch (token->type) {
+ case '<':
+ if (other->type == '<')
+ combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+ break;
+ case '>':
+ if (other->type == '>')
+ combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+ break;
+ case '=':
+ if (other->type == '=')
+ combined = _token_create_ival (token, EQUAL, EQUAL);
+ break;
+ case '!':
+ if (other->type == '=')
+ combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+ break;
+ case '&':
+ if (other->type == '&')
+ combined = _token_create_ival (token, AND, AND);
+ break;
+ case '|':
+ if (other->type == '|')
+ combined = _token_create_ival (token, OR, OR);
+ break;
+ }
+
+ if (combined != NULL) {
+ /* Inherit the location from the first token */
+ combined->location = token->location;
+ return combined;
+ }
+
+ /* Two string-valued tokens can usually just be mashed
+ * together.
+ *
+ * XXX: This isn't actually legitimate. Several things here
+ * should result in a diagnostic since the result cannot be a
+ * valid, single pre-processing token. For example, pasting
+ * "123" and "abc" is not legal, but we don't catch that
+ * here. */
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+ {
+ char *str;
+
+ str = talloc_asprintf (token, "%s%s", token->value.str,
+ other->value.str);
+ combined = _token_create_str (token, token->type, str);
+ combined->location = token->location;
+ return combined;
+ }
+
+ glcpp_error (&token->location, parser, "");
+ glcpp_print (parser->info_log, "Pasting \"");
+ _token_print (&parser->info_log, token);
+ glcpp_print (parser->info_log, "\" and \"");
+ _token_print (&parser->info_log, other);
+ glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+ return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ if (list == NULL)
+ return;
+
+ for (node = list->head; node; node = node->next)
+ _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+ glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+ const char *name, int value)
+{
+ token_t *tok;
+ token_list_t *list;
+
+ tok = _token_create_ival (parser, INTEGER, value);
+
+ list = _token_list_create(parser);
+ _token_list_append(list, tok);
+ _define_object_macro(parser, NULL, name, list);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions, int api)
+{
+ glcpp_parser_t *parser;
+ int language_version;
+
+ parser = talloc (NULL, glcpp_parser_t);
+
+ glcpp_lex_init_extra (parser, &parser->scanner);
+ parser->defines = hash_table_ctor (32, hash_table_string_hash,
+ hash_table_string_compare);
+ parser->active = NULL;
+ parser->lexing_if = 0;
+ parser->space_tokens = 1;
+ parser->newline_as_space = 0;
+ parser->in_control_line = 0;
+ parser->paren_count = 0;
+
+ parser->skip_stack = NULL;
+
+ parser->lex_from_list = NULL;
+ parser->lex_from_node = NULL;
+
+ parser->output = talloc_strdup(parser, "");
+ parser->info_log = talloc_strdup(parser, "");
+ parser->error = 0;
+
+ /* Add pre-defined macros. */
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (api == API_OPENGLES2)
+ add_builtin_define(parser, "GL_ES", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array) {
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+ }
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+
+ if (extensions->ARB_explicit_attrib_location)
+ add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+ if (extensions->AMD_conservative_depth)
+ add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
+ }
+
+ language_version = 110;
+ add_builtin_define(parser, "__VERSION__", language_version);
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ glcpp_lex_destroy (parser->scanner);
+ hash_table_dtor (parser->defines);
+ talloc_free (parser);
+}
+
+typedef enum function_status
+{
+ FUNCTION_STATUS_SUCCESS,
+ FUNCTION_NOT_A_FUNCTION,
+ FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ * FUNCTION_STATUS_SUCCESS:
+ *
+ * Successfully parsed a set of function arguments.
+ *
+ * FUNCTION_NOT_A_FUNCTION:
+ *
+ * Macro name not followed by a '('. This is not an error, but
+ * simply that the macro name should be treated as a non-macro.
+ *
+ * FUNCTION_UNBALANCED_PARENTHESES
+ *
+ * Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_list_t *argument;
+ int paren_count;
+
+ node = node->next;
+
+ /* Ignore whitespace before first parenthesis. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != '(')
+ return FUNCTION_NOT_A_FUNCTION;
+
+ node = node->next;
+
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+
+ for (paren_count = 1; node; node = node->next) {
+ if (node->token->type == '(')
+ {
+ paren_count++;
+ }
+ else if (node->token->type == ')')
+ {
+ paren_count--;
+ if (paren_count == 0)
+ break;
+ }
+
+ if (node->token->type == ',' &&
+ paren_count == 1)
+ {
+ _token_list_trim_trailing_space (argument);
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ else {
+ if (argument->head == NULL) {
+ /* Don't treat initial whitespace as
+ * part of the arguement. */
+ if (node->token->type == SPACE)
+ continue;
+ }
+ _token_list_append (argument, node->token);
+ }
+ }
+
+ if (paren_count)
+ return FUNCTION_UNBALANCED_PARENTHESES;
+
+ *last = node;
+
+ return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, type, type);
+ _token_list_append (expanded, token);
+ _glcpp_parser_expand_token_list (parser, list);
+ _token_list_append_list (expanded, list);
+ glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+
+{
+ macro_t *macro;
+ const char *identifier;
+ argument_list_t *arguments;
+ function_status_t status;
+ token_list_t *substituted;
+ int parameter_index;
+
+ identifier = node->token->value.str;
+
+ macro = hash_table_find (parser->defines, identifier);
+
+ assert (macro->is_function);
+
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node, last);
+
+ switch (status) {
+ case FUNCTION_STATUS_SUCCESS:
+ break;
+ case FUNCTION_NOT_A_FUNCTION:
+ return NULL;
+ case FUNCTION_UNBALANCED_PARENTHESES:
+ glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+ return NULL;
+ }
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return _token_list_create_with_one_space (parser);
+ }
+
+ if (! ((_argument_list_length (arguments) ==
+ _string_list_length (macro->parameters)) ||
+ (_string_list_length (macro->parameters) == 0 &&
+ _argument_list_length (arguments) == 1 &&
+ arguments->head->argument->head == NULL)))
+ {
+ glcpp_error (&node->token->location, parser,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return NULL;
+ }
+
+ /* Perform argument substitution on the replacement list. */
+ substituted = _token_list_create (arguments);
+
+ for (node = macro->replacements->head; node; node = node->next)
+ {
+ if (node->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ node->token->value.str,
+ &parameter_index))
+ {
+ token_list_t *argument;
+ argument = _argument_list_member_at (arguments,
+ parameter_index);
+ /* Before substituting, we expand the argument
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ token_list_t *expanded_argument;
+ expanded_argument = _token_list_copy (parser,
+ argument);
+ _glcpp_parser_expand_token_list (parser,
+ expanded_argument);
+ _token_list_append_list (substituted,
+ expanded_argument);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
+ } else {
+ _token_list_append (substituted, node->token);
+ }
+ }
+
+ /* After argument substitution, and before further expansion
+ * below, implement token pasting. */
+
+ _token_list_trim_trailing_space (substituted);
+
+ node = substituted->head;
+ while (node)
+ {
+ token_node_t *next_non_space;
+
+ /* Look ahead for a PASTE token, skipping space. */
+ next_non_space = node->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL)
+ break;
+
+ if (next_non_space->token->type != PASTE) {
+ node = next_non_space;
+ continue;
+ }
+
+ /* Now find the next non-space token after the PASTE. */
+ next_non_space = next_non_space->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL) {
+ yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+ return NULL;
+ }
+
+ node->token = _token_paste (parser, node->token, next_non_space->token);
+ node->next = next_non_space->next;
+ if (next_non_space == substituted->tail)
+ substituted->tail = node;
+
+ node = node->next;
+ }
+
+ substituted->non_space_tail = substituted->tail;
+
+ return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ * As 'node' in the case of object-like macro expansion.
+ *
+ * As the token of the closing right parenthesis in the case of
+ * function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_t *token = node->token;
+ const char *identifier;
+ macro_t *macro;
+
+ /* We only expand identifiers */
+ if (token->type != IDENTIFIER) {
+ /* We change any COMMA into a COMMA_FINAL to prevent
+ * it being mistaken for an argument separator
+ * later. */
+ if (token->type == ',') {
+ token->type = COMMA_FINAL;
+ token->value.ival = COMMA_FINAL;
+ }
+
+ return NULL;
+ }
+
+ /* Look up this identifier in the hash table. */
+ identifier = token->value.str;
+ macro = hash_table_find (parser->defines, identifier);
+
+ /* Not a macro, so no expansion needed. */
+ if (macro == NULL)
+ return NULL;
+
+ /* Finally, don't expand this macro if we're already actively
+ * expanding it, (to avoid infinite recursion). */
+ if (_active_list_contains (parser->active, identifier)) {
+ /* We change the token type here from IDENTIFIER to
+ * OTHER to prevent any future expansion of this
+ * unexpanded token. */
+ char *str;
+ token_list_t *expansion;
+ token_t *final;
+
+ str = talloc_strdup (parser, token->value.str);
+ final = _token_create_str (parser, OTHER, str);
+ expansion = _token_list_create (parser);
+ _token_list_append (expansion, final);
+ *last = node;
+ return expansion;
+ }
+
+ if (! macro->is_function)
+ {
+ *last = node;
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL)
+ return _token_list_create_with_one_space (parser);
+
+ return _token_list_copy (parser, macro->replacements);
+ }
+
+ return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker)
+{
+ active_list_t *node;
+
+ node = talloc (list, active_list_t);
+ node->identifier = talloc_strdup (node, identifier);
+ node->marker = marker;
+ node->next = list;
+
+ return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+ active_list_t *node = list;
+
+ if (node == NULL)
+ return NULL;
+
+ node = list->next;
+ talloc_free (list);
+
+ return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+ active_list_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list; node; node = node->next)
+ if (strcmp (node->identifier, identifier) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node_prev;
+ token_node_t *node, *last = NULL;
+ token_list_t *expansion;
+
+ if (list == NULL)
+ return;
+
+ _token_list_trim_trailing_space (list);
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ while (parser->active && parser->active->marker == node)
+ parser->active = _active_list_pop (parser->active);
+
+ /* Find the expansion for node, which will replace all
+ * nodes from node to last, inclusive. */
+ expansion = _glcpp_parser_expand_node (parser, node, &last);
+ if (expansion) {
+ token_node_t *n;
+
+ for (n = node; n != last->next; n = n->next)
+ while (parser->active &&
+ parser->active->marker == n)
+ {
+ parser->active = _active_list_pop (parser->active);
+ }
+
+ parser->active = _active_list_push (parser->active,
+ node->token->value.str,
+ last->next);
+
+ /* Splice expansion into list, supporting a
+ * simple deletion if the expansion is
+ * empty. */
+ if (expansion->head) {
+ if (node_prev)
+ node_prev->next = expansion->head;
+ else
+ list->head = expansion->head;
+ expansion->tail->next = last->next;
+ if (last == list->tail)
+ list->tail = expansion->tail;
+ } else {
+ if (node_prev)
+ node_prev->next = last->next;
+ else
+ list->head = last->next;
+ if (last == list->tail)
+ list->tail = NULL;
+ }
+ } else {
+ node_prev = node;
+ }
+ node = node_prev ? node_prev->next : list->head;
+ }
+
+ while (parser->active)
+ parser->active = _active_list_pop (parser->active);
+
+ list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ if (list == NULL)
+ return;
+
+ _glcpp_parser_expand_token_list (parser, list);
+
+ _token_list_trim_trailing_space (list);
+
+ _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *identifier)
+{
+ /* According to the GLSL specification, macro names starting with "__"
+ * or "GL_" are reserved for future use. So, don't allow them.
+ */
+ if (strncmp(identifier, "__", 2) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+ }
+ if (strncmp(identifier, "GL_", 3) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+ }
+}
+
+static int
+_macro_equal (macro_t *a, macro_t *b)
+{
+ if (a->is_function != b->is_function)
+ return 0;
+
+ if (a->is_function) {
+ if (! _string_list_equal (a->parameters, b->parameters))
+ return 0;
+ }
+
+ return _token_list_equal_ignoring_space (a->replacements,
+ b->replacements);
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ if (loc != NULL)
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 0;
+ macro->parameters = NULL;
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ talloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ string_list_t *parameters,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 1;
+ macro->parameters = talloc_steal (macro, parameters);
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ talloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+ token_node_t *node;
+ int ret;
+
+ if (parser->lex_from_list == NULL) {
+ ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+ /* XXX: This ugly block of code exists for the sole
+ * purpose of converting a NEWLINE token into a SPACE
+ * token, but only in the case where we have seen a
+ * function-like macro name, but have not yet seen its
+ * closing parenthesis.
+ *
+ * There's perhaps a more compact way to do this with
+ * mid-rule actions in the grammar.
+ *
+ * I'm definitely not pleased with the complexity of
+ * this code here.
+ */
+ if (parser->newline_as_space)
+ {
+ if (ret == '(') {
+ parser->paren_count++;
+ } else if (ret == ')') {
+ parser->paren_count--;
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ } else if (ret == NEWLINE) {
+ ret = SPACE;
+ } else if (ret != SPACE) {
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ }
+ }
+ else if (parser->in_control_line)
+ {
+ if (ret == NEWLINE)
+ parser->in_control_line = 0;
+ }
+ else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+ ret == HASH_UNDEF || ret == HASH_IF ||
+ ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+ ret == HASH_ELIF || ret == HASH_ELSE ||
+ ret == HASH_ENDIF || ret == HASH)
+ {
+ parser->in_control_line = 1;
+ }
+ else if (ret == IDENTIFIER)
+ {
+ macro_t *macro;
+ macro = hash_table_find (parser->defines,
+ yylval->str);
+ if (macro && macro->is_function) {
+ parser->newline_as_space = 1;
+ parser->paren_count = 0;
+ }
+ }
+
+ return ret;
+ }
+
+ node = parser->lex_from_node;
+
+ if (node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ return NEWLINE;
+ }
+
+ *yylval = node->token->value;
+ ret = node->token->type;
+
+ parser->lex_from_node = node->next;
+
+ return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ assert (parser->lex_from_list == NULL);
+
+ /* Copy list, eliminating any space tokens. */
+ parser->lex_from_list = _token_list_create (parser);
+
+ for (node = list->head; node; node = node->next) {
+ if (node->token->type == SPACE)
+ continue;
+ _token_list_append (parser->lex_from_list, node->token);
+ }
+
+ talloc_free (list);
+
+ parser->lex_from_node = parser->lex_from_list->head;
+
+ /* It's possible the list consisted of nothing but whitespace. */
+ if (parser->lex_from_node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition)
+{
+ skip_type_t current = SKIP_NO_SKIP;
+ skip_node_t *node;
+
+ if (parser->skip_stack)
+ current = parser->skip_stack->type;
+
+ node = talloc (parser, skip_node_t);
+ node->loc = *loc;
+
+ if (current == SKIP_NO_SKIP) {
+ if (condition)
+ node->type = SKIP_NO_SKIP;
+ else
+ node->type = SKIP_TO_ELSE;
+ } else {
+ node->type = SKIP_TO_ENDIF;
+ }
+
+ node->next = parser->skip_stack;
+ parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition)
+{
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "%s without #if\n", type);
+ return;
+ }
+
+ if (parser->skip_stack->type == SKIP_TO_ELSE) {
+ if (condition)
+ parser->skip_stack->type = SKIP_NO_SKIP;
+ } else {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+ skip_node_t *node;
+
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "#endif without #if\n");
+ return;
+ }
+
+ node = parser->skip_stack;
+ parser->skip_stack = node->next;
+ talloc_free (node);
+}
+
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index a64d6691c..b449eb288 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -1,1888 +1,1890 @@
-%{
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#include "glcpp.h"
-#include "main/core.h" /* for struct gl_extensions */
-#include "main/mtypes.h" /* for gl_api enum */
-
-#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
-#define glcpp_printf(stream, fmt, args, ...) \
- stream = talloc_asprintf_append(stream, fmt, args)
-
-static void
-yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
-
-static void
-_define_object_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *macro,
- token_list_t *replacements);
-
-static void
-_define_function_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *macro,
- string_list_t *parameters,
- token_list_t *replacements);
-
-static string_list_t *
-_string_list_create (void *ctx);
-
-static void
-_string_list_append_item (string_list_t *list, const char *str);
-
-static int
-_string_list_contains (string_list_t *list, const char *member, int *index);
-
-static int
-_string_list_length (string_list_t *list);
-
-static int
-_string_list_equal (string_list_t *a, string_list_t *b);
-
-static argument_list_t *
-_argument_list_create (void *ctx);
-
-static void
-_argument_list_append (argument_list_t *list, token_list_t *argument);
-
-static int
-_argument_list_length (argument_list_t *list);
-
-static token_list_t *
-_argument_list_member_at (argument_list_t *list, int index);
-
-/* Note: This function talloc_steal()s the str pointer. */
-static token_t *
-_token_create_str (void *ctx, int type, char *str);
-
-static token_t *
-_token_create_ival (void *ctx, int type, int ival);
-
-static token_list_t *
-_token_list_create (void *ctx);
-
-/* Note: This function calls talloc_steal on token. */
-static void
-_token_list_append (token_list_t *list, token_t *token);
-
-static void
-_token_list_append_list (token_list_t *list, token_list_t *tail);
-
-static int
-_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
-
-static active_list_t *
-_active_list_push (active_list_t *list,
- const char *identifier,
- token_node_t *marker);
-
-static active_list_t *
-_active_list_pop (active_list_t *list);
-
-int
-_active_list_contains (active_list_t *list, const char *identifier);
-
-static void
-_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
-
-static void
-_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list);
-
-static void
-_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
- token_list_t *list);
-
-static void
-_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
- int condition);
-
-static void
-_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *type, int condition);
-
-static void
-_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
-
-#define yylex glcpp_parser_lex
-
-static int
-glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
-
-static void
-glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
-
-static void
-add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
-
-%}
-
-%pure-parser
-%error-verbose
-
-%locations
-%initial-action {
- @$.first_line = 1;
- @$.first_column = 1;
- @$.last_line = 1;
- @$.last_column = 1;
- @$.source = 0;
-}
-
-%parse-param {glcpp_parser_t *parser}
-%lex-param {glcpp_parser_t *parser}
-
-%expect 0
-%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
-%token PASTE
-%type <ival> expression INTEGER operator SPACE integer_constant
-%type <str> IDENTIFIER INTEGER_STRING OTHER
-%type <string_list> identifier_list
-%type <token> preprocessing_token conditional_token
-%type <token_list> pp_tokens replacement_list text_line conditional_tokens
-%left OR
-%left AND
-%left '|'
-%left '^'
-%left '&'
-%left EQUAL NOT_EQUAL
-%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
-%left LEFT_SHIFT RIGHT_SHIFT
-%left '+' '-'
-%left '*' '/' '%'
-%right UNARY
-
-%%
-
-input:
- /* empty */
-| input line
-;
-
-line:
- control_line {
- glcpp_print(parser->output, "\n");
- }
-| text_line {
- _glcpp_parser_print_expanded_token_list (parser, $1);
- glcpp_print(parser->output, "\n");
- talloc_free ($1);
- }
-| expanded_line
-| HASH non_directive
-;
-
-expanded_line:
- IF_EXPANDED expression NEWLINE {
- _glcpp_parser_skip_stack_push_if (parser, & @1, $2);
- }
-| ELIF_EXPANDED expression NEWLINE {
- _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
- }
-;
-
-control_line:
- HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
- _define_object_macro (parser, & @2, $2, $3);
- }
-| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
- _define_function_macro (parser, & @2, $2, NULL, $5);
- }
-| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
- _define_function_macro (parser, & @2, $2, $4, $6);
- }
-| HASH_UNDEF IDENTIFIER NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
- if (macro) {
- hash_table_remove (parser->defines, $2);
- talloc_free (macro);
- }
- talloc_free ($2);
- }
-| HASH_IF conditional_tokens NEWLINE {
- /* Be careful to only evaluate the 'if' expression if
- * we are not skipping. When we are skipping, we
- * simply push a new 0-valued 'if' onto the skip
- * stack.
- *
- * This avoids generating diagnostics for invalid
- * expressions that are being skipped. */
- if (parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
- }
- else
- {
- _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
- parser->skip_stack->type = SKIP_TO_ENDIF;
- }
- }
-| HASH_IF NEWLINE {
- /* #if without an expression is only an error if we
- * are not skipping */
- if (parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- glcpp_error(& @1, parser, "#if with no expression");
- }
- _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
- }
-| HASH_IFDEF IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
- talloc_free ($2);
- _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
- }
-| HASH_IFNDEF IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $2);
- talloc_free ($2);
- _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
- }
-| HASH_ELIF conditional_tokens NEWLINE {
- /* Be careful to only evaluate the 'elif' expression
- * if we are not skipping. When we are skipping, we
- * simply change to a 0-valued 'elif' on the skip
- * stack.
- *
- * This avoids generating diagnostics for invalid
- * expressions that are being skipped. */
- if (parser->skip_stack &&
- parser->skip_stack->type == SKIP_TO_ELSE)
- {
- _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
- }
- else
- {
- _glcpp_parser_skip_stack_change_if (parser, & @1,
- "elif", 0);
- }
- }
-| HASH_ELIF NEWLINE {
- /* #elif without an expression is an error unless we
- * are skipping. */
- if (parser->skip_stack &&
- parser->skip_stack->type == SKIP_TO_ELSE)
- {
- glcpp_error(& @1, parser, "#elif with no expression");
- }
- else
- {
- _glcpp_parser_skip_stack_change_if (parser, & @1,
- "elif", 0);
- glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
- }
- }
-| HASH_ELSE NEWLINE {
- _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
- }
-| HASH_ENDIF NEWLINE {
- _glcpp_parser_skip_stack_pop (parser, & @1);
- }
-| HASH_VERSION integer_constant NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
- if (macro) {
- hash_table_remove (parser->defines, "__VERSION__");
- talloc_free (macro);
- }
- add_builtin_define (parser, "__VERSION__", $2);
-
- if ($2 == 100)
- add_builtin_define (parser, "GL_ES", 1);
-
- /* Currently, all ES2 implementations support highp in the
- * fragment shader, so we always define this macro in ES2.
- * If we ever get a driver that doesn't support highp, we'll
- * need to add a flag to the gl_context and check that here.
- */
- if ($2 >= 130 || $2 == 100)
- add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
-
- glcpp_printf(parser->output, "#version %" PRIiMAX, $2);
- }
-| HASH NEWLINE
-;
-
-integer_constant:
- INTEGER_STRING {
- if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
- $$ = strtoll ($1 + 2, NULL, 16);
- } else if ($1[0] == '0') {
- $$ = strtoll ($1, NULL, 8);
- } else {
- $$ = strtoll ($1, NULL, 10);
- }
- }
-| INTEGER {
- $$ = $1;
- }
-
-expression:
- integer_constant
-| expression OR expression {
- $$ = $1 || $3;
- }
-| expression AND expression {
- $$ = $1 && $3;
- }
-| expression '|' expression {
- $$ = $1 | $3;
- }
-| expression '^' expression {
- $$ = $1 ^ $3;
- }
-| expression '&' expression {
- $$ = $1 & $3;
- }
-| expression NOT_EQUAL expression {
- $$ = $1 != $3;
- }
-| expression EQUAL expression {
- $$ = $1 == $3;
- }
-| expression GREATER_OR_EQUAL expression {
- $$ = $1 >= $3;
- }
-| expression LESS_OR_EQUAL expression {
- $$ = $1 <= $3;
- }
-| expression '>' expression {
- $$ = $1 > $3;
- }
-| expression '<' expression {
- $$ = $1 < $3;
- }
-| expression RIGHT_SHIFT expression {
- $$ = $1 >> $3;
- }
-| expression LEFT_SHIFT expression {
- $$ = $1 << $3;
- }
-| expression '-' expression {
- $$ = $1 - $3;
- }
-| expression '+' expression {
- $$ = $1 + $3;
- }
-| expression '%' expression {
- $$ = $1 % $3;
- }
-| expression '/' expression {
- if ($3 == 0) {
- yyerror (& @1, parser,
- "division by 0 in preprocessor directive");
- } else {
- $$ = $1 / $3;
- }
- }
-| expression '*' expression {
- $$ = $1 * $3;
- }
-| '!' expression %prec UNARY {
- $$ = ! $2;
- }
-| '~' expression %prec UNARY {
- $$ = ~ $2;
- }
-| '-' expression %prec UNARY {
- $$ = - $2;
- }
-| '+' expression %prec UNARY {
- $$ = + $2;
- }
-| '(' expression ')' {
- $$ = $2;
- }
-;
-
-identifier_list:
- IDENTIFIER {
- $$ = _string_list_create (parser);
- _string_list_append_item ($$, $1);
- talloc_steal ($$, $1);
- }
-| identifier_list ',' IDENTIFIER {
- $$ = $1;
- _string_list_append_item ($$, $3);
- talloc_steal ($$, $3);
- }
-;
-
-text_line:
- NEWLINE { $$ = NULL; }
-| pp_tokens NEWLINE
-;
-
-non_directive:
- pp_tokens NEWLINE {
- yyerror (& @1, parser, "Invalid tokens after #");
- }
-;
-
-replacement_list:
- /* empty */ { $$ = NULL; }
-| pp_tokens
-;
-
-junk:
- /* empty */
-| pp_tokens {
- glcpp_warning(&@1, parser, "extra tokens at end of directive");
- }
-;
-
-conditional_token:
- /* Handle "defined" operator */
- DEFINED IDENTIFIER {
- int v = hash_table_find (parser->defines, $2) ? 1 : 0;
- $$ = _token_create_ival (parser, INTEGER, v);
- }
-| DEFINED '(' IDENTIFIER ')' {
- int v = hash_table_find (parser->defines, $3) ? 1 : 0;
- $$ = _token_create_ival (parser, INTEGER, v);
- }
-| preprocessing_token
-;
-
-conditional_tokens:
- /* Exactly the same as pp_tokens, but using conditional_token */
- conditional_token {
- $$ = _token_list_create (parser);
- _token_list_append ($$, $1);
- }
-| conditional_tokens conditional_token {
- $$ = $1;
- _token_list_append ($$, $2);
- }
-;
-
-pp_tokens:
- preprocessing_token {
- parser->space_tokens = 1;
- $$ = _token_list_create (parser);
- _token_list_append ($$, $1);
- }
-| pp_tokens preprocessing_token {
- $$ = $1;
- _token_list_append ($$, $2);
- }
-;
-
-preprocessing_token:
- IDENTIFIER {
- $$ = _token_create_str (parser, IDENTIFIER, $1);
- $$->location = yylloc;
- }
-| INTEGER_STRING {
- $$ = _token_create_str (parser, INTEGER_STRING, $1);
- $$->location = yylloc;
- }
-| operator {
- $$ = _token_create_ival (parser, $1, $1);
- $$->location = yylloc;
- }
-| OTHER {
- $$ = _token_create_str (parser, OTHER, $1);
- $$->location = yylloc;
- }
-| SPACE {
- $$ = _token_create_ival (parser, SPACE, SPACE);
- $$->location = yylloc;
- }
-;
-
-operator:
- '[' { $$ = '['; }
-| ']' { $$ = ']'; }
-| '(' { $$ = '('; }
-| ')' { $$ = ')'; }
-| '{' { $$ = '{'; }
-| '}' { $$ = '}'; }
-| '.' { $$ = '.'; }
-| '&' { $$ = '&'; }
-| '*' { $$ = '*'; }
-| '+' { $$ = '+'; }
-| '-' { $$ = '-'; }
-| '~' { $$ = '~'; }
-| '!' { $$ = '!'; }
-| '/' { $$ = '/'; }
-| '%' { $$ = '%'; }
-| LEFT_SHIFT { $$ = LEFT_SHIFT; }
-| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
-| '<' { $$ = '<'; }
-| '>' { $$ = '>'; }
-| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
-| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
-| EQUAL { $$ = EQUAL; }
-| NOT_EQUAL { $$ = NOT_EQUAL; }
-| '^' { $$ = '^'; }
-| '|' { $$ = '|'; }
-| AND { $$ = AND; }
-| OR { $$ = OR; }
-| ';' { $$ = ';'; }
-| ',' { $$ = ','; }
-| '=' { $$ = '='; }
-| PASTE { $$ = PASTE; }
-;
-
-%%
-
-string_list_t *
-_string_list_create (void *ctx)
-{
- string_list_t *list;
-
- list = talloc (ctx, string_list_t);
- list->head = NULL;
- list->tail = NULL;
-
- return list;
-}
-
-void
-_string_list_append_item (string_list_t *list, const char *str)
-{
- string_node_t *node;
-
- node = talloc (list, string_node_t);
- node->str = talloc_strdup (node, str);
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
-}
-
-int
-_string_list_contains (string_list_t *list, const char *member, int *index)
-{
- string_node_t *node;
- int i;
-
- if (list == NULL)
- return 0;
-
- for (i = 0, node = list->head; node; i++, node = node->next) {
- if (strcmp (node->str, member) == 0) {
- if (index)
- *index = i;
- return 1;
- }
- }
-
- return 0;
-}
-
-int
-_string_list_length (string_list_t *list)
-{
- int length = 0;
- string_node_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list->head; node; node = node->next)
- length++;
-
- return length;
-}
-
-int
-_string_list_equal (string_list_t *a, string_list_t *b)
-{
- string_node_t *node_a, *node_b;
-
- if (a == NULL && b == NULL)
- return 1;
-
- if (a == NULL || b == NULL)
- return 0;
-
- for (node_a = a->head, node_b = b->head;
- node_a && node_b;
- node_a = node_a->next, node_b = node_b->next)
- {
- if (strcmp (node_a->str, node_b->str))
- return 0;
- }
-
- /* Catch the case of lists being different lengths, (which
- * would cause the loop above to terminate after the shorter
- * list). */
- return node_a == node_b;
-}
-
-argument_list_t *
-_argument_list_create (void *ctx)
-{
- argument_list_t *list;
-
- list = talloc (ctx, argument_list_t);
- list->head = NULL;
- list->tail = NULL;
-
- return list;
-}
-
-void
-_argument_list_append (argument_list_t *list, token_list_t *argument)
-{
- argument_node_t *node;
-
- node = talloc (list, argument_node_t);
- node->argument = argument;
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
-}
-
-int
-_argument_list_length (argument_list_t *list)
-{
- int length = 0;
- argument_node_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list->head; node; node = node->next)
- length++;
-
- return length;
-}
-
-token_list_t *
-_argument_list_member_at (argument_list_t *list, int index)
-{
- argument_node_t *node;
- int i;
-
- if (list == NULL)
- return NULL;
-
- node = list->head;
- for (i = 0; i < index; i++) {
- node = node->next;
- if (node == NULL)
- break;
- }
-
- if (node)
- return node->argument;
-
- return NULL;
-}
-
-/* Note: This function talloc_steal()s the str pointer. */
-token_t *
-_token_create_str (void *ctx, int type, char *str)
-{
- token_t *token;
-
- token = talloc (ctx, token_t);
- token->type = type;
- token->value.str = talloc_steal (token, str);
-
- return token;
-}
-
-token_t *
-_token_create_ival (void *ctx, int type, int ival)
-{
- token_t *token;
-
- token = talloc (ctx, token_t);
- token->type = type;
- token->value.ival = ival;
-
- return token;
-}
-
-token_list_t *
-_token_list_create (void *ctx)
-{
- token_list_t *list;
-
- list = talloc (ctx, token_list_t);
- list->head = NULL;
- list->tail = NULL;
- list->non_space_tail = NULL;
-
- return list;
-}
-
-void
-_token_list_append (token_list_t *list, token_t *token)
-{
- token_node_t *node;
-
- node = talloc (list, token_node_t);
- node->token = talloc_steal (list, token);
-
- node->next = NULL;
-
- if (list->head == NULL) {
- list->head = node;
- } else {
- list->tail->next = node;
- }
-
- list->tail = node;
- if (token->type != SPACE)
- list->non_space_tail = node;
-}
-
-void
-_token_list_append_list (token_list_t *list, token_list_t *tail)
-{
- if (tail == NULL || tail->head == NULL)
- return;
-
- if (list->head == NULL) {
- list->head = tail->head;
- } else {
- list->tail->next = tail->head;
- }
-
- list->tail = tail->tail;
- list->non_space_tail = tail->non_space_tail;
-}
-
-static token_list_t *
-_token_list_copy (void *ctx, token_list_t *other)
-{
- token_list_t *copy;
- token_node_t *node;
-
- if (other == NULL)
- return NULL;
-
- copy = _token_list_create (ctx);
- for (node = other->head; node; node = node->next) {
- token_t *new_token = talloc (copy, token_t);
- *new_token = *node->token;
- _token_list_append (copy, new_token);
- }
-
- return copy;
-}
-
-static void
-_token_list_trim_trailing_space (token_list_t *list)
-{
- token_node_t *tail, *next;
-
- if (list->non_space_tail) {
- tail = list->non_space_tail->next;
- list->non_space_tail->next = NULL;
- list->tail = list->non_space_tail;
-
- while (tail) {
- next = tail->next;
- talloc_free (tail);
- tail = next;
- }
- }
-}
-
-int
-_token_list_is_empty_ignoring_space (token_list_t *l)
-{
- token_node_t *n;
-
- if (l == NULL)
- return 1;
-
- n = l->head;
- while (n != NULL && n->token->type == SPACE)
- n = n->next;
-
- return n == NULL;
-}
-
-int
-_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
-{
- token_node_t *node_a, *node_b;
-
- if (a == NULL || b == NULL) {
- int a_empty = _token_list_is_empty_ignoring_space(a);
- int b_empty = _token_list_is_empty_ignoring_space(b);
- return a_empty == b_empty;
- }
-
- node_a = a->head;
- node_b = b->head;
-
- while (1)
- {
- if (node_a == NULL && node_b == NULL)
- break;
-
- if (node_a == NULL || node_b == NULL)
- return 0;
-
- if (node_a->token->type == SPACE) {
- node_a = node_a->next;
- continue;
- }
-
- if (node_b->token->type == SPACE) {
- node_b = node_b->next;
- continue;
- }
-
- if (node_a->token->type != node_b->token->type)
- return 0;
-
- switch (node_a->token->type) {
- case INTEGER:
- if (node_a->token->value.ival !=
- node_b->token->value.ival)
- {
- return 0;
- }
- break;
- case IDENTIFIER:
- case INTEGER_STRING:
- case OTHER:
- if (strcmp (node_a->token->value.str,
- node_b->token->value.str))
- {
- return 0;
- }
- break;
- }
-
- node_a = node_a->next;
- node_b = node_b->next;
- }
-
- return 1;
-}
-
-static void
-_token_print (char **out, token_t *token)
-{
- if (token->type < 256) {
- glcpp_printf (*out, "%c", token->type);
- return;
- }
-
- switch (token->type) {
- case INTEGER:
- glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
- break;
- case IDENTIFIER:
- case INTEGER_STRING:
- case OTHER:
- glcpp_print (*out, token->value.str);
- break;
- case SPACE:
- glcpp_print (*out, " ");
- break;
- case LEFT_SHIFT:
- glcpp_print (*out, "<<");
- break;
- case RIGHT_SHIFT:
- glcpp_print (*out, ">>");
- break;
- case LESS_OR_EQUAL:
- glcpp_print (*out, "<=");
- break;
- case GREATER_OR_EQUAL:
- glcpp_print (*out, ">=");
- break;
- case EQUAL:
- glcpp_print (*out, "==");
- break;
- case NOT_EQUAL:
- glcpp_print (*out, "!=");
- break;
- case AND:
- glcpp_print (*out, "&&");
- break;
- case OR:
- glcpp_print (*out, "||");
- break;
- case PASTE:
- glcpp_print (*out, "##");
- break;
- case COMMA_FINAL:
- glcpp_print (*out, ",");
- break;
- case PLACEHOLDER:
- /* Nothing to print. */
- break;
- default:
- assert(!"Error: Don't know how to print token.");
- break;
- }
-}
-
-/* Return a new token (talloc()ed off of 'token') formed by pasting
- * 'token' and 'other'. Note that this function may return 'token' or
- * 'other' directly rather than allocating anything new.
- *
- * Caution: Only very cursory error-checking is performed to see if
- * the final result is a valid single token. */
-static token_t *
-_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
-{
- token_t *combined = NULL;
-
- /* Pasting a placeholder onto anything makes no change. */
- if (other->type == PLACEHOLDER)
- return token;
-
- /* When 'token' is a placeholder, just return 'other'. */
- if (token->type == PLACEHOLDER)
- return other;
-
- /* A very few single-character punctuators can be combined
- * with another to form a multi-character punctuator. */
- switch (token->type) {
- case '<':
- if (other->type == '<')
- combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
- else if (other->type == '=')
- combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
- break;
- case '>':
- if (other->type == '>')
- combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
- else if (other->type == '=')
- combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
- break;
- case '=':
- if (other->type == '=')
- combined = _token_create_ival (token, EQUAL, EQUAL);
- break;
- case '!':
- if (other->type == '=')
- combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
- break;
- case '&':
- if (other->type == '&')
- combined = _token_create_ival (token, AND, AND);
- break;
- case '|':
- if (other->type == '|')
- combined = _token_create_ival (token, OR, OR);
- break;
- }
-
- if (combined != NULL) {
- /* Inherit the location from the first token */
- combined->location = token->location;
- return combined;
- }
-
- /* Two string-valued tokens can usually just be mashed
- * together.
- *
- * XXX: This isn't actually legitimate. Several things here
- * should result in a diagnostic since the result cannot be a
- * valid, single pre-processing token. For example, pasting
- * "123" and "abc" is not legal, but we don't catch that
- * here. */
- if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
- (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
- {
- char *str;
-
- str = talloc_asprintf (token, "%s%s", token->value.str,
- other->value.str);
- combined = _token_create_str (token, token->type, str);
- combined->location = token->location;
- return combined;
- }
-
- glcpp_error (&token->location, parser, "");
- glcpp_print (parser->info_log, "Pasting \"");
- _token_print (&parser->info_log, token);
- glcpp_print (parser->info_log, "\" and \"");
- _token_print (&parser->info_log, other);
- glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
-
- return token;
-}
-
-static void
-_token_list_print (glcpp_parser_t *parser, token_list_t *list)
-{
- token_node_t *node;
-
- if (list == NULL)
- return;
-
- for (node = list->head; node; node = node->next)
- _token_print (&parser->output, node->token);
-}
-
-void
-yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
-{
- glcpp_error(locp, parser, "%s", error);
-}
-
-static void add_builtin_define(glcpp_parser_t *parser,
- const char *name, int value)
-{
- token_t *tok;
- token_list_t *list;
-
- tok = _token_create_ival (parser, INTEGER, value);
-
- list = _token_list_create(parser);
- _token_list_append(list, tok);
- _define_object_macro(parser, NULL, name, list);
-}
-
-glcpp_parser_t *
-glcpp_parser_create (const struct gl_extensions *extensions, int api)
-{
- glcpp_parser_t *parser;
- int language_version;
-
- parser = talloc (NULL, glcpp_parser_t);
-
- glcpp_lex_init_extra (parser, &parser->scanner);
- parser->defines = hash_table_ctor (32, hash_table_string_hash,
- hash_table_string_compare);
- parser->active = NULL;
- parser->lexing_if = 0;
- parser->space_tokens = 1;
- parser->newline_as_space = 0;
- parser->in_control_line = 0;
- parser->paren_count = 0;
-
- parser->skip_stack = NULL;
-
- parser->lex_from_list = NULL;
- parser->lex_from_node = NULL;
-
- parser->output = talloc_strdup(parser, "");
- parser->info_log = talloc_strdup(parser, "");
- parser->error = 0;
-
- /* Add pre-defined macros. */
- add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
- add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
-
- if (api == API_OPENGLES2)
- add_builtin_define(parser, "GL_ES", 1);
-
- if (extensions != NULL) {
- if (extensions->EXT_texture_array) {
- add_builtin_define(parser, "GL_EXT_texture_array", 1);
- }
-
- if (extensions->ARB_fragment_coord_conventions)
- add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
- 1);
-
- if (extensions->ARB_explicit_attrib_location)
- add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
- }
-
- language_version = 110;
- add_builtin_define(parser, "__VERSION__", language_version);
-
- return parser;
-}
-
-int
-glcpp_parser_parse (glcpp_parser_t *parser)
-{
- return yyparse (parser);
-}
-
-void
-glcpp_parser_destroy (glcpp_parser_t *parser)
-{
- glcpp_lex_destroy (parser->scanner);
- hash_table_dtor (parser->defines);
- talloc_free (parser);
-}
-
-typedef enum function_status
-{
- FUNCTION_STATUS_SUCCESS,
- FUNCTION_NOT_A_FUNCTION,
- FUNCTION_UNBALANCED_PARENTHESES
-} function_status_t;
-
-/* Find a set of function-like macro arguments by looking for a
- * balanced set of parentheses.
- *
- * When called, 'node' should be the opening-parenthesis token, (or
- * perhaps preceeding SPACE tokens). Upon successful return *last will
- * be the last consumed node, (corresponding to the closing right
- * parenthesis).
- *
- * Return values:
- *
- * FUNCTION_STATUS_SUCCESS:
- *
- * Successfully parsed a set of function arguments.
- *
- * FUNCTION_NOT_A_FUNCTION:
- *
- * Macro name not followed by a '('. This is not an error, but
- * simply that the macro name should be treated as a non-macro.
- *
- * FUNCTION_UNBALANCED_PARENTHESES
- *
- * Macro name is not followed by a balanced set of parentheses.
- */
-static function_status_t
-_arguments_parse (argument_list_t *arguments,
- token_node_t *node,
- token_node_t **last)
-{
- token_list_t *argument;
- int paren_count;
-
- node = node->next;
-
- /* Ignore whitespace before first parenthesis. */
- while (node && node->token->type == SPACE)
- node = node->next;
-
- if (node == NULL || node->token->type != '(')
- return FUNCTION_NOT_A_FUNCTION;
-
- node = node->next;
-
- argument = _token_list_create (arguments);
- _argument_list_append (arguments, argument);
-
- for (paren_count = 1; node; node = node->next) {
- if (node->token->type == '(')
- {
- paren_count++;
- }
- else if (node->token->type == ')')
- {
- paren_count--;
- if (paren_count == 0)
- break;
- }
-
- if (node->token->type == ',' &&
- paren_count == 1)
- {
- _token_list_trim_trailing_space (argument);
- argument = _token_list_create (arguments);
- _argument_list_append (arguments, argument);
- }
- else {
- if (argument->head == NULL) {
- /* Don't treat initial whitespace as
- * part of the arguement. */
- if (node->token->type == SPACE)
- continue;
- }
- _token_list_append (argument, node->token);
- }
- }
-
- if (paren_count)
- return FUNCTION_UNBALANCED_PARENTHESES;
-
- *last = node;
-
- return FUNCTION_STATUS_SUCCESS;
-}
-
-static token_list_t *
-_token_list_create_with_one_space (void *ctx)
-{
- token_list_t *list;
- token_t *space;
-
- list = _token_list_create (ctx);
- space = _token_create_ival (list, SPACE, SPACE);
- _token_list_append (list, space);
-
- return list;
-}
-
-static void
-_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
-{
- token_list_t *expanded;
- token_t *token;
-
- expanded = _token_list_create (parser);
- token = _token_create_ival (parser, type, type);
- _token_list_append (expanded, token);
- _glcpp_parser_expand_token_list (parser, list);
- _token_list_append_list (expanded, list);
- glcpp_parser_lex_from (parser, expanded);
-}
-
-/* This is a helper function that's essentially part of the
- * implementation of _glcpp_parser_expand_node. It shouldn't be called
- * except for by that function.
- *
- * Returns NULL if node is a simple token with no expansion, (that is,
- * although 'node' corresponds to an identifier defined as a
- * function-like macro, it is not followed with a parenthesized
- * argument list).
- *
- * Compute the complete expansion of node (which is a function-like
- * macro) and subsequent nodes which are arguments.
- *
- * Returns the token list that results from the expansion and sets
- * *last to the last node in the list that was consumed by the
- * expansion. Specifically, *last will be set as follows: as the
- * token of the closing right parenthesis.
- */
-static token_list_t *
-_glcpp_parser_expand_function (glcpp_parser_t *parser,
- token_node_t *node,
- token_node_t **last)
-
-{
- macro_t *macro;
- const char *identifier;
- argument_list_t *arguments;
- function_status_t status;
- token_list_t *substituted;
- int parameter_index;
-
- identifier = node->token->value.str;
-
- macro = hash_table_find (parser->defines, identifier);
-
- assert (macro->is_function);
-
- arguments = _argument_list_create (parser);
- status = _arguments_parse (arguments, node, last);
-
- switch (status) {
- case FUNCTION_STATUS_SUCCESS:
- break;
- case FUNCTION_NOT_A_FUNCTION:
- return NULL;
- case FUNCTION_UNBALANCED_PARENTHESES:
- glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
- return NULL;
- }
-
- /* Replace a macro defined as empty with a SPACE token. */
- if (macro->replacements == NULL) {
- talloc_free (arguments);
- return _token_list_create_with_one_space (parser);
- }
-
- if (! ((_argument_list_length (arguments) ==
- _string_list_length (macro->parameters)) ||
- (_string_list_length (macro->parameters) == 0 &&
- _argument_list_length (arguments) == 1 &&
- arguments->head->argument->head == NULL)))
- {
- glcpp_error (&node->token->location, parser,
- "Error: macro %s invoked with %d arguments (expected %d)\n",
- identifier,
- _argument_list_length (arguments),
- _string_list_length (macro->parameters));
- return NULL;
- }
-
- /* Perform argument substitution on the replacement list. */
- substituted = _token_list_create (arguments);
-
- for (node = macro->replacements->head; node; node = node->next)
- {
- if (node->token->type == IDENTIFIER &&
- _string_list_contains (macro->parameters,
- node->token->value.str,
- &parameter_index))
- {
- token_list_t *argument;
- argument = _argument_list_member_at (arguments,
- parameter_index);
- /* Before substituting, we expand the argument
- * tokens, or append a placeholder token for
- * an empty argument. */
- if (argument->head) {
- token_list_t *expanded_argument;
- expanded_argument = _token_list_copy (parser,
- argument);
- _glcpp_parser_expand_token_list (parser,
- expanded_argument);
- _token_list_append_list (substituted,
- expanded_argument);
- } else {
- token_t *new_token;
-
- new_token = _token_create_ival (substituted,
- PLACEHOLDER,
- PLACEHOLDER);
- _token_list_append (substituted, new_token);
- }
- } else {
- _token_list_append (substituted, node->token);
- }
- }
-
- /* After argument substitution, and before further expansion
- * below, implement token pasting. */
-
- _token_list_trim_trailing_space (substituted);
-
- node = substituted->head;
- while (node)
- {
- token_node_t *next_non_space;
-
- /* Look ahead for a PASTE token, skipping space. */
- next_non_space = node->next;
- while (next_non_space && next_non_space->token->type == SPACE)
- next_non_space = next_non_space->next;
-
- if (next_non_space == NULL)
- break;
-
- if (next_non_space->token->type != PASTE) {
- node = next_non_space;
- continue;
- }
-
- /* Now find the next non-space token after the PASTE. */
- next_non_space = next_non_space->next;
- while (next_non_space && next_non_space->token->type == SPACE)
- next_non_space = next_non_space->next;
-
- if (next_non_space == NULL) {
- yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
- return NULL;
- }
-
- node->token = _token_paste (parser, node->token, next_non_space->token);
- node->next = next_non_space->next;
- if (next_non_space == substituted->tail)
- substituted->tail = node;
-
- node = node->next;
- }
-
- substituted->non_space_tail = substituted->tail;
-
- return substituted;
-}
-
-/* Compute the complete expansion of node, (and subsequent nodes after
- * 'node' in the case that 'node' is a function-like macro and
- * subsequent nodes are arguments).
- *
- * Returns NULL if node is a simple token with no expansion.
- *
- * Otherwise, returns the token list that results from the expansion
- * and sets *last to the last node in the list that was consumed by
- * the expansion. Specifically, *last will be set as follows:
- *
- * As 'node' in the case of object-like macro expansion.
- *
- * As the token of the closing right parenthesis in the case of
- * function-like macro expansion.
- */
-static token_list_t *
-_glcpp_parser_expand_node (glcpp_parser_t *parser,
- token_node_t *node,
- token_node_t **last)
-{
- token_t *token = node->token;
- const char *identifier;
- macro_t *macro;
-
- /* We only expand identifiers */
- if (token->type != IDENTIFIER) {
- /* We change any COMMA into a COMMA_FINAL to prevent
- * it being mistaken for an argument separator
- * later. */
- if (token->type == ',') {
- token->type = COMMA_FINAL;
- token->value.ival = COMMA_FINAL;
- }
-
- return NULL;
- }
-
- /* Look up this identifier in the hash table. */
- identifier = token->value.str;
- macro = hash_table_find (parser->defines, identifier);
-
- /* Not a macro, so no expansion needed. */
- if (macro == NULL)
- return NULL;
-
- /* Finally, don't expand this macro if we're already actively
- * expanding it, (to avoid infinite recursion). */
- if (_active_list_contains (parser->active, identifier)) {
- /* We change the token type here from IDENTIFIER to
- * OTHER to prevent any future expansion of this
- * unexpanded token. */
- char *str;
- token_list_t *expansion;
- token_t *final;
-
- str = talloc_strdup (parser, token->value.str);
- final = _token_create_str (parser, OTHER, str);
- expansion = _token_list_create (parser);
- _token_list_append (expansion, final);
- *last = node;
- return expansion;
- }
-
- if (! macro->is_function)
- {
- *last = node;
-
- /* Replace a macro defined as empty with a SPACE token. */
- if (macro->replacements == NULL)
- return _token_list_create_with_one_space (parser);
-
- return _token_list_copy (parser, macro->replacements);
- }
-
- return _glcpp_parser_expand_function (parser, node, last);
-}
-
-/* Push a new identifier onto the active list, returning the new list.
- *
- * Here, 'marker' is the token node that appears in the list after the
- * expansion of 'identifier'. That is, when the list iterator begins
- * examinging 'marker', then it is time to pop this node from the
- * active stack.
- */
-active_list_t *
-_active_list_push (active_list_t *list,
- const char *identifier,
- token_node_t *marker)
-{
- active_list_t *node;
-
- node = talloc (list, active_list_t);
- node->identifier = talloc_strdup (node, identifier);
- node->marker = marker;
- node->next = list;
-
- return node;
-}
-
-active_list_t *
-_active_list_pop (active_list_t *list)
-{
- active_list_t *node = list;
-
- if (node == NULL)
- return NULL;
-
- node = list->next;
- talloc_free (list);
-
- return node;
-}
-
-int
-_active_list_contains (active_list_t *list, const char *identifier)
-{
- active_list_t *node;
-
- if (list == NULL)
- return 0;
-
- for (node = list; node; node = node->next)
- if (strcmp (node->identifier, identifier) == 0)
- return 1;
-
- return 0;
-}
-
-/* Walk over the token list replacing nodes with their expansion.
- * Whenever nodes are expanded the walking will walk over the new
- * nodes, continuing to expand as necessary. The results are placed in
- * 'list' itself;
- */
-static void
-_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list)
-{
- token_node_t *node_prev;
- token_node_t *node, *last = NULL;
- token_list_t *expansion;
-
- if (list == NULL)
- return;
-
- _token_list_trim_trailing_space (list);
-
- node_prev = NULL;
- node = list->head;
-
- while (node) {
-
- while (parser->active && parser->active->marker == node)
- parser->active = _active_list_pop (parser->active);
-
- /* Find the expansion for node, which will replace all
- * nodes from node to last, inclusive. */
- expansion = _glcpp_parser_expand_node (parser, node, &last);
- if (expansion) {
- token_node_t *n;
-
- for (n = node; n != last->next; n = n->next)
- while (parser->active &&
- parser->active->marker == n)
- {
- parser->active = _active_list_pop (parser->active);
- }
-
- parser->active = _active_list_push (parser->active,
- node->token->value.str,
- last->next);
-
- /* Splice expansion into list, supporting a
- * simple deletion if the expansion is
- * empty. */
- if (expansion->head) {
- if (node_prev)
- node_prev->next = expansion->head;
- else
- list->head = expansion->head;
- expansion->tail->next = last->next;
- if (last == list->tail)
- list->tail = expansion->tail;
- } else {
- if (node_prev)
- node_prev->next = last->next;
- else
- list->head = last->next;
- if (last == list->tail)
- list->tail = NULL;
- }
- } else {
- node_prev = node;
- }
- node = node_prev ? node_prev->next : list->head;
- }
-
- while (parser->active)
- parser->active = _active_list_pop (parser->active);
-
- list->non_space_tail = list->tail;
-}
-
-void
-_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
- token_list_t *list)
-{
- if (list == NULL)
- return;
-
- _glcpp_parser_expand_token_list (parser, list);
-
- _token_list_trim_trailing_space (list);
-
- _token_list_print (parser, list);
-}
-
-static void
-_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *identifier)
-{
- /* According to the GLSL specification, macro names starting with "__"
- * or "GL_" are reserved for future use. So, don't allow them.
- */
- if (strncmp(identifier, "__", 2) == 0) {
- glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
- }
- if (strncmp(identifier, "GL_", 3) == 0) {
- glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
- }
-}
-
-static int
-_macro_equal (macro_t *a, macro_t *b)
-{
- if (a->is_function != b->is_function)
- return 0;
-
- if (a->is_function) {
- if (! _string_list_equal (a->parameters, b->parameters))
- return 0;
- }
-
- return _token_list_equal_ignoring_space (a->replacements,
- b->replacements);
-}
-
-void
-_define_object_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *identifier,
- token_list_t *replacements)
-{
- macro_t *macro, *previous;
-
- if (loc != NULL)
- _check_for_reserved_macro_name(parser, loc, identifier);
-
- macro = talloc (parser, macro_t);
-
- macro->is_function = 0;
- macro->parameters = NULL;
- macro->identifier = talloc_strdup (macro, identifier);
- macro->replacements = talloc_steal (macro, replacements);
-
- previous = hash_table_find (parser->defines, identifier);
- if (previous) {
- if (_macro_equal (macro, previous)) {
- talloc_free (macro);
- return;
- }
- glcpp_error (loc, parser, "Redefinition of macro %s\n",
- identifier);
- }
-
- hash_table_insert (parser->defines, macro, identifier);
-}
-
-void
-_define_function_macro (glcpp_parser_t *parser,
- YYLTYPE *loc,
- const char *identifier,
- string_list_t *parameters,
- token_list_t *replacements)
-{
- macro_t *macro, *previous;
-
- _check_for_reserved_macro_name(parser, loc, identifier);
-
- macro = talloc (parser, macro_t);
-
- macro->is_function = 1;
- macro->parameters = talloc_steal (macro, parameters);
- macro->identifier = talloc_strdup (macro, identifier);
- macro->replacements = talloc_steal (macro, replacements);
-
- previous = hash_table_find (parser->defines, identifier);
- if (previous) {
- if (_macro_equal (macro, previous)) {
- talloc_free (macro);
- return;
- }
- glcpp_error (loc, parser, "Redefinition of macro %s\n",
- identifier);
- }
-
- hash_table_insert (parser->defines, macro, identifier);
-}
-
-static int
-glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
-{
- token_node_t *node;
- int ret;
-
- if (parser->lex_from_list == NULL) {
- ret = glcpp_lex (yylval, yylloc, parser->scanner);
-
- /* XXX: This ugly block of code exists for the sole
- * purpose of converting a NEWLINE token into a SPACE
- * token, but only in the case where we have seen a
- * function-like macro name, but have not yet seen its
- * closing parenthesis.
- *
- * There's perhaps a more compact way to do this with
- * mid-rule actions in the grammar.
- *
- * I'm definitely not pleased with the complexity of
- * this code here.
- */
- if (parser->newline_as_space)
- {
- if (ret == '(') {
- parser->paren_count++;
- } else if (ret == ')') {
- parser->paren_count--;
- if (parser->paren_count == 0)
- parser->newline_as_space = 0;
- } else if (ret == NEWLINE) {
- ret = SPACE;
- } else if (ret != SPACE) {
- if (parser->paren_count == 0)
- parser->newline_as_space = 0;
- }
- }
- else if (parser->in_control_line)
- {
- if (ret == NEWLINE)
- parser->in_control_line = 0;
- }
- else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
- ret == HASH_UNDEF || ret == HASH_IF ||
- ret == HASH_IFDEF || ret == HASH_IFNDEF ||
- ret == HASH_ELIF || ret == HASH_ELSE ||
- ret == HASH_ENDIF || ret == HASH)
- {
- parser->in_control_line = 1;
- }
- else if (ret == IDENTIFIER)
- {
- macro_t *macro;
- macro = hash_table_find (parser->defines,
- yylval->str);
- if (macro && macro->is_function) {
- parser->newline_as_space = 1;
- parser->paren_count = 0;
- }
- }
-
- return ret;
- }
-
- node = parser->lex_from_node;
-
- if (node == NULL) {
- talloc_free (parser->lex_from_list);
- parser->lex_from_list = NULL;
- return NEWLINE;
- }
-
- *yylval = node->token->value;
- ret = node->token->type;
-
- parser->lex_from_node = node->next;
-
- return ret;
-}
-
-static void
-glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
-{
- token_node_t *node;
-
- assert (parser->lex_from_list == NULL);
-
- /* Copy list, eliminating any space tokens. */
- parser->lex_from_list = _token_list_create (parser);
-
- for (node = list->head; node; node = node->next) {
- if (node->token->type == SPACE)
- continue;
- _token_list_append (parser->lex_from_list, node->token);
- }
-
- talloc_free (list);
-
- parser->lex_from_node = parser->lex_from_list->head;
-
- /* It's possible the list consisted of nothing but whitespace. */
- if (parser->lex_from_node == NULL) {
- talloc_free (parser->lex_from_list);
- parser->lex_from_list = NULL;
- }
-}
-
-static void
-_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
- int condition)
-{
- skip_type_t current = SKIP_NO_SKIP;
- skip_node_t *node;
-
- if (parser->skip_stack)
- current = parser->skip_stack->type;
-
- node = talloc (parser, skip_node_t);
- node->loc = *loc;
-
- if (current == SKIP_NO_SKIP) {
- if (condition)
- node->type = SKIP_NO_SKIP;
- else
- node->type = SKIP_TO_ELSE;
- } else {
- node->type = SKIP_TO_ENDIF;
- }
-
- node->next = parser->skip_stack;
- parser->skip_stack = node;
-}
-
-static void
-_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
- const char *type, int condition)
-{
- if (parser->skip_stack == NULL) {
- glcpp_error (loc, parser, "%s without #if\n", type);
- return;
- }
-
- if (parser->skip_stack->type == SKIP_TO_ELSE) {
- if (condition)
- parser->skip_stack->type = SKIP_NO_SKIP;
- } else {
- parser->skip_stack->type = SKIP_TO_ENDIF;
- }
-}
-
-static void
-_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
-{
- skip_node_t *node;
-
- if (parser->skip_stack == NULL) {
- glcpp_error (loc, parser, "#endif without #if\n");
- return;
- }
-
- node = parser->skip_stack;
- parser->skip_stack = node->next;
- talloc_free (node);
-}
+%{
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.h"
+#include "main/core.h" /* for struct gl_extensions */
+#include "main/mtypes.h" /* for gl_api enum */
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+ stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ string_list_t *parameters,
+ token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static int
+_string_list_equal (string_list_t *a, string_list_t *b);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function calls talloc_steal on token. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+ @$.first_line = 1;
+ @$.first_column = 1;
+ @$.last_line = 1;
+ @$.last_column = 1;
+ @$.source = 0;
+}
+
+%parse-param {glcpp_parser_t *parser}
+%lex-param {glcpp_parser_t *parser}
+
+%expect 0
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
+%token PASTE
+%type <ival> expression INTEGER operator SPACE integer_constant
+%type <str> IDENTIFIER INTEGER_STRING OTHER
+%type <string_list> identifier_list
+%type <token> preprocessing_token conditional_token
+%type <token_list> pp_tokens replacement_list text_line conditional_tokens
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOT_EQUAL
+%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
+%left LEFT_SHIFT RIGHT_SHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+
+%%
+
+input:
+ /* empty */
+| input line
+;
+
+line:
+ control_line {
+ glcpp_print(parser->output, "\n");
+ }
+| text_line {
+ _glcpp_parser_print_expanded_token_list (parser, $1);
+ glcpp_print(parser->output, "\n");
+ talloc_free ($1);
+ }
+| expanded_line
+| HASH non_directive
+;
+
+expanded_line:
+ IF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, $2);
+ }
+| ELIF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
+ }
+;
+
+control_line:
+ HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+ _define_object_macro (parser, & @2, $2, $3);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, NULL, $5);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, $4, $6);
+ }
+| HASH_UNDEF IDENTIFIER NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ if (macro) {
+ hash_table_remove (parser->defines, $2);
+ talloc_free (macro);
+ }
+ talloc_free ($2);
+ }
+| HASH_IF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'if' expression if
+ * we are not skipping. When we are skipping, we
+ * simply push a new 0-valued 'if' onto the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+ }
+| HASH_IF NEWLINE {
+ /* #if without an expression is only an error if we
+ * are not skipping */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ glcpp_error(& @1, parser, "#if with no expression");
+ }
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ }
+| HASH_IFDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ talloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
+ }
+| HASH_IFNDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ talloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
+ }
+| HASH_ELIF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'elif' expression
+ * if we are not skipping. When we are skipping, we
+ * simply change to a 0-valued 'elif' on the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ }
+ }
+| HASH_ELIF NEWLINE {
+ /* #elif without an expression is an error unless we
+ * are skipping. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ glcpp_error(& @1, parser, "#elif with no expression");
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+ }
+ }
+| HASH_ELSE NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+ }
+| HASH_ENDIF NEWLINE {
+ _glcpp_parser_skip_stack_pop (parser, & @1);
+ }
+| HASH_VERSION integer_constant NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+ if (macro) {
+ hash_table_remove (parser->defines, "__VERSION__");
+ talloc_free (macro);
+ }
+ add_builtin_define (parser, "__VERSION__", $2);
+
+ if ($2 == 100)
+ add_builtin_define (parser, "GL_ES", 1);
+
+ /* Currently, all ES2 implementations support highp in the
+ * fragment shader, so we always define this macro in ES2.
+ * If we ever get a driver that doesn't support highp, we'll
+ * need to add a flag to the gl_context and check that here.
+ */
+ if ($2 >= 130 || $2 == 100)
+ add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
+
+ glcpp_printf(parser->output, "#version %" PRIiMAX, $2);
+ }
+| HASH NEWLINE
+;
+
+integer_constant:
+ INTEGER_STRING {
+ if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
+ $$ = strtoll ($1 + 2, NULL, 16);
+ } else if ($1[0] == '0') {
+ $$ = strtoll ($1, NULL, 8);
+ } else {
+ $$ = strtoll ($1, NULL, 10);
+ }
+ }
+| INTEGER {
+ $$ = $1;
+ }
+
+expression:
+ integer_constant
+| expression OR expression {
+ $$ = $1 || $3;
+ }
+| expression AND expression {
+ $$ = $1 && $3;
+ }
+| expression '|' expression {
+ $$ = $1 | $3;
+ }
+| expression '^' expression {
+ $$ = $1 ^ $3;
+ }
+| expression '&' expression {
+ $$ = $1 & $3;
+ }
+| expression NOT_EQUAL expression {
+ $$ = $1 != $3;
+ }
+| expression EQUAL expression {
+ $$ = $1 == $3;
+ }
+| expression GREATER_OR_EQUAL expression {
+ $$ = $1 >= $3;
+ }
+| expression LESS_OR_EQUAL expression {
+ $$ = $1 <= $3;
+ }
+| expression '>' expression {
+ $$ = $1 > $3;
+ }
+| expression '<' expression {
+ $$ = $1 < $3;
+ }
+| expression RIGHT_SHIFT expression {
+ $$ = $1 >> $3;
+ }
+| expression LEFT_SHIFT expression {
+ $$ = $1 << $3;
+ }
+| expression '-' expression {
+ $$ = $1 - $3;
+ }
+| expression '+' expression {
+ $$ = $1 + $3;
+ }
+| expression '%' expression {
+ $$ = $1 % $3;
+ }
+| expression '/' expression {
+ if ($3 == 0) {
+ yyerror (& @1, parser,
+ "division by 0 in preprocessor directive");
+ } else {
+ $$ = $1 / $3;
+ }
+ }
+| expression '*' expression {
+ $$ = $1 * $3;
+ }
+| '!' expression %prec UNARY {
+ $$ = ! $2;
+ }
+| '~' expression %prec UNARY {
+ $$ = ~ $2;
+ }
+| '-' expression %prec UNARY {
+ $$ = - $2;
+ }
+| '+' expression %prec UNARY {
+ $$ = + $2;
+ }
+| '(' expression ')' {
+ $$ = $2;
+ }
+;
+
+identifier_list:
+ IDENTIFIER {
+ $$ = _string_list_create (parser);
+ _string_list_append_item ($$, $1);
+ talloc_steal ($$, $1);
+ }
+| identifier_list ',' IDENTIFIER {
+ $$ = $1;
+ _string_list_append_item ($$, $3);
+ talloc_steal ($$, $3);
+ }
+;
+
+text_line:
+ NEWLINE { $$ = NULL; }
+| pp_tokens NEWLINE
+;
+
+non_directive:
+ pp_tokens NEWLINE {
+ yyerror (& @1, parser, "Invalid tokens after #");
+ }
+;
+
+replacement_list:
+ /* empty */ { $$ = NULL; }
+| pp_tokens
+;
+
+junk:
+ /* empty */
+| pp_tokens {
+ glcpp_warning(&@1, parser, "extra tokens at end of directive");
+ }
+;
+
+conditional_token:
+ /* Handle "defined" operator */
+ DEFINED IDENTIFIER {
+ int v = hash_table_find (parser->defines, $2) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| DEFINED '(' IDENTIFIER ')' {
+ int v = hash_table_find (parser->defines, $3) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| preprocessing_token
+;
+
+conditional_tokens:
+ /* Exactly the same as pp_tokens, but using conditional_token */
+ conditional_token {
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ }
+| conditional_tokens conditional_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ }
+;
+
+pp_tokens:
+ preprocessing_token {
+ parser->space_tokens = 1;
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ }
+| pp_tokens preprocessing_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ }
+;
+
+preprocessing_token:
+ IDENTIFIER {
+ $$ = _token_create_str (parser, IDENTIFIER, $1);
+ $$->location = yylloc;
+ }
+| INTEGER_STRING {
+ $$ = _token_create_str (parser, INTEGER_STRING, $1);
+ $$->location = yylloc;
+ }
+| operator {
+ $$ = _token_create_ival (parser, $1, $1);
+ $$->location = yylloc;
+ }
+| OTHER {
+ $$ = _token_create_str (parser, OTHER, $1);
+ $$->location = yylloc;
+ }
+| SPACE {
+ $$ = _token_create_ival (parser, SPACE, SPACE);
+ $$->location = yylloc;
+ }
+;
+
+operator:
+ '[' { $$ = '['; }
+| ']' { $$ = ']'; }
+| '(' { $$ = '('; }
+| ')' { $$ = ')'; }
+| '{' { $$ = '{'; }
+| '}' { $$ = '}'; }
+| '.' { $$ = '.'; }
+| '&' { $$ = '&'; }
+| '*' { $$ = '*'; }
+| '+' { $$ = '+'; }
+| '-' { $$ = '-'; }
+| '~' { $$ = '~'; }
+| '!' { $$ = '!'; }
+| '/' { $$ = '/'; }
+| '%' { $$ = '%'; }
+| LEFT_SHIFT { $$ = LEFT_SHIFT; }
+| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
+| '<' { $$ = '<'; }
+| '>' { $$ = '>'; }
+| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
+| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
+| EQUAL { $$ = EQUAL; }
+| NOT_EQUAL { $$ = NOT_EQUAL; }
+| '^' { $$ = '^'; }
+| '|' { $$ = '|'; }
+| AND { $$ = AND; }
+| OR { $$ = OR; }
+| ';' { $$ = ';'; }
+| ',' { $$ = ','; }
+| '=' { $$ = '='; }
+| PASTE { $$ = PASTE; }
+;
+
+%%
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = talloc (ctx, string_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = talloc (list, string_node_t);
+ node->str = talloc_strdup (node, str);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+ string_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0, node = list->head; node; i++, node = node->next) {
+ if (strcmp (node->str, member) == 0) {
+ if (index)
+ *index = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+ int length = 0;
+ string_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+int
+_string_list_equal (string_list_t *a, string_list_t *b)
+{
+ string_node_t *node_a, *node_b;
+
+ if (a == NULL && b == NULL)
+ return 1;
+
+ if (a == NULL || b == NULL)
+ return 0;
+
+ for (node_a = a->head, node_b = b->head;
+ node_a && node_b;
+ node_a = node_a->next, node_b = node_b->next)
+ {
+ if (strcmp (node_a->str, node_b->str))
+ return 0;
+ }
+
+ /* Catch the case of lists being different lengths, (which
+ * would cause the loop above to terminate after the shorter
+ * list). */
+ return node_a == node_b;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+ argument_list_t *list;
+
+ list = talloc (ctx, argument_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+ argument_node_t *node;
+
+ node = talloc (list, argument_node_t);
+ node->argument = argument;
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+ int length = 0;
+ argument_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+ argument_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return NULL;
+
+ node = list->head;
+ for (i = 0; i < index; i++) {
+ node = node->next;
+ if (node == NULL)
+ break;
+ }
+
+ if (node)
+ return node->argument;
+
+ return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.str = talloc_steal (token, str);
+
+ return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+ token_t *token;
+
+ token = talloc (ctx, token_t);
+ token->type = type;
+ token->value.ival = ival;
+
+ return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+ token_list_t *list;
+
+ list = talloc (ctx, token_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+ list->non_space_tail = NULL;
+
+ return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+ token_node_t *node;
+
+ node = talloc (list, token_node_t);
+ node->token = talloc_steal (list, token);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+ if (token->type != SPACE)
+ list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+ if (tail == NULL || tail->head == NULL)
+ return;
+
+ if (list->head == NULL) {
+ list->head = tail->head;
+ } else {
+ list->tail->next = tail->head;
+ }
+
+ list->tail = tail->tail;
+ list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+ token_list_t *copy;
+ token_node_t *node;
+
+ if (other == NULL)
+ return NULL;
+
+ copy = _token_list_create (ctx);
+ for (node = other->head; node; node = node->next) {
+ token_t *new_token = talloc (copy, token_t);
+ *new_token = *node->token;
+ _token_list_append (copy, new_token);
+ }
+
+ return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+ token_node_t *tail, *next;
+
+ if (list->non_space_tail) {
+ tail = list->non_space_tail->next;
+ list->non_space_tail->next = NULL;
+ list->tail = list->non_space_tail;
+
+ while (tail) {
+ next = tail->next;
+ talloc_free (tail);
+ tail = next;
+ }
+ }
+}
+
+int
+_token_list_is_empty_ignoring_space (token_list_t *l)
+{
+ token_node_t *n;
+
+ if (l == NULL)
+ return 1;
+
+ n = l->head;
+ while (n != NULL && n->token->type == SPACE)
+ n = n->next;
+
+ return n == NULL;
+}
+
+int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
+{
+ token_node_t *node_a, *node_b;
+
+ if (a == NULL || b == NULL) {
+ int a_empty = _token_list_is_empty_ignoring_space(a);
+ int b_empty = _token_list_is_empty_ignoring_space(b);
+ return a_empty == b_empty;
+ }
+
+ node_a = a->head;
+ node_b = b->head;
+
+ while (1)
+ {
+ if (node_a == NULL && node_b == NULL)
+ break;
+
+ if (node_a == NULL || node_b == NULL)
+ return 0;
+
+ if (node_a->token->type == SPACE) {
+ node_a = node_a->next;
+ continue;
+ }
+
+ if (node_b->token->type == SPACE) {
+ node_b = node_b->next;
+ continue;
+ }
+
+ if (node_a->token->type != node_b->token->type)
+ return 0;
+
+ switch (node_a->token->type) {
+ case INTEGER:
+ if (node_a->token->value.ival !=
+ node_b->token->value.ival)
+ {
+ return 0;
+ }
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ if (strcmp (node_a->token->value.str,
+ node_b->token->value.str))
+ {
+ return 0;
+ }
+ break;
+ }
+
+ node_a = node_a->next;
+ node_b = node_b->next;
+ }
+
+ return 1;
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+ if (token->type < 256) {
+ glcpp_printf (*out, "%c", token->type);
+ return;
+ }
+
+ switch (token->type) {
+ case INTEGER:
+ glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ glcpp_print (*out, token->value.str);
+ break;
+ case SPACE:
+ glcpp_print (*out, " ");
+ break;
+ case LEFT_SHIFT:
+ glcpp_print (*out, "<<");
+ break;
+ case RIGHT_SHIFT:
+ glcpp_print (*out, ">>");
+ break;
+ case LESS_OR_EQUAL:
+ glcpp_print (*out, "<=");
+ break;
+ case GREATER_OR_EQUAL:
+ glcpp_print (*out, ">=");
+ break;
+ case EQUAL:
+ glcpp_print (*out, "==");
+ break;
+ case NOT_EQUAL:
+ glcpp_print (*out, "!=");
+ break;
+ case AND:
+ glcpp_print (*out, "&&");
+ break;
+ case OR:
+ glcpp_print (*out, "||");
+ break;
+ case PASTE:
+ glcpp_print (*out, "##");
+ break;
+ case COMMA_FINAL:
+ glcpp_print (*out, ",");
+ break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
+ default:
+ assert(!"Error: Don't know how to print token.");
+ break;
+ }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+ token_t *combined = NULL;
+
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return token;
+
+ /* When 'token' is a placeholder, just return 'other'. */
+ if (token->type == PLACEHOLDER)
+ return other;
+
+ /* A very few single-character punctuators can be combined
+ * with another to form a multi-character punctuator. */
+ switch (token->type) {
+ case '<':
+ if (other->type == '<')
+ combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+ break;
+ case '>':
+ if (other->type == '>')
+ combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+ break;
+ case '=':
+ if (other->type == '=')
+ combined = _token_create_ival (token, EQUAL, EQUAL);
+ break;
+ case '!':
+ if (other->type == '=')
+ combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+ break;
+ case '&':
+ if (other->type == '&')
+ combined = _token_create_ival (token, AND, AND);
+ break;
+ case '|':
+ if (other->type == '|')
+ combined = _token_create_ival (token, OR, OR);
+ break;
+ }
+
+ if (combined != NULL) {
+ /* Inherit the location from the first token */
+ combined->location = token->location;
+ return combined;
+ }
+
+ /* Two string-valued tokens can usually just be mashed
+ * together.
+ *
+ * XXX: This isn't actually legitimate. Several things here
+ * should result in a diagnostic since the result cannot be a
+ * valid, single pre-processing token. For example, pasting
+ * "123" and "abc" is not legal, but we don't catch that
+ * here. */
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+ {
+ char *str;
+
+ str = talloc_asprintf (token, "%s%s", token->value.str,
+ other->value.str);
+ combined = _token_create_str (token, token->type, str);
+ combined->location = token->location;
+ return combined;
+ }
+
+ glcpp_error (&token->location, parser, "");
+ glcpp_print (parser->info_log, "Pasting \"");
+ _token_print (&parser->info_log, token);
+ glcpp_print (parser->info_log, "\" and \"");
+ _token_print (&parser->info_log, other);
+ glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+ return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ if (list == NULL)
+ return;
+
+ for (node = list->head; node; node = node->next)
+ _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+ glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+ const char *name, int value)
+{
+ token_t *tok;
+ token_list_t *list;
+
+ tok = _token_create_ival (parser, INTEGER, value);
+
+ list = _token_list_create(parser);
+ _token_list_append(list, tok);
+ _define_object_macro(parser, NULL, name, list);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions, int api)
+{
+ glcpp_parser_t *parser;
+ int language_version;
+
+ parser = talloc (NULL, glcpp_parser_t);
+
+ glcpp_lex_init_extra (parser, &parser->scanner);
+ parser->defines = hash_table_ctor (32, hash_table_string_hash,
+ hash_table_string_compare);
+ parser->active = NULL;
+ parser->lexing_if = 0;
+ parser->space_tokens = 1;
+ parser->newline_as_space = 0;
+ parser->in_control_line = 0;
+ parser->paren_count = 0;
+
+ parser->skip_stack = NULL;
+
+ parser->lex_from_list = NULL;
+ parser->lex_from_node = NULL;
+
+ parser->output = talloc_strdup(parser, "");
+ parser->info_log = talloc_strdup(parser, "");
+ parser->error = 0;
+
+ /* Add pre-defined macros. */
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (api == API_OPENGLES2)
+ add_builtin_define(parser, "GL_ES", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array) {
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+ }
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+
+ if (extensions->ARB_explicit_attrib_location)
+ add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+ if (extensions->AMD_conservative_depth)
+ add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
+ }
+
+ language_version = 110;
+ add_builtin_define(parser, "__VERSION__", language_version);
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ glcpp_lex_destroy (parser->scanner);
+ hash_table_dtor (parser->defines);
+ talloc_free (parser);
+}
+
+typedef enum function_status
+{
+ FUNCTION_STATUS_SUCCESS,
+ FUNCTION_NOT_A_FUNCTION,
+ FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ * FUNCTION_STATUS_SUCCESS:
+ *
+ * Successfully parsed a set of function arguments.
+ *
+ * FUNCTION_NOT_A_FUNCTION:
+ *
+ * Macro name not followed by a '('. This is not an error, but
+ * simply that the macro name should be treated as a non-macro.
+ *
+ * FUNCTION_UNBALANCED_PARENTHESES
+ *
+ * Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_list_t *argument;
+ int paren_count;
+
+ node = node->next;
+
+ /* Ignore whitespace before first parenthesis. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != '(')
+ return FUNCTION_NOT_A_FUNCTION;
+
+ node = node->next;
+
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+
+ for (paren_count = 1; node; node = node->next) {
+ if (node->token->type == '(')
+ {
+ paren_count++;
+ }
+ else if (node->token->type == ')')
+ {
+ paren_count--;
+ if (paren_count == 0)
+ break;
+ }
+
+ if (node->token->type == ',' &&
+ paren_count == 1)
+ {
+ _token_list_trim_trailing_space (argument);
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ else {
+ if (argument->head == NULL) {
+ /* Don't treat initial whitespace as
+ * part of the arguement. */
+ if (node->token->type == SPACE)
+ continue;
+ }
+ _token_list_append (argument, node->token);
+ }
+ }
+
+ if (paren_count)
+ return FUNCTION_UNBALANCED_PARENTHESES;
+
+ *last = node;
+
+ return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, type, type);
+ _token_list_append (expanded, token);
+ _glcpp_parser_expand_token_list (parser, list);
+ _token_list_append_list (expanded, list);
+ glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+
+{
+ macro_t *macro;
+ const char *identifier;
+ argument_list_t *arguments;
+ function_status_t status;
+ token_list_t *substituted;
+ int parameter_index;
+
+ identifier = node->token->value.str;
+
+ macro = hash_table_find (parser->defines, identifier);
+
+ assert (macro->is_function);
+
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node, last);
+
+ switch (status) {
+ case FUNCTION_STATUS_SUCCESS:
+ break;
+ case FUNCTION_NOT_A_FUNCTION:
+ return NULL;
+ case FUNCTION_UNBALANCED_PARENTHESES:
+ glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+ return NULL;
+ }
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL) {
+ talloc_free (arguments);
+ return _token_list_create_with_one_space (parser);
+ }
+
+ if (! ((_argument_list_length (arguments) ==
+ _string_list_length (macro->parameters)) ||
+ (_string_list_length (macro->parameters) == 0 &&
+ _argument_list_length (arguments) == 1 &&
+ arguments->head->argument->head == NULL)))
+ {
+ glcpp_error (&node->token->location, parser,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return NULL;
+ }
+
+ /* Perform argument substitution on the replacement list. */
+ substituted = _token_list_create (arguments);
+
+ for (node = macro->replacements->head; node; node = node->next)
+ {
+ if (node->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ node->token->value.str,
+ &parameter_index))
+ {
+ token_list_t *argument;
+ argument = _argument_list_member_at (arguments,
+ parameter_index);
+ /* Before substituting, we expand the argument
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ token_list_t *expanded_argument;
+ expanded_argument = _token_list_copy (parser,
+ argument);
+ _glcpp_parser_expand_token_list (parser,
+ expanded_argument);
+ _token_list_append_list (substituted,
+ expanded_argument);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
+ } else {
+ _token_list_append (substituted, node->token);
+ }
+ }
+
+ /* After argument substitution, and before further expansion
+ * below, implement token pasting. */
+
+ _token_list_trim_trailing_space (substituted);
+
+ node = substituted->head;
+ while (node)
+ {
+ token_node_t *next_non_space;
+
+ /* Look ahead for a PASTE token, skipping space. */
+ next_non_space = node->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL)
+ break;
+
+ if (next_non_space->token->type != PASTE) {
+ node = next_non_space;
+ continue;
+ }
+
+ /* Now find the next non-space token after the PASTE. */
+ next_non_space = next_non_space->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL) {
+ yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+ return NULL;
+ }
+
+ node->token = _token_paste (parser, node->token, next_non_space->token);
+ node->next = next_non_space->next;
+ if (next_non_space == substituted->tail)
+ substituted->tail = node;
+
+ node = node->next;
+ }
+
+ substituted->non_space_tail = substituted->tail;
+
+ return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ * As 'node' in the case of object-like macro expansion.
+ *
+ * As the token of the closing right parenthesis in the case of
+ * function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_t *token = node->token;
+ const char *identifier;
+ macro_t *macro;
+
+ /* We only expand identifiers */
+ if (token->type != IDENTIFIER) {
+ /* We change any COMMA into a COMMA_FINAL to prevent
+ * it being mistaken for an argument separator
+ * later. */
+ if (token->type == ',') {
+ token->type = COMMA_FINAL;
+ token->value.ival = COMMA_FINAL;
+ }
+
+ return NULL;
+ }
+
+ /* Look up this identifier in the hash table. */
+ identifier = token->value.str;
+ macro = hash_table_find (parser->defines, identifier);
+
+ /* Not a macro, so no expansion needed. */
+ if (macro == NULL)
+ return NULL;
+
+ /* Finally, don't expand this macro if we're already actively
+ * expanding it, (to avoid infinite recursion). */
+ if (_active_list_contains (parser->active, identifier)) {
+ /* We change the token type here from IDENTIFIER to
+ * OTHER to prevent any future expansion of this
+ * unexpanded token. */
+ char *str;
+ token_list_t *expansion;
+ token_t *final;
+
+ str = talloc_strdup (parser, token->value.str);
+ final = _token_create_str (parser, OTHER, str);
+ expansion = _token_list_create (parser);
+ _token_list_append (expansion, final);
+ *last = node;
+ return expansion;
+ }
+
+ if (! macro->is_function)
+ {
+ *last = node;
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL)
+ return _token_list_create_with_one_space (parser);
+
+ return _token_list_copy (parser, macro->replacements);
+ }
+
+ return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+ const char *identifier,
+ token_node_t *marker)
+{
+ active_list_t *node;
+
+ node = talloc (list, active_list_t);
+ node->identifier = talloc_strdup (node, identifier);
+ node->marker = marker;
+ node->next = list;
+
+ return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+ active_list_t *node = list;
+
+ if (node == NULL)
+ return NULL;
+
+ node = list->next;
+ talloc_free (list);
+
+ return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+ active_list_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list; node; node = node->next)
+ if (strcmp (node->identifier, identifier) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node_prev;
+ token_node_t *node, *last = NULL;
+ token_list_t *expansion;
+
+ if (list == NULL)
+ return;
+
+ _token_list_trim_trailing_space (list);
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ while (parser->active && parser->active->marker == node)
+ parser->active = _active_list_pop (parser->active);
+
+ /* Find the expansion for node, which will replace all
+ * nodes from node to last, inclusive. */
+ expansion = _glcpp_parser_expand_node (parser, node, &last);
+ if (expansion) {
+ token_node_t *n;
+
+ for (n = node; n != last->next; n = n->next)
+ while (parser->active &&
+ parser->active->marker == n)
+ {
+ parser->active = _active_list_pop (parser->active);
+ }
+
+ parser->active = _active_list_push (parser->active,
+ node->token->value.str,
+ last->next);
+
+ /* Splice expansion into list, supporting a
+ * simple deletion if the expansion is
+ * empty. */
+ if (expansion->head) {
+ if (node_prev)
+ node_prev->next = expansion->head;
+ else
+ list->head = expansion->head;
+ expansion->tail->next = last->next;
+ if (last == list->tail)
+ list->tail = expansion->tail;
+ } else {
+ if (node_prev)
+ node_prev->next = last->next;
+ else
+ list->head = last->next;
+ if (last == list->tail)
+ list->tail = NULL;
+ }
+ } else {
+ node_prev = node;
+ }
+ node = node_prev ? node_prev->next : list->head;
+ }
+
+ while (parser->active)
+ parser->active = _active_list_pop (parser->active);
+
+ list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ if (list == NULL)
+ return;
+
+ _glcpp_parser_expand_token_list (parser, list);
+
+ _token_list_trim_trailing_space (list);
+
+ _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *identifier)
+{
+ /* According to the GLSL specification, macro names starting with "__"
+ * or "GL_" are reserved for future use. So, don't allow them.
+ */
+ if (strncmp(identifier, "__", 2) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+ }
+ if (strncmp(identifier, "GL_", 3) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+ }
+}
+
+static int
+_macro_equal (macro_t *a, macro_t *b)
+{
+ if (a->is_function != b->is_function)
+ return 0;
+
+ if (a->is_function) {
+ if (! _string_list_equal (a->parameters, b->parameters))
+ return 0;
+ }
+
+ return _token_list_equal_ignoring_space (a->replacements,
+ b->replacements);
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ if (loc != NULL)
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 0;
+ macro->parameters = NULL;
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ talloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ string_list_t *parameters,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = talloc (parser, macro_t);
+
+ macro->is_function = 1;
+ macro->parameters = talloc_steal (macro, parameters);
+ macro->identifier = talloc_strdup (macro, identifier);
+ macro->replacements = talloc_steal (macro, replacements);
+
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ talloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+ token_node_t *node;
+ int ret;
+
+ if (parser->lex_from_list == NULL) {
+ ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+ /* XXX: This ugly block of code exists for the sole
+ * purpose of converting a NEWLINE token into a SPACE
+ * token, but only in the case where we have seen a
+ * function-like macro name, but have not yet seen its
+ * closing parenthesis.
+ *
+ * There's perhaps a more compact way to do this with
+ * mid-rule actions in the grammar.
+ *
+ * I'm definitely not pleased with the complexity of
+ * this code here.
+ */
+ if (parser->newline_as_space)
+ {
+ if (ret == '(') {
+ parser->paren_count++;
+ } else if (ret == ')') {
+ parser->paren_count--;
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ } else if (ret == NEWLINE) {
+ ret = SPACE;
+ } else if (ret != SPACE) {
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ }
+ }
+ else if (parser->in_control_line)
+ {
+ if (ret == NEWLINE)
+ parser->in_control_line = 0;
+ }
+ else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+ ret == HASH_UNDEF || ret == HASH_IF ||
+ ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+ ret == HASH_ELIF || ret == HASH_ELSE ||
+ ret == HASH_ENDIF || ret == HASH)
+ {
+ parser->in_control_line = 1;
+ }
+ else if (ret == IDENTIFIER)
+ {
+ macro_t *macro;
+ macro = hash_table_find (parser->defines,
+ yylval->str);
+ if (macro && macro->is_function) {
+ parser->newline_as_space = 1;
+ parser->paren_count = 0;
+ }
+ }
+
+ return ret;
+ }
+
+ node = parser->lex_from_node;
+
+ if (node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ return NEWLINE;
+ }
+
+ *yylval = node->token->value;
+ ret = node->token->type;
+
+ parser->lex_from_node = node->next;
+
+ return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ assert (parser->lex_from_list == NULL);
+
+ /* Copy list, eliminating any space tokens. */
+ parser->lex_from_list = _token_list_create (parser);
+
+ for (node = list->head; node; node = node->next) {
+ if (node->token->type == SPACE)
+ continue;
+ _token_list_append (parser->lex_from_list, node->token);
+ }
+
+ talloc_free (list);
+
+ parser->lex_from_node = parser->lex_from_list->head;
+
+ /* It's possible the list consisted of nothing but whitespace. */
+ if (parser->lex_from_node == NULL) {
+ talloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition)
+{
+ skip_type_t current = SKIP_NO_SKIP;
+ skip_node_t *node;
+
+ if (parser->skip_stack)
+ current = parser->skip_stack->type;
+
+ node = talloc (parser, skip_node_t);
+ node->loc = *loc;
+
+ if (current == SKIP_NO_SKIP) {
+ if (condition)
+ node->type = SKIP_NO_SKIP;
+ else
+ node->type = SKIP_TO_ELSE;
+ } else {
+ node->type = SKIP_TO_ENDIF;
+ }
+
+ node->next = parser->skip_stack;
+ parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition)
+{
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "%s without #if\n", type);
+ return;
+ }
+
+ if (parser->skip_stack->type == SKIP_TO_ELSE) {
+ if (condition)
+ parser->skip_stack->type = SKIP_NO_SKIP;
+ } else {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+ skip_node_t *node;
+
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "#endif without #if\n");
+ return;
+ }
+
+ node = parser->skip_stack;
+ parser->skip_stack = node->next;
+ talloc_free (node);
+}
diff --git a/mesalib/src/glsl/glsl_lexer.cpp b/mesalib/src/glsl/glsl_lexer.cpp
index b923af2e5..04a434eb5 100644
--- a/mesalib/src/glsl/glsl_lexer.cpp
+++ b/mesalib/src/glsl/glsl_lexer.cpp
@@ -1,3722 +1,3713 @@
-#line 2 "glsl_lexer.cpp"
-
-#line 4 "glsl_lexer.cpp"
-
-#define YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
- are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition. This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state. The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE _mesa_glsl_restart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- #define YY_LESS_LINENO(n)
-
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- *yy_cp = yyg->yy_hold_char; \
- YY_RESTORE_YY_MORE_OFFSET \
- yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
- YY_DO_BEFORE_ACTION; /* set up yytext again */ \
- } \
- while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
- {
- FILE *yy_input_file;
-
- char *yy_ch_buf; /* input buffer */
- char *yy_buf_pos; /* current position in input buffer */
-
- /* Size of input buffer in bytes, not including room for EOB
- * characters.
- */
- yy_size_t yy_buf_size;
-
- /* Number of characters read into yy_ch_buf, not including EOB
- * characters.
- */
- int yy_n_chars;
-
- /* Whether we "own" the buffer - i.e., we know we created it,
- * and can realloc() it to grow it, and should free() it to
- * delete it.
- */
- int yy_is_our_buffer;
-
- /* Whether this is an "interactive" input source; if so, and
- * if we're using stdio for input, then we want to use getc()
- * instead of fread(), to make sure we stop fetching input after
- * each newline.
- */
- int yy_is_interactive;
-
- /* Whether we're considered to be at the beginning of a line.
- * If so, '^' rules will be active on the next match, otherwise
- * not.
- */
- int yy_at_bol;
-
- int yy_bs_lineno; /**< The line count. */
- int yy_bs_column; /**< The column count. */
-
- /* Whether to try to fill the input buffer when we reach the
- * end of it.
- */
- int yy_fill_buffer;
-
- int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
- /* When an EOF's been seen but there's still some text to process
- * then we mark the buffer as YY_EOF_PENDING, to indicate that we
- * shouldn't try reading from the input source any more. We might
- * still have a bunch of tokens to match, though, because of
- * possible backing-up.
- *
- * When we actually see the EOF, we change the status to "new"
- * (via _mesa_glsl_restart()), so that the user can continue scanning by
- * just pointing yyin at a new input file.
- */
-#define YY_BUFFER_EOF_PENDING 2
-
- };
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
- ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
- : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void _mesa_glsl_restart (FILE *input_file ,yyscan_t yyscanner );
-void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner );
-
-static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner );
-static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner );
-static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER _mesa_glsl__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE _mesa_glsl__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *_mesa_glsl_alloc (yy_size_t ,yyscan_t yyscanner );
-void *_mesa_glsl_realloc (void *,yy_size_t ,yyscan_t yyscanner );
-void _mesa_glsl_free (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer _mesa_glsl__create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- _mesa_glsl_ensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
- }
-
-#define yy_set_bol(at_bol) \
- { \
- if ( ! YY_CURRENT_BUFFER ){\
- _mesa_glsl_ensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
- }
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define _mesa_glsl_wrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
- yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
- yyg->yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 210
-#define YY_END_OF_BUFFER 211
-/* This struct is not used in this scanner,
- but its presence is necessary. */
-struct yy_trans_info
- {
- flex_int32_t yy_verify;
- flex_int32_t yy_nxt;
- };
-static yyconst flex_int16_t yy_accept[836] =
- { 0,
- 0, 0, 16, 16, 0, 0, 211, 209, 1, 21,
- 209, 209, 209, 209, 209, 209, 209, 209, 120, 118,
- 209, 209, 209, 208, 209, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 209, 1, 209, 210, 16,
- 20, 210, 19, 17, 18, 14, 13, 1, 102, 111,
- 103, 114, 108, 97, 110, 98, 117, 122, 109, 123,
- 120, 0, 0, 125, 120, 0, 118, 118, 106, 99,
- 101, 100, 107, 208, 115, 105, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 30, 208,
-
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 34, 208, 208, 61, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 116,
- 104, 1, 0, 0, 2, 0, 0, 0, 0, 16,
- 15, 19, 18, 0, 122, 121, 0, 123, 0, 124,
- 119, 112, 113, 208, 128, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 33, 208, 208, 208,
-
- 208, 208, 208, 208, 208, 208, 208, 26, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 62,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 0, 0, 0, 0, 15, 0, 122, 0, 121, 0,
- 123, 124, 119, 208, 208, 24, 208, 208, 175, 168,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 32,
- 131, 208, 208, 208, 208, 68, 208, 208, 136, 150,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-
- 208, 208, 147, 171, 49, 50, 51, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 134, 126, 208,
- 208, 27, 208, 208, 208, 208, 208, 208, 208, 46,
- 47, 48, 95, 208, 208, 0, 0, 0, 0, 0,
- 121, 208, 208, 28, 37, 38, 39, 208, 129, 208,
- 23, 208, 208, 208, 208, 158, 159, 160, 208, 127,
- 208, 151, 25, 161, 162, 163, 173, 155, 156, 157,
- 208, 208, 208, 63, 153, 208, 208, 208, 40, 41,
- 42, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-
- 208, 208, 208, 208, 208, 208, 208, 148, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 130, 208,
- 208, 170, 43, 44, 45, 208, 208, 31, 0, 0,
- 0, 0, 178, 208, 208, 176, 208, 208, 208, 149,
- 144, 181, 208, 208, 208, 208, 208, 208, 139, 208,
- 208, 208, 96, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 208, 208, 208, 208, 154, 135, 208, 208,
- 142, 36, 208, 208, 167, 69, 143, 94, 179, 137,
- 208, 208, 208, 208, 208, 208, 208, 208, 0, 0,
- 0, 0, 208, 208, 208, 138, 35, 208, 208, 208,
-
- 208, 208, 208, 182, 183, 184, 208, 208, 208, 208,
- 208, 172, 208, 208, 208, 208, 208, 208, 208, 208,
- 132, 208, 208, 208, 208, 208, 64, 208, 208, 65,
- 208, 0, 0, 0, 0, 0, 208, 66, 29, 145,
- 186, 187, 188, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 140, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 133, 190, 191, 192, 208,
- 208, 152, 208, 141, 0, 0, 6, 0, 0, 0,
- 12, 3, 22, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 185, 146, 67, 208, 208, 208, 208, 169,
-
- 208, 177, 174, 207, 71, 72, 73, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 0, 0, 0,
- 0, 0, 0, 0, 208, 208, 208, 189, 208, 208,
- 208, 208, 208, 82, 83, 84, 208, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, 208, 208, 193,
- 88, 89, 90, 208, 4, 0, 5, 0, 0, 0,
- 0, 0, 0, 208, 208, 208, 208, 208, 208, 208,
- 204, 208, 208, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 74, 208, 208, 208, 208, 208, 208, 0,
- 0, 0, 0, 208, 208, 205, 194, 208, 195, 208,
-
- 208, 208, 85, 208, 208, 208, 208, 208, 208, 208,
- 208, 208, 208, 208, 206, 208, 208, 91, 0, 0,
- 0, 196, 197, 208, 200, 208, 201, 208, 208, 70,
- 208, 208, 208, 164, 208, 165, 180, 208, 198, 199,
- 208, 208, 0, 0, 0, 208, 208, 208, 208, 75,
- 208, 76, 208, 208, 208, 208, 208, 0, 0, 0,
- 0, 208, 208, 86, 87, 208, 77, 208, 208, 78,
- 208, 92, 93, 0, 0, 0, 0, 208, 208, 208,
- 208, 208, 208, 0, 0, 0, 0, 208, 208, 208,
- 208, 208, 79, 0, 0, 0, 7, 0, 0, 202,
-
- 203, 208, 208, 208, 0, 0, 8, 0, 0, 208,
- 208, 166, 0, 0, 0, 80, 81, 0, 0, 0,
- 9, 0, 0, 10, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 11, 0
- } ;
-
-static yyconst flex_int32_t yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 5, 1, 6, 1, 7, 8, 1, 9,
- 10, 11, 12, 1, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 21, 21, 22, 22, 23, 1, 24,
- 25, 26, 1, 1, 27, 28, 29, 30, 31, 32,
- 33, 34, 34, 34, 34, 35, 34, 34, 34, 34,
- 34, 36, 37, 38, 39, 34, 34, 40, 34, 34,
- 1, 1, 1, 41, 42, 1, 43, 44, 45, 46,
-
- 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 34, 59, 60, 61, 62, 63, 64, 65,
- 66, 67, 1, 68, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
- } ;
-
-static yyconst flex_int32_t yy_meta[69] =
- { 0,
- 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
- 3, 3, 1, 1, 1, 1, 4, 4, 4, 4,
- 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
- 1, 5, 4, 4, 4, 4, 3, 3, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 1
- } ;
-
-static yyconst flex_int16_t yy_base[845] =
- { 0,
- 0, 67, 73, 0, 1210, 1209, 1211, 1214, 68, 1214,
- 1185, 1184, 134, 1183, 131, 132, 130, 1182, 146, 198,
- 129, 1181, 144, 0, 130, 113, 124, 141, 150, 126,
- 181, 1148, 159, 192, 118, 129, 146, 1142, 147, 174,
- 206, 192, 203, 222, 1153, 203, 221, 231, 1214, 260,
- 1214, 1187, 279, 1214, 0, 1214, 1214, 270, 1214, 1214,
- 1214, 1214, 1214, 1214, 1214, 1214, 1214, 244, 1214, 255,
- 139, 290, 307, 1214, 1214, 0, 0, 1214, 1176, 1214,
- 1214, 1214, 1175, 0, 1214, 1214, 1138, 1143, 1136, 1139,
- 1148, 1147, 1133, 1136, 1148, 144, 1142, 1129, 1126, 1140,
-
- 1126, 1123, 1123, 1129, 219, 193, 1123, 1134, 1119, 1125,
- 1129, 1130, 0, 1121, 1132, 278, 1131, 1126, 1106, 224,
- 1110, 1124, 1114, 232, 1107, 271, 1120, 1122, 1104, 1100,
- 1108, 1105, 1094, 1103, 234, 1101, 1107, 1102, 1105, 1093,
- 1096, 226, 145, 262, 1106, 1093, 1106, 263, 1099, 1214,
- 1214, 338, 331, 343, 1214, 1084, 1097, 1088, 1099, 345,
- 0, 334, 0, 345, 1214, 328, 391, 1214, 352, 398,
- 338, 1214, 1214, 1094, 0, 1085, 1089, 1099, 1096, 332,
- 1079, 1079, 1083, 320, 1094, 1091, 1091, 1089, 1086, 1077,
- 1084, 1070, 1068, 1081, 1066, 1083, 0, 1080, 1067, 1075,
-
- 1072, 1076, 1077, 1070, 1067, 1055, 1054, 1068, 1071, 1058,
- 1067, 1054, 1061, 1051, 364, 1057, 1060, 1050, 1058, 1046,
- 1050, 1041, 1056, 1046, 1037, 1056, 1039, 1037, 1048, 1037,
- 1032, 1030, 1044, 1029, 1031, 1028, 1040, 1039, 1042, 1023,
- 338, 1032, 1027, 1025, 1035, 1013, 403, 1032, 1034, 1022,
- 1014, 1018, 1030, 1013, 0, 415, 422, 439, 1214, 446,
- 455, 1214, 1214, 1008, 1019, 0, 1016, 406, 0, 0,
- 1009, 1007, 1009, 1004, 1013, 1001, 1019, 1007, 409, 0,
- 0, 1001, 1012, 1011, 1011, 0, 995, 429, 0, 0,
- 997, 460, 1005, 1006, 996, 990, 989, 990, 989, 989,
-
- 463, 984, 0, 0, 980, 979, 978, 980, 981, 986,
- 980, 976, 990, 985, 984, 983, 974, 977, 977, 969,
- 972, 967, 976, 981, 966, 979, 969, 0, 0, 976,
- 972, 0, 963, 963, 969, 959, 967, 466, 964, 0,
- 0, 0, 0, 953, 966, 965, 964, 961, 949, 472,
- 479, 961, 963, 0, 0, 0, 0, 949, 0, 949,
- 0, 948, 949, 943, 954, 0, 0, 0, 944, 0,
- 940, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 951, 487, 950, 0, 0, 948, 944, 940, 0, 0,
- 0, 932, 489, 494, 499, 937, 933, 939, 929, 927,
-
- 941, 925, 925, 939, 927, 939, 934, 0, 932, 929,
- 933, 916, 918, 925, 931, 926, 925, 912, 0, 914,
- 915, 0, 0, 0, 0, 912, 916, 0, 910, 963,
- 909, 912, 0, 900, 910, 0, 898, 898, 912, 0,
- 914, 0, 503, 926, 925, 924, 891, 890, 0, 908,
- 907, 902, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 890, 904, 890, 887, 0, 0, 893, 892,
- 0, 0, 890, 882, 0, 0, 0, 0, 0, 0,
- 879, 891, 506, 883, 890, 889, 886, 880, 873, 524,
- 889, 874, 869, 883, 881, 0, 0, 873, 896, 895,
-
- 894, 861, 860, 361, 365, 0, 873, 876, 874, 862,
- 858, 0, 871, 868, 867, 856, 855, 854, 519, 863,
- 0, 879, 878, 877, 844, 843, 0, 858, 844, 0,
- 855, 850, 547, 553, 898, 843, 851, 0, 0, 0,
- 870, 869, 0, 847, 850, 834, 842, 832, 840, 841,
- 841, 840, 825, 559, 838, 0, 839, 827, 826, 822,
- 850, 849, 848, 815, 814, 0, 848, 847, 0, 825,
- 828, 0, 562, 0, 814, 580, 1214, 587, 0, 607,
- 584, 1214, 0, 811, 810, 820, 820, 807, 822, 805,
- 820, 815, 0, 0, 0, 831, 830, 829, 796, 0,
-
- 796, 0, 0, 0, 502, 524, 820, 807, 810, 794,
- 793, 803, 803, 819, 818, 817, 784, 789, 615, 640,
- 550, 806, 796, 784, 782, 781, 792, 0, 795, 791,
- 793, 789, 775, 806, 805, 0, 787, 779, 770, 778,
- 768, 779, 775, 777, 775, 775, 762, 761, 772, 0,
- 791, 790, 0, 772, 1214, 555, 1214, 647, 0, 667,
- 785, 770, 752, 769, 768, 751, 743, 751, 741, 749,
- 0, 746, 745, 756, 739, 742, 757, 740, 753, 754,
- 751, 748, 757, 750, 749, 732, 731, 730, 741, 582,
- 754, 724, 734, 718, 717, 0, 745, 717, 743, 715,
-
- 719, 718, 0, 729, 732, 728, 730, 711, 725, 709,
- 710, 718, 701, 700, 0, 706, 705, 0, 728, 713,
- 706, 0, 0, 710, 0, 709, 0, 715, 714, 0,
- 690, 698, 688, 716, 695, 0, 0, 708, 0, 0,
- 707, 706, 746, 611, 696, 703, 702, 678, 677, 705,
- 677, 703, 689, 674, 691, 670, 669, 190, 613, 557,
- 667, 687, 686, 0, 0, 681, 0, 680, 686, 0,
- 671, 0, 0, 671, 590, 343, 672, 645, 644, 654,
- 635, 631, 612, 612, 604, 443, 635, 576, 575, 549,
- 25, 87, 0, 183, 500, 552, 1214, 636, 591, 0,
-
- 0, 196, 258, 254, 272, 609, 1214, 614, 598, 279,
- 284, 0, 336, 348, 671, 0, 0, 362, 672, 688,
- 1214, 394, 689, 1214, 408, 670, 691, 649, 651, 474,
- 476, 693, 694, 1214, 1214, 704, 707, 710, 530, 591,
- 713, 717, 720, 722
- } ;
-
-static yyconst flex_int16_t yy_def[845] =
- { 0,
- 835, 1, 835, 3, 836, 836, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 837, 835, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 838, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 839, 835, 840,
- 19, 835, 835, 835, 835, 841, 20, 835, 835, 835,
- 835, 835, 835, 837, 835, 835, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 842, 835, 838, 835, 835, 840, 835, 835, 835, 835,
- 841, 835, 835, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 835, 835, 835, 835, 842, 835, 835, 835, 835, 835,
- 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 835, 835, 835, 835, 835,
- 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
- 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
- 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 835, 835, 835, 835, 835, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 835, 835, 835, 835, 843, 835,
- 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 835, 835, 835,
- 843, 835, 835, 835, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 835, 835, 835, 835, 844, 835,
- 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 844,
- 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
-
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
- 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 835, 835, 835, 837, 837, 837, 837, 837,
- 837, 837, 837, 837, 837, 837, 837, 835, 835, 835,
- 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
- 837, 837, 837, 835, 835, 835, 835, 837, 837, 837,
- 837, 837, 837, 835, 835, 835, 835, 837, 837, 837,
- 837, 837, 837, 835, 835, 835, 835, 835, 835, 837,
-
- 837, 837, 837, 837, 835, 835, 835, 835, 835, 837,
- 837, 837, 835, 835, 835, 837, 837, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 0, 835, 835, 835, 835, 835,
- 835, 835, 835, 835
- } ;
-
-static yyconst flex_int16_t yy_nxt[1283] =
- { 0,
- 8, 9, 10, 9, 11, 8, 12, 13, 8, 8,
- 14, 15, 16, 17, 18, 19, 20, 20, 20, 20,
- 20, 20, 8, 21, 22, 23, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 25, 24, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 24, 24, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 44, 45, 24, 24, 24, 46, 47, 58,
- 803, 58, 48, 49, 50, 51, 50, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 52, 49, 53,
- 53, 53, 53, 53, 53, 54, 49, 49, 49, 55,
-
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 49, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 49, 61, 64, 804, 66, 68, 68, 68, 68, 68,
- 68, 68, 79, 80, 85, 65, 67, 87, 62, 70,
- 119, 71, 71, 71, 71, 71, 71, 72, 82, 83,
- 86, 121, 88, 89, 120, 122, 73, 74, 835, 101,
- 90, 102, 91, 93, 75, 76, 92, 94, 123, 126,
- 103, 758, 73, 74, 95, 241, 97, 96, 183, 184,
-
- 98, 110, 124, 835, 242, 127, 99, 75, 128, 111,
- 76, 70, 100, 77, 77, 77, 77, 77, 77, 77,
- 129, 112, 152, 104, 58, 805, 153, 150, 73, 74,
- 130, 105, 154, 155, 106, 195, 78, 107, 138, 113,
- 774, 139, 114, 108, 73, 74, 115, 116, 131, 196,
- 140, 117, 810, 142, 118, 132, 133, 141, 143, 78,
- 134, 160, 144, 160, 146, 145, 135, 136, 147, 137,
- 151, 58, 193, 58, 164, 165, 231, 156, 148, 213,
- 239, 240, 218, 194, 157, 167, 168, 214, 158, 219,
- 164, 165, 232, 159, 162, 162, 162, 162, 162, 162,
-
- 162, 167, 168, 70, 243, 72, 72, 72, 72, 72,
- 72, 72, 244, 248, 811, 221, 249, 812, 169, 169,
- 73, 74, 170, 170, 170, 170, 170, 170, 170, 222,
- 813, 205, 154, 155, 206, 207, 73, 74, 208, 152,
- 209, 58, 816, 153, 154, 155, 160, 817, 160, 162,
- 162, 162, 162, 162, 162, 162, 256, 256, 258, 259,
- 257, 257, 257, 257, 257, 257, 257, 170, 170, 170,
- 170, 170, 170, 170, 258, 259, 263, 156, 269, 274,
- 275, 305, 306, 307, 157, 333, 818, 546, 158, 156,
- 785, 548, 270, 159, 334, 819, 157, 547, 786, 263,
-
- 158, 549, 260, 260, 822, 159, 261, 261, 261, 261,
- 261, 261, 261, 170, 170, 170, 170, 170, 170, 170,
- 340, 341, 342, 355, 356, 357, 366, 367, 368, 262,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 796, 262, 374, 375, 376, 825,
- 350, 350, 797, 165, 351, 351, 351, 351, 351, 351,
- 351, 261, 261, 261, 261, 261, 261, 261, 826, 165,
- 261, 261, 261, 261, 261, 261, 261, 378, 379, 380,
- 389, 390, 391, 423, 424, 425, 168, 351, 351, 351,
- 351, 351, 351, 351, 351, 351, 351, 351, 351, 351,
-
- 351, 806, 168, 444, 445, 446, 454, 455, 456, 807,
- 259, 457, 458, 459, 447, 448, 460, 461, 462, 499,
- 500, 501, 522, 523, 524, 490, 259, 831, 639, 832,
- 502, 503, 68, 525, 526, 561, 562, 563, 640, 533,
- 534, 534, 534, 534, 534, 534, 564, 565, 576, 577,
- 641, 576, 577, 796, 576, 577, 656, 657, 775, 642,
- 643, 797, 578, 578, 578, 578, 578, 578, 580, 580,
- 580, 580, 580, 580, 580, 596, 597, 598, 614, 615,
- 616, 576, 577, 656, 657, 581, 579, 599, 576, 577,
- 617, 775, 808, 166, 802, 619, 620, 620, 620, 620,
-
- 620, 620, 578, 578, 578, 578, 578, 578, 576, 577,
- 806, 579, 759, 776, 759, 808, 656, 657, 807, 760,
- 622, 760, 580, 580, 580, 580, 580, 580, 580, 623,
- 658, 658, 658, 658, 658, 658, 798, 798, 801, 800,
- 624, 656, 657, 799, 799, 814, 776, 809, 656, 657,
- 829, 795, 829, 815, 659, 660, 660, 660, 660, 660,
- 660, 660, 658, 658, 658, 658, 658, 658, 656, 657,
- 809, 827, 820, 823, 794, 793, 792, 791, 828, 659,
- 821, 824, 660, 660, 660, 660, 660, 660, 660, 820,
- 823, 830, 827, 830, 833, 833, 790, 821, 824, 828,
-
- 789, 788, 834, 834, 56, 56, 56, 56, 56, 84,
- 84, 84, 163, 163, 163, 171, 171, 255, 787, 255,
- 255, 255, 621, 621, 690, 690, 784, 783, 782, 781,
- 780, 779, 778, 777, 773, 772, 771, 770, 769, 768,
- 767, 766, 765, 764, 763, 762, 761, 758, 757, 756,
- 755, 754, 753, 752, 751, 750, 749, 748, 747, 746,
- 745, 744, 743, 742, 741, 740, 739, 738, 737, 736,
- 735, 734, 733, 732, 731, 730, 729, 728, 727, 726,
- 725, 724, 723, 722, 721, 720, 719, 718, 717, 716,
- 715, 714, 713, 712, 711, 710, 709, 708, 707, 706,
-
- 705, 704, 703, 702, 701, 700, 699, 698, 697, 696,
- 695, 694, 693, 692, 691, 689, 688, 687, 686, 685,
- 684, 683, 682, 681, 680, 679, 678, 677, 676, 675,
- 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
- 664, 663, 662, 661, 655, 654, 653, 652, 651, 650,
- 649, 648, 647, 646, 645, 644, 638, 637, 636, 635,
- 634, 633, 632, 631, 630, 629, 628, 627, 626, 625,
- 618, 613, 612, 611, 610, 609, 608, 607, 606, 605,
- 604, 603, 602, 601, 600, 595, 594, 593, 592, 591,
- 590, 589, 588, 587, 586, 585, 584, 583, 582, 581,
-
- 575, 574, 573, 572, 571, 570, 569, 568, 567, 566,
- 560, 559, 558, 557, 556, 555, 554, 553, 552, 551,
- 550, 545, 544, 543, 542, 541, 540, 539, 538, 537,
- 536, 535, 532, 531, 530, 529, 528, 527, 521, 520,
- 519, 518, 517, 516, 515, 514, 513, 512, 511, 510,
- 509, 508, 507, 506, 505, 504, 498, 497, 496, 495,
- 494, 493, 492, 491, 490, 489, 488, 487, 486, 485,
- 484, 483, 482, 481, 480, 479, 478, 477, 476, 475,
- 474, 473, 472, 471, 470, 469, 468, 467, 466, 465,
- 464, 463, 453, 452, 451, 450, 449, 443, 442, 441,
-
- 440, 439, 438, 437, 436, 435, 434, 433, 432, 431,
- 430, 429, 428, 427, 426, 422, 421, 420, 419, 418,
- 417, 416, 415, 414, 413, 412, 411, 410, 409, 408,
- 407, 406, 405, 404, 403, 402, 401, 400, 399, 398,
- 397, 396, 395, 394, 393, 392, 388, 387, 386, 385,
- 384, 383, 382, 381, 377, 373, 372, 371, 370, 369,
- 365, 364, 363, 362, 361, 360, 359, 358, 354, 353,
- 352, 349, 348, 347, 346, 345, 344, 343, 339, 338,
- 337, 336, 335, 332, 331, 330, 329, 328, 327, 326,
- 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
-
- 315, 314, 313, 312, 311, 310, 309, 308, 304, 303,
- 302, 301, 300, 299, 298, 297, 296, 295, 294, 293,
- 292, 291, 290, 289, 288, 287, 286, 285, 284, 283,
- 282, 281, 280, 279, 278, 277, 276, 273, 272, 271,
- 268, 267, 266, 265, 264, 254, 253, 252, 251, 250,
- 247, 246, 245, 238, 237, 236, 235, 234, 233, 230,
- 229, 228, 227, 226, 225, 224, 223, 220, 217, 216,
- 215, 212, 211, 210, 204, 203, 202, 201, 200, 199,
- 198, 197, 192, 191, 190, 189, 188, 187, 186, 185,
- 182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
-
- 172, 161, 149, 125, 109, 81, 69, 63, 60, 59,
- 835, 57, 57, 7, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835
- } ;
-
-static yyconst flex_int16_t yy_chk[1283] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 9,
- 791, 9, 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 13, 15, 792, 16, 17, 17, 17, 17, 17,
- 17, 17, 21, 21, 25, 15, 16, 26, 13, 19,
- 35, 19, 19, 19, 19, 19, 19, 19, 23, 23,
- 25, 36, 26, 26, 35, 36, 19, 19, 71, 30,
- 27, 30, 27, 28, 19, 19, 27, 28, 37, 39,
- 30, 758, 19, 19, 28, 143, 29, 28, 96, 96,
-
- 29, 33, 37, 71, 143, 39, 29, 19, 39, 33,
- 19, 20, 29, 20, 20, 20, 20, 20, 20, 20,
- 40, 33, 47, 31, 47, 794, 47, 46, 20, 20,
- 40, 31, 48, 48, 31, 106, 20, 31, 42, 34,
- 758, 42, 34, 31, 20, 20, 34, 34, 41, 106,
- 42, 34, 802, 43, 34, 41, 41, 42, 43, 20,
- 41, 50, 43, 50, 44, 43, 41, 41, 44, 41,
- 46, 58, 105, 58, 68, 68, 135, 48, 44, 120,
- 142, 142, 124, 105, 48, 70, 70, 120, 48, 124,
- 68, 68, 135, 48, 53, 53, 53, 53, 53, 53,
-
- 53, 70, 70, 72, 144, 72, 72, 72, 72, 72,
- 72, 72, 144, 148, 803, 126, 148, 804, 73, 73,
- 72, 72, 73, 73, 73, 73, 73, 73, 73, 126,
- 805, 116, 153, 153, 116, 116, 72, 72, 116, 152,
- 116, 152, 810, 152, 154, 154, 160, 811, 160, 162,
- 162, 162, 162, 162, 162, 162, 164, 164, 166, 166,
- 164, 164, 164, 164, 164, 164, 164, 169, 169, 169,
- 169, 169, 169, 169, 166, 166, 171, 153, 180, 184,
- 184, 215, 215, 215, 153, 241, 813, 504, 153, 154,
- 776, 505, 180, 153, 241, 814, 154, 504, 776, 171,
-
- 154, 505, 167, 167, 818, 154, 167, 167, 167, 167,
- 167, 167, 167, 170, 170, 170, 170, 170, 170, 170,
- 247, 247, 247, 268, 268, 268, 279, 279, 279, 170,
- 256, 256, 256, 256, 256, 256, 256, 257, 257, 257,
- 257, 257, 257, 257, 786, 170, 288, 288, 288, 822,
- 258, 258, 786, 257, 258, 258, 258, 258, 258, 258,
- 258, 260, 260, 260, 260, 260, 260, 260, 825, 257,
- 261, 261, 261, 261, 261, 261, 261, 292, 292, 292,
- 301, 301, 301, 338, 338, 338, 261, 350, 350, 350,
- 350, 350, 350, 350, 351, 351, 351, 351, 351, 351,
-
- 351, 795, 261, 382, 382, 382, 393, 393, 393, 795,
- 351, 394, 394, 394, 382, 382, 395, 395, 395, 443,
- 443, 443, 483, 483, 483, 490, 351, 830, 605, 831,
- 443, 443, 839, 483, 483, 519, 519, 519, 605, 490,
- 490, 490, 490, 490, 490, 490, 519, 519, 533, 533,
- 606, 621, 621, 796, 534, 534, 656, 656, 760, 606,
- 606, 796, 533, 533, 533, 533, 533, 533, 534, 534,
- 534, 534, 534, 534, 534, 554, 554, 554, 573, 573,
- 573, 576, 576, 690, 690, 581, 533, 554, 578, 578,
- 573, 775, 799, 840, 790, 576, 576, 576, 576, 576,
-
- 576, 576, 578, 578, 578, 578, 578, 578, 580, 580,
- 806, 533, 744, 760, 759, 808, 619, 619, 806, 744,
- 581, 759, 580, 580, 580, 580, 580, 580, 580, 581,
- 619, 619, 619, 619, 619, 619, 787, 798, 789, 788,
- 581, 620, 620, 787, 798, 809, 775, 799, 658, 658,
- 828, 785, 829, 809, 619, 620, 620, 620, 620, 620,
- 620, 620, 658, 658, 658, 658, 658, 658, 660, 660,
- 808, 826, 815, 819, 784, 783, 782, 781, 826, 619,
- 815, 819, 660, 660, 660, 660, 660, 660, 660, 820,
- 823, 828, 827, 829, 832, 833, 780, 820, 823, 827,
-
- 779, 778, 832, 833, 836, 836, 836, 836, 836, 837,
- 837, 837, 838, 838, 838, 841, 841, 842, 777, 842,
- 842, 842, 843, 843, 844, 844, 774, 771, 769, 768,
- 766, 763, 762, 761, 757, 756, 755, 754, 753, 752,
- 751, 750, 749, 748, 747, 746, 745, 743, 742, 741,
- 738, 735, 734, 733, 732, 731, 729, 728, 726, 724,
- 721, 720, 719, 717, 716, 714, 713, 712, 711, 710,
- 709, 708, 707, 706, 705, 704, 702, 701, 700, 699,
- 698, 697, 695, 694, 693, 692, 691, 689, 688, 687,
- 686, 685, 684, 683, 682, 681, 680, 679, 678, 677,
-
- 676, 675, 674, 673, 672, 670, 669, 668, 667, 666,
- 665, 664, 663, 662, 661, 654, 652, 651, 649, 648,
- 647, 646, 645, 644, 643, 642, 641, 640, 639, 638,
- 637, 635, 634, 633, 632, 631, 630, 629, 627, 626,
- 625, 624, 623, 622, 618, 617, 616, 615, 614, 613,
- 612, 611, 610, 609, 608, 607, 601, 599, 598, 597,
- 596, 592, 591, 590, 589, 588, 587, 586, 585, 584,
- 575, 571, 570, 568, 567, 565, 564, 563, 562, 561,
- 560, 559, 558, 557, 555, 553, 552, 551, 550, 549,
- 548, 547, 546, 545, 544, 542, 541, 537, 536, 535,
-
- 532, 531, 529, 528, 526, 525, 524, 523, 522, 520,
- 518, 517, 516, 515, 514, 513, 511, 510, 509, 508,
- 507, 503, 502, 501, 500, 499, 498, 495, 494, 493,
- 492, 491, 489, 488, 487, 486, 485, 484, 482, 481,
- 474, 473, 470, 469, 466, 465, 464, 463, 452, 451,
- 450, 448, 447, 446, 445, 444, 441, 439, 438, 437,
- 435, 434, 432, 431, 430, 429, 427, 426, 421, 420,
- 418, 417, 416, 415, 414, 413, 412, 411, 410, 409,
- 407, 406, 405, 404, 403, 402, 401, 400, 399, 398,
- 397, 396, 392, 388, 387, 386, 383, 381, 371, 369,
-
- 365, 364, 363, 362, 360, 358, 353, 352, 349, 348,
- 347, 346, 345, 344, 339, 337, 336, 335, 334, 333,
- 331, 330, 327, 326, 325, 324, 323, 322, 321, 320,
- 319, 318, 317, 316, 315, 314, 313, 312, 311, 310,
- 309, 308, 307, 306, 305, 302, 300, 299, 298, 297,
- 296, 295, 294, 293, 291, 287, 285, 284, 283, 282,
- 278, 277, 276, 275, 274, 273, 272, 271, 267, 265,
- 264, 254, 253, 252, 251, 250, 249, 248, 246, 245,
- 244, 243, 242, 240, 239, 238, 237, 236, 235, 234,
- 233, 232, 231, 230, 229, 228, 227, 226, 225, 224,
-
- 223, 222, 221, 220, 219, 218, 217, 216, 214, 213,
- 212, 211, 210, 209, 208, 207, 206, 205, 204, 203,
- 202, 201, 200, 199, 198, 196, 195, 194, 193, 192,
- 191, 190, 189, 188, 187, 186, 185, 183, 182, 181,
- 179, 178, 177, 176, 174, 159, 158, 157, 156, 149,
- 147, 146, 145, 141, 140, 139, 138, 137, 136, 134,
- 133, 132, 131, 130, 129, 128, 127, 125, 123, 122,
- 121, 119, 118, 117, 115, 114, 112, 111, 110, 109,
- 108, 107, 104, 103, 102, 101, 100, 99, 98, 97,
- 95, 94, 93, 92, 91, 90, 89, 88, 87, 83,
-
- 79, 52, 45, 38, 32, 22, 18, 14, 12, 11,
- 7, 6, 5, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
- 835, 835
- } ;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "glsl_lexer.lpp"
-#line 2 "glsl_lexer.lpp"
-/*
- * Copyright © 2008, 2009 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 <ctype.h>
-#include "strtod.h"
-#include "ast.h"
-#include "glsl_parser_extras.h"
-#include "glsl_parser.h"
-
-#define YY_USER_ACTION \
- do { \
- yylloc->source = 0; \
- yylloc->first_column = yycolumn + 1; \
- yylloc->first_line = yylineno + 1; \
- yycolumn += yyleng; \
- } while(0);
-
-#define YY_USER_INIT yylineno = 0; yycolumn = 0;
-
-#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
-
-/* A macro for handling reserved words and keywords across language versions.
- *
- * Certain words start out as identifiers, become reserved words in
- * later language revisions, and finally become language keywords.
- *
- * For example, consider the following lexer rule:
- * samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER)
- *
- * This means that "samplerBuffer" will be treated as:
- * - a keyword (SAMPLERBUFFER token) ...in GLSL >= 1.40
- * - a reserved word - error ...in GLSL >= 1.30
- * - an identifier ...in GLSL < 1.30
- */
-#define KEYWORD(reserved_version, allowed_version, token) \
- do { \
- if (yyextra->language_version >= allowed_version) { \
- return token; \
- } else if (yyextra->language_version >= reserved_version) { \
- _mesa_glsl_error(yylloc, yyextra, \
- "Illegal use of reserved word `%s'", yytext); \
- return ERROR_TOK; \
- } else { \
- yylval->identifier = strdup(yytext); \
- return IDENTIFIER; \
- } \
- } while (0)
-
-/* The ES macro can be used in KEYWORD checks:
- *
- * word KEYWORD(110 || ES, 400, TOKEN)
- * ...means the word is reserved in GLSL ES 1.00, while
- *
- * word KEYWORD(110, 130 || ES, TOKEN)
- * ...means the word is a legal keyword in GLSL ES 1.00.
- */
-#define ES yyextra->es_shader
-
-#line 1080 "glsl_lexer.cpp"
-
-#define INITIAL 0
-#define PP 1
-#define PRAGMA 2
-
-#define YY_EXTRA_TYPE struct _mesa_glsl_parse_state *
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
- {
-
- /* User-defined. Not touched by flex. */
- YY_EXTRA_TYPE yyextra_r;
-
- /* The rest are the same as the globals declared in the non-reentrant scanner. */
- FILE *yyin_r, *yyout_r;
- size_t yy_buffer_stack_top; /**< index of top of stack. */
- size_t yy_buffer_stack_max; /**< capacity of stack. */
- YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
- char yy_hold_char;
- int yy_n_chars;
- int yyleng_r;
- char *yy_c_buf_p;
- int yy_init;
- int yy_start;
- int yy_did_buffer_switch_on_eof;
- int yy_start_stack_ptr;
- int yy_start_stack_depth;
- int *yy_start_stack;
- yy_state_type yy_last_accepting_state;
- char* yy_last_accepting_cpos;
-
- int yylineno_r;
- int yy_flex_debug_r;
-
- char *yytext_r;
- int yy_more_flag;
- int yy_more_len;
-
- YYSTYPE * yylval_r;
-
- YYLTYPE * yylloc_r;
-
- }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
- /* This must go here because YYSTYPE and YYLTYPE are included
- * from bison output in section 1.*/
- # define yylval yyg->yylval_r
-
- # define yylloc yyg->yylloc_r
-
-int _mesa_glsl_lex_init (yyscan_t* scanner);
-
-int _mesa_glsl_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
- These are made visible to non-reentrant scanners for convenience. */
-
-int _mesa_glsl_lex_destroy (yyscan_t yyscanner );
-
-int _mesa_glsl_get_debug (yyscan_t yyscanner );
-
-void _mesa_glsl_set_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner );
-
-void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *_mesa_glsl_get_in (yyscan_t yyscanner );
-
-void _mesa_glsl_set_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *_mesa_glsl_get_out (yyscan_t yyscanner );
-
-void _mesa_glsl_set_out (FILE * out_str ,yyscan_t yyscanner );
-
-int _mesa_glsl_get_leng (yyscan_t yyscanner );
-
-char *_mesa_glsl_get_text (yyscan_t yyscanner );
-
-int _mesa_glsl_get_lineno (yyscan_t yyscanner );
-
-void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner );
-
-YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner );
-
-void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
-
- YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner );
-
- void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int _mesa_glsl_wrap (yyscan_t yyscanner );
-#else
-extern int _mesa_glsl_wrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
- { \
- int c = '*'; \
- size_t n; \
- for ( n = 0; n < max_size && \
- (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
- buf[n] = (char) c; \
- if ( c == '\n' ) \
- buf[n++] = (char) c; \
- if ( c == EOF && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- result = n; \
- } \
- else \
- { \
- errno=0; \
- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
- { \
- if( errno != EINTR) \
- { \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- break; \
- } \
- errno=0; \
- clearerr(yyin); \
- } \
- }\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int _mesa_glsl_lex \
- (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
-
-#define YY_DECL int _mesa_glsl_lex \
- (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
- if ( yyleng > 0 ) \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
- (yytext[yyleng - 1] == '\n'); \
- YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-#line 95 "glsl_lexer.lpp"
-
-
-#line 1322 "glsl_lexer.cpp"
-
- yylval = yylval_param;
-
- yylloc = yylloc_param;
-
- if ( !yyg->yy_init )
- {
- yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
- YY_USER_INIT;
-#endif
-
- if ( ! yyg->yy_start )
- yyg->yy_start = 1; /* first start state */
-
- if ( ! yyin )
- yyin = stdin;
-
- if ( ! yyout )
- yyout = stdout;
-
- if ( ! YY_CURRENT_BUFFER ) {
- _mesa_glsl_ensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- _mesa_glsl__load_buffer_state(yyscanner );
- }
-
- while ( 1 ) /* loops until end-of-file is reached */
- {
- yy_cp = yyg->yy_c_buf_p;
-
- /* Support of yytext. */
- *yy_cp = yyg->yy_hold_char;
-
- /* yy_bp points to the position in yy_ch_buf of the start of
- * the current run.
- */
- yy_bp = yy_cp;
-
- yy_current_state = yyg->yy_start;
- yy_current_state += YY_AT_BOL();
-yy_match:
- do
- {
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 836 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_current_state != 835 );
- yy_cp = yyg->yy_last_accepting_cpos;
- yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
- yy_act = yy_accept[yy_current_state];
-
- YY_DO_BEFORE_ACTION;
-
-do_action: /* This label is used only to access EOF actions. */
-
- switch ( yy_act )
- { /* beginning of action switch */
- case 0: /* must back up */
- /* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = yyg->yy_hold_char;
- yy_cp = yyg->yy_last_accepting_cpos;
- yy_current_state = yyg->yy_last_accepting_state;
- goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 97 "glsl_lexer.lpp"
-;
- YY_BREAK
-/* Preprocessor tokens. */
-case 2:
-*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
-yyg->yy_c_buf_p = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 100 "glsl_lexer.lpp"
-;
- YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 101 "glsl_lexer.lpp"
-{ BEGIN PP; return VERSION; }
- YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 102 "glsl_lexer.lpp"
-{ BEGIN PP; return EXTENSION; }
- YY_BREAK
-case 5:
-*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
-yyg->yy_c_buf_p = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 103 "glsl_lexer.lpp"
-{
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
- yylloc->source = strtol(ptr, NULL, 0);
- }
- YY_BREAK
-case 6:
-*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
-yyg->yy_c_buf_p = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 118 "glsl_lexer.lpp"
-{
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
- }
- YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 132 "glsl_lexer.lpp"
-{
- BEGIN PP;
- return PRAGMA_DEBUG_ON;
- }
- YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 136 "glsl_lexer.lpp"
-{
- BEGIN PP;
- return PRAGMA_DEBUG_OFF;
- }
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 140 "glsl_lexer.lpp"
-{
- BEGIN PP;
- return PRAGMA_OPTIMIZE_ON;
- }
- YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 144 "glsl_lexer.lpp"
-{
- BEGIN PP;
- return PRAGMA_OPTIMIZE_OFF;
- }
- YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 148 "glsl_lexer.lpp"
-{
- BEGIN PP;
- return PRAGMA_INVARIANT_ALL;
- }
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 152 "glsl_lexer.lpp"
-{ BEGIN PRAGMA; }
- YY_BREAK
-case 13:
-/* rule 13 can match eol */
-YY_RULE_SETUP
-#line 154 "glsl_lexer.lpp"
-{ BEGIN 0; yylineno++; yycolumn = 0; }
- YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 155 "glsl_lexer.lpp"
-{ }
- YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 157 "glsl_lexer.lpp"
-{ }
- YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 158 "glsl_lexer.lpp"
-{ }
- YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 159 "glsl_lexer.lpp"
-return COLON;
- YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 160 "glsl_lexer.lpp"
-{
- yylval->identifier = strdup(yytext);
- return IDENTIFIER;
- }
- YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 164 "glsl_lexer.lpp"
-{
- yylval->n = strtol(yytext, NULL, 10);
- return INTCONSTANT;
- }
- YY_BREAK
-case 20:
-/* rule 20 can match eol */
-YY_RULE_SETUP
-#line 168 "glsl_lexer.lpp"
-{ BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
- YY_BREAK
-case 21:
-/* rule 21 can match eol */
-YY_RULE_SETUP
-#line 170 "glsl_lexer.lpp"
-{ yylineno++; yycolumn = 0; }
- YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 172 "glsl_lexer.lpp"
-return ATTRIBUTE;
- YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 173 "glsl_lexer.lpp"
-return CONST_TOK;
- YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 174 "glsl_lexer.lpp"
-return BOOL_TOK;
- YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 175 "glsl_lexer.lpp"
-return FLOAT_TOK;
- YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 176 "glsl_lexer.lpp"
-return INT_TOK;
- YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 177 "glsl_lexer.lpp"
-KEYWORD(130, 130, UINT_TOK);
- YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 179 "glsl_lexer.lpp"
-return BREAK;
- YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 180 "glsl_lexer.lpp"
-return CONTINUE;
- YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 181 "glsl_lexer.lpp"
-return DO;
- YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 182 "glsl_lexer.lpp"
-return WHILE;
- YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 183 "glsl_lexer.lpp"
-return ELSE;
- YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 184 "glsl_lexer.lpp"
-return FOR;
- YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 185 "glsl_lexer.lpp"
-return IF;
- YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 186 "glsl_lexer.lpp"
-return DISCARD;
- YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 187 "glsl_lexer.lpp"
-return RETURN;
- YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 189 "glsl_lexer.lpp"
-return BVEC2;
- YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 190 "glsl_lexer.lpp"
-return BVEC3;
- YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 191 "glsl_lexer.lpp"
-return BVEC4;
- YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 192 "glsl_lexer.lpp"
-return IVEC2;
- YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 193 "glsl_lexer.lpp"
-return IVEC3;
- YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 194 "glsl_lexer.lpp"
-return IVEC4;
- YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 195 "glsl_lexer.lpp"
-KEYWORD(130, 130, UVEC2);
- YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 196 "glsl_lexer.lpp"
-KEYWORD(130, 130, UVEC3);
- YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 197 "glsl_lexer.lpp"
-KEYWORD(130, 130, UVEC4);
- YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 198 "glsl_lexer.lpp"
-return VEC2;
- YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 199 "glsl_lexer.lpp"
-return VEC3;
- YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 200 "glsl_lexer.lpp"
-return VEC4;
- YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 201 "glsl_lexer.lpp"
-return MAT2X2;
- YY_BREAK
-case 50:
-YY_RULE_SETUP
-#line 202 "glsl_lexer.lpp"
-return MAT3X3;
- YY_BREAK
-case 51:
-YY_RULE_SETUP
-#line 203 "glsl_lexer.lpp"
-return MAT4X4;
- YY_BREAK
-case 52:
-YY_RULE_SETUP
-#line 204 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT2X2);
- YY_BREAK
-case 53:
-YY_RULE_SETUP
-#line 205 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT2X3);
- YY_BREAK
-case 54:
-YY_RULE_SETUP
-#line 206 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT2X4);
- YY_BREAK
-case 55:
-YY_RULE_SETUP
-#line 207 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT3X2);
- YY_BREAK
-case 56:
-YY_RULE_SETUP
-#line 208 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT3X3);
- YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 209 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT3X4);
- YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 210 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT4X2);
- YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 211 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT4X3);
- YY_BREAK
-case 60:
-YY_RULE_SETUP
-#line 212 "glsl_lexer.lpp"
-KEYWORD(120, 120, MAT4X4);
- YY_BREAK
-case 61:
-YY_RULE_SETUP
-#line 214 "glsl_lexer.lpp"
-return IN_TOK;
- YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 215 "glsl_lexer.lpp"
-return OUT_TOK;
- YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 216 "glsl_lexer.lpp"
-return INOUT_TOK;
- YY_BREAK
-case 64:
-YY_RULE_SETUP
-#line 217 "glsl_lexer.lpp"
-return UNIFORM;
- YY_BREAK
-case 65:
-YY_RULE_SETUP
-#line 218 "glsl_lexer.lpp"
-return VARYING;
- YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 219 "glsl_lexer.lpp"
-KEYWORD(120, 120, CENTROID);
- YY_BREAK
-case 67:
-YY_RULE_SETUP
-#line 220 "glsl_lexer.lpp"
-KEYWORD(120 || ES, 120 || ES, INVARIANT);
- YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 221 "glsl_lexer.lpp"
-KEYWORD(130 || ES, 130, FLAT);
- YY_BREAK
-case 69:
-YY_RULE_SETUP
-#line 222 "glsl_lexer.lpp"
-KEYWORD(130, 130, SMOOTH);
- YY_BREAK
-case 70:
-YY_RULE_SETUP
-#line 223 "glsl_lexer.lpp"
-KEYWORD(130, 130, NOPERSPECTIVE);
- YY_BREAK
-case 71:
-YY_RULE_SETUP
-#line 225 "glsl_lexer.lpp"
-return SAMPLER1D;
- YY_BREAK
-case 72:
-YY_RULE_SETUP
-#line 226 "glsl_lexer.lpp"
-return SAMPLER2D;
- YY_BREAK
-case 73:
-YY_RULE_SETUP
-#line 227 "glsl_lexer.lpp"
-return SAMPLER3D;
- YY_BREAK
-case 74:
-YY_RULE_SETUP
-#line 228 "glsl_lexer.lpp"
-return SAMPLERCUBE;
- YY_BREAK
-case 75:
-YY_RULE_SETUP
-#line 229 "glsl_lexer.lpp"
-KEYWORD(130, 130, SAMPLER1DARRAY);
- YY_BREAK
-case 76:
-YY_RULE_SETUP
-#line 230 "glsl_lexer.lpp"
-KEYWORD(130, 130, SAMPLER2DARRAY);
- YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 231 "glsl_lexer.lpp"
-return SAMPLER1DSHADOW;
- YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 232 "glsl_lexer.lpp"
-return SAMPLER2DSHADOW;
- YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 233 "glsl_lexer.lpp"
-KEYWORD(130, 130, SAMPLERCUBESHADOW);
- YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 234 "glsl_lexer.lpp"
-KEYWORD(130, 130, SAMPLER1DARRAYSHADOW);
- YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 235 "glsl_lexer.lpp"
-KEYWORD(130, 130, SAMPLER2DARRAYSHADOW);
- YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 236 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLER1D);
- YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 237 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLER2D);
- YY_BREAK
-case 84:
-YY_RULE_SETUP
-#line 238 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLER3D);
- YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 239 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLERCUBE);
- YY_BREAK
-case 86:
-YY_RULE_SETUP
-#line 240 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLER1DARRAY);
- YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 241 "glsl_lexer.lpp"
-KEYWORD(130, 130, ISAMPLER2DARRAY);
- YY_BREAK
-case 88:
-YY_RULE_SETUP
-#line 242 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLER1D);
- YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 243 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLER2D);
- YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 244 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLER3D);
- YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 245 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLERCUBE);
- YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 246 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLER1DARRAY);
- YY_BREAK
-case 93:
-YY_RULE_SETUP
-#line 247 "glsl_lexer.lpp"
-KEYWORD(130, 130, USAMPLER2DARRAY);
- YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 250 "glsl_lexer.lpp"
-return STRUCT;
- YY_BREAK
-case 95:
-YY_RULE_SETUP
-#line 251 "glsl_lexer.lpp"
-return VOID_TOK;
- YY_BREAK
-case 96:
-YY_RULE_SETUP
-#line 253 "glsl_lexer.lpp"
-{
- if ((yyextra->language_version >= 140)
- || yyextra->ARB_explicit_attrib_location_enable
- || (yyextra->ARB_fragment_coord_conventions_enable)){
- return LAYOUT_TOK;
- } else {
- yylval->identifier = strdup(yytext);
- return IDENTIFIER;
- }
- }
- YY_BREAK
-case 97:
-YY_RULE_SETUP
-#line 264 "glsl_lexer.lpp"
-return INC_OP;
- YY_BREAK
-case 98:
-YY_RULE_SETUP
-#line 265 "glsl_lexer.lpp"
-return DEC_OP;
- YY_BREAK
-case 99:
-YY_RULE_SETUP
-#line 266 "glsl_lexer.lpp"
-return LE_OP;
- YY_BREAK
-case 100:
-YY_RULE_SETUP
-#line 267 "glsl_lexer.lpp"
-return GE_OP;
- YY_BREAK
-case 101:
-YY_RULE_SETUP
-#line 268 "glsl_lexer.lpp"
-return EQ_OP;
- YY_BREAK
-case 102:
-YY_RULE_SETUP
-#line 269 "glsl_lexer.lpp"
-return NE_OP;
- YY_BREAK
-case 103:
-YY_RULE_SETUP
-#line 270 "glsl_lexer.lpp"
-return AND_OP;
- YY_BREAK
-case 104:
-YY_RULE_SETUP
-#line 271 "glsl_lexer.lpp"
-return OR_OP;
- YY_BREAK
-case 105:
-YY_RULE_SETUP
-#line 272 "glsl_lexer.lpp"
-return XOR_OP;
- YY_BREAK
-case 106:
-YY_RULE_SETUP
-#line 273 "glsl_lexer.lpp"
-return LEFT_OP;
- YY_BREAK
-case 107:
-YY_RULE_SETUP
-#line 274 "glsl_lexer.lpp"
-return RIGHT_OP;
- YY_BREAK
-case 108:
-YY_RULE_SETUP
-#line 276 "glsl_lexer.lpp"
-return MUL_ASSIGN;
- YY_BREAK
-case 109:
-YY_RULE_SETUP
-#line 277 "glsl_lexer.lpp"
-return DIV_ASSIGN;
- YY_BREAK
-case 110:
-YY_RULE_SETUP
-#line 278 "glsl_lexer.lpp"
-return ADD_ASSIGN;
- YY_BREAK
-case 111:
-YY_RULE_SETUP
-#line 279 "glsl_lexer.lpp"
-return MOD_ASSIGN;
- YY_BREAK
-case 112:
-YY_RULE_SETUP
-#line 280 "glsl_lexer.lpp"
-return LEFT_ASSIGN;
- YY_BREAK
-case 113:
-YY_RULE_SETUP
-#line 281 "glsl_lexer.lpp"
-return RIGHT_ASSIGN;
- YY_BREAK
-case 114:
-YY_RULE_SETUP
-#line 282 "glsl_lexer.lpp"
-return AND_ASSIGN;
- YY_BREAK
-case 115:
-YY_RULE_SETUP
-#line 283 "glsl_lexer.lpp"
-return XOR_ASSIGN;
- YY_BREAK
-case 116:
-YY_RULE_SETUP
-#line 284 "glsl_lexer.lpp"
-return OR_ASSIGN;
- YY_BREAK
-case 117:
-YY_RULE_SETUP
-#line 285 "glsl_lexer.lpp"
-return SUB_ASSIGN;
- YY_BREAK
-case 118:
-YY_RULE_SETUP
-#line 287 "glsl_lexer.lpp"
-{
- yylval->n = strtol(yytext, NULL, 10);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
- YY_BREAK
-case 119:
-YY_RULE_SETUP
-#line 291 "glsl_lexer.lpp"
-{
- yylval->n = strtol(yytext + 2, NULL, 16);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
- YY_BREAK
-case 120:
-YY_RULE_SETUP
-#line 295 "glsl_lexer.lpp"
-{
- yylval->n = strtol(yytext, NULL, 8);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
- YY_BREAK
-case 121:
-YY_RULE_SETUP
-#line 300 "glsl_lexer.lpp"
-{
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
- YY_BREAK
-case 122:
-YY_RULE_SETUP
-#line 304 "glsl_lexer.lpp"
-{
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
- YY_BREAK
-case 123:
-YY_RULE_SETUP
-#line 308 "glsl_lexer.lpp"
-{
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
- YY_BREAK
-case 124:
-YY_RULE_SETUP
-#line 312 "glsl_lexer.lpp"
-{
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
- YY_BREAK
-case 125:
-YY_RULE_SETUP
-#line 316 "glsl_lexer.lpp"
-{
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
- YY_BREAK
-case 126:
-YY_RULE_SETUP
-#line 321 "glsl_lexer.lpp"
-{
- yylval->n = 1;
- return BOOLCONSTANT;
- }
- YY_BREAK
-case 127:
-YY_RULE_SETUP
-#line 325 "glsl_lexer.lpp"
-{
- yylval->n = 0;
- return BOOLCONSTANT;
- }
- YY_BREAK
-/* Reserved words in GLSL 1.10. */
-case 128:
-YY_RULE_SETUP
-#line 332 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, ASM);
- YY_BREAK
-case 129:
-YY_RULE_SETUP
-#line 333 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, CLASS);
- YY_BREAK
-case 130:
-YY_RULE_SETUP
-#line 334 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, UNION);
- YY_BREAK
-case 131:
-YY_RULE_SETUP
-#line 335 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, ENUM);
- YY_BREAK
-case 132:
-YY_RULE_SETUP
-#line 336 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, TYPEDEF);
- YY_BREAK
-case 133:
-YY_RULE_SETUP
-#line 337 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, TEMPLATE);
- YY_BREAK
-case 134:
-YY_RULE_SETUP
-#line 338 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, THIS);
- YY_BREAK
-case 135:
-YY_RULE_SETUP
-#line 339 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, PACKED_TOK);
- YY_BREAK
-case 136:
-YY_RULE_SETUP
-#line 340 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, GOTO);
- YY_BREAK
-case 137:
-YY_RULE_SETUP
-#line 341 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 130, SWITCH);
- YY_BREAK
-case 138:
-YY_RULE_SETUP
-#line 342 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 130, DEFAULT);
- YY_BREAK
-case 139:
-YY_RULE_SETUP
-#line 343 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, INLINE_TOK);
- YY_BREAK
-case 140:
-YY_RULE_SETUP
-#line 344 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, NOINLINE);
- YY_BREAK
-case 141:
-YY_RULE_SETUP
-#line 345 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, VOLATILE);
- YY_BREAK
-case 142:
-YY_RULE_SETUP
-#line 346 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, PUBLIC_TOK);
- YY_BREAK
-case 143:
-YY_RULE_SETUP
-#line 347 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, STATIC);
- YY_BREAK
-case 144:
-YY_RULE_SETUP
-#line 348 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, EXTERN);
- YY_BREAK
-case 145:
-YY_RULE_SETUP
-#line 349 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, EXTERNAL);
- YY_BREAK
-case 146:
-YY_RULE_SETUP
-#line 350 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, INTERFACE);
- YY_BREAK
-case 147:
-YY_RULE_SETUP
-#line 351 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, LONG_TOK);
- YY_BREAK
-case 148:
-YY_RULE_SETUP
-#line 352 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, SHORT_TOK);
- YY_BREAK
-case 149:
-YY_RULE_SETUP
-#line 353 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 400, DOUBLE_TOK);
- YY_BREAK
-case 150:
-YY_RULE_SETUP
-#line 354 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, HALF);
- YY_BREAK
-case 151:
-YY_RULE_SETUP
-#line 355 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, FIXED_TOK);
- YY_BREAK
-case 152:
-YY_RULE_SETUP
-#line 356 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, UNSIGNED);
- YY_BREAK
-case 153:
-YY_RULE_SETUP
-#line 357 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, INPUT_TOK);
- YY_BREAK
-case 154:
-YY_RULE_SETUP
-#line 358 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, OUTPUT);
- YY_BREAK
-case 155:
-YY_RULE_SETUP
-#line 359 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, HVEC2);
- YY_BREAK
-case 156:
-YY_RULE_SETUP
-#line 360 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, HVEC3);
- YY_BREAK
-case 157:
-YY_RULE_SETUP
-#line 361 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, HVEC4);
- YY_BREAK
-case 158:
-YY_RULE_SETUP
-#line 362 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 400, DVEC2);
- YY_BREAK
-case 159:
-YY_RULE_SETUP
-#line 363 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 400, DVEC3);
- YY_BREAK
-case 160:
-YY_RULE_SETUP
-#line 364 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 400, DVEC4);
- YY_BREAK
-case 161:
-YY_RULE_SETUP
-#line 365 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, FVEC2);
- YY_BREAK
-case 162:
-YY_RULE_SETUP
-#line 366 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, FVEC3);
- YY_BREAK
-case 163:
-YY_RULE_SETUP
-#line 367 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, FVEC4);
- YY_BREAK
-case 164:
-YY_RULE_SETUP
-#line 368 "glsl_lexer.lpp"
-return SAMPLER2DRECT;
- YY_BREAK
-case 165:
-YY_RULE_SETUP
-#line 369 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, SAMPLER3DRECT);
- YY_BREAK
-case 166:
-YY_RULE_SETUP
-#line 370 "glsl_lexer.lpp"
-return SAMPLER2DRECTSHADOW;
- YY_BREAK
-case 167:
-YY_RULE_SETUP
-#line 371 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, SIZEOF);
- YY_BREAK
-case 168:
-YY_RULE_SETUP
-#line 372 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, CAST);
- YY_BREAK
-case 169:
-YY_RULE_SETUP
-#line 373 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, NAMESPACE);
- YY_BREAK
-case 170:
-YY_RULE_SETUP
-#line 374 "glsl_lexer.lpp"
-KEYWORD(110 || ES, 999, USING);
- YY_BREAK
-/* Additional reserved words in GLSL 1.20. */
-case 171:
-YY_RULE_SETUP
-#line 377 "glsl_lexer.lpp"
-KEYWORD(120, 130 || ES, LOWP);
- YY_BREAK
-case 172:
-YY_RULE_SETUP
-#line 378 "glsl_lexer.lpp"
-KEYWORD(120, 130 || ES, MEDIUMP);
- YY_BREAK
-case 173:
-YY_RULE_SETUP
-#line 379 "glsl_lexer.lpp"
-KEYWORD(120, 130 || ES, HIGHP);
- YY_BREAK
-case 174:
-YY_RULE_SETUP
-#line 380 "glsl_lexer.lpp"
-KEYWORD(120, 130 || ES, PRECISION);
- YY_BREAK
-/* Additional reserved words in GLSL 1.30. */
-case 175:
-YY_RULE_SETUP
-#line 383 "glsl_lexer.lpp"
-KEYWORD(130, 130, CASE);
- YY_BREAK
-case 176:
-YY_RULE_SETUP
-#line 384 "glsl_lexer.lpp"
-KEYWORD(130, 999, COMMON);
- YY_BREAK
-case 177:
-YY_RULE_SETUP
-#line 385 "glsl_lexer.lpp"
-KEYWORD(130, 999, PARTITION);
- YY_BREAK
-case 178:
-YY_RULE_SETUP
-#line 386 "glsl_lexer.lpp"
-KEYWORD(130, 999, ACTIVE);
- YY_BREAK
-case 179:
-YY_RULE_SETUP
-#line 387 "glsl_lexer.lpp"
-KEYWORD(130 || ES, 999, SUPERP);
- YY_BREAK
-case 180:
-YY_RULE_SETUP
-#line 388 "glsl_lexer.lpp"
-KEYWORD(130, 140, SAMPLERBUFFER);
- YY_BREAK
-case 181:
-YY_RULE_SETUP
-#line 389 "glsl_lexer.lpp"
-KEYWORD(130, 999, FILTER);
- YY_BREAK
-case 182:
-YY_RULE_SETUP
-#line 390 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE1D);
- YY_BREAK
-case 183:
-YY_RULE_SETUP
-#line 391 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE2D);
- YY_BREAK
-case 184:
-YY_RULE_SETUP
-#line 392 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE3D);
- YY_BREAK
-case 185:
-YY_RULE_SETUP
-#line 393 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGECUBE);
- YY_BREAK
-case 186:
-YY_RULE_SETUP
-#line 394 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGE1D);
- YY_BREAK
-case 187:
-YY_RULE_SETUP
-#line 395 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGE2D);
- YY_BREAK
-case 188:
-YY_RULE_SETUP
-#line 396 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGE3D);
- YY_BREAK
-case 189:
-YY_RULE_SETUP
-#line 397 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGECUBE);
- YY_BREAK
-case 190:
-YY_RULE_SETUP
-#line 398 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGE1D);
- YY_BREAK
-case 191:
-YY_RULE_SETUP
-#line 399 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGE2D);
- YY_BREAK
-case 192:
-YY_RULE_SETUP
-#line 400 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGE3D);
- YY_BREAK
-case 193:
-YY_RULE_SETUP
-#line 401 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGECUBE);
- YY_BREAK
-case 194:
-YY_RULE_SETUP
-#line 402 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE1DARRAY);
- YY_BREAK
-case 195:
-YY_RULE_SETUP
-#line 403 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE2DARRAY);
- YY_BREAK
-case 196:
-YY_RULE_SETUP
-#line 404 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGE1DARRAY);
- YY_BREAK
-case 197:
-YY_RULE_SETUP
-#line 405 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGE2DARRAY);
- YY_BREAK
-case 198:
-YY_RULE_SETUP
-#line 406 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGE1DARRAY);
- YY_BREAK
-case 199:
-YY_RULE_SETUP
-#line 407 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGE2DARRAY);
- YY_BREAK
-case 200:
-YY_RULE_SETUP
-#line 408 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE1DSHADOW);
- YY_BREAK
-case 201:
-YY_RULE_SETUP
-#line 409 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE2DSHADOW);
- YY_BREAK
-case 202:
-YY_RULE_SETUP
-#line 410 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE1DARRAYSHADOW);
- YY_BREAK
-case 203:
-YY_RULE_SETUP
-#line 411 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
- YY_BREAK
-case 204:
-YY_RULE_SETUP
-#line 412 "glsl_lexer.lpp"
-KEYWORD(130, 999, IMAGEBUFFER);
- YY_BREAK
-case 205:
-YY_RULE_SETUP
-#line 413 "glsl_lexer.lpp"
-KEYWORD(130, 999, IIMAGEBUFFER);
- YY_BREAK
-case 206:
-YY_RULE_SETUP
-#line 414 "glsl_lexer.lpp"
-KEYWORD(130, 999, UIMAGEBUFFER);
- YY_BREAK
-case 207:
-YY_RULE_SETUP
-#line 415 "glsl_lexer.lpp"
-KEYWORD(130, 999, ROW_MAJOR);
- YY_BREAK
-case 208:
-YY_RULE_SETUP
-#line 417 "glsl_lexer.lpp"
-{
- struct _mesa_glsl_parse_state *state = yyextra;
- void *ctx = state;
- yylval->identifier = talloc_strdup(ctx, yytext);
- return IDENTIFIER;
- }
- YY_BREAK
-case 209:
-YY_RULE_SETUP
-#line 424 "glsl_lexer.lpp"
-{ return yytext[0]; }
- YY_BREAK
-case 210:
-YY_RULE_SETUP
-#line 426 "glsl_lexer.lpp"
-ECHO;
- YY_BREAK
-#line 2564 "glsl_lexer.cpp"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(PP):
-case YY_STATE_EOF(PRAGMA):
- yyterminate();
-
- case YY_END_OF_BUFFER:
- {
- /* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
- /* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = yyg->yy_hold_char;
- YY_RESTORE_YY_MORE_OFFSET
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
- {
- /* We're scanning a new file or input source. It's
- * possible that this happened because the user
- * just pointed yyin at a new source and called
- * _mesa_glsl_lex(). If so, then we have to assure
- * consistency between YY_CURRENT_BUFFER and our
- * globals. Here is the right place to do so, because
- * this is the first action (other than possibly a
- * back-up) that will match for the new input source.
- */
- yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
- }
-
- /* Note that here we test for yy_c_buf_p "<=" to the position
- * of the first EOB in the buffer, since yy_c_buf_p will
- * already have been incremented past the NUL character
- * (since all states make transitions on EOB to the
- * end-of-buffer state). Contrast this with the test
- * in input().
- */
- if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
- { /* This was really a NUL. */
- yy_state_type yy_next_state;
-
- yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- /* Okay, we're now positioned to make the NUL
- * transition. We couldn't have
- * yy_get_previous_state() go ahead and do it
- * for us because it doesn't know how to deal
- * with the possibility of jamming (and we don't
- * want to build jamming into it because then it
- * will run more slowly).
- */
-
- yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
- if ( yy_next_state )
- {
- /* Consume the NUL. */
- yy_cp = ++yyg->yy_c_buf_p;
- yy_current_state = yy_next_state;
- goto yy_match;
- }
-
- else
- {
- yy_cp = yyg->yy_last_accepting_cpos;
- yy_current_state = yyg->yy_last_accepting_state;
- goto yy_find_action;
- }
- }
-
- else switch ( yy_get_next_buffer( yyscanner ) )
- {
- case EOB_ACT_END_OF_FILE:
- {
- yyg->yy_did_buffer_switch_on_eof = 0;
-
- if ( _mesa_glsl_wrap(yyscanner ) )
- {
- /* Note: because we've taken care in
- * yy_get_next_buffer() to have set up
- * yytext, we can now set up
- * yy_c_buf_p so that if some total
- * hoser (like flex itself) wants to
- * call the scanner after we return the
- * YY_NULL, it'll still work - another
- * YY_NULL will get returned.
- */
- yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
- yy_act = YY_STATE_EOF(YY_START);
- goto do_action;
- }
-
- else
- {
- if ( ! yyg->yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
- }
- break;
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yyg->yy_c_buf_p =
- yyg->yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- yy_cp = yyg->yy_c_buf_p;
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
- goto yy_match;
-
- case EOB_ACT_LAST_MATCH:
- yyg->yy_c_buf_p =
- &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- yy_cp = yyg->yy_c_buf_p;
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
- goto yy_find_action;
- }
- break;
- }
-
- default:
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--no action found" );
- } /* end of action switch */
- } /* end of scanning one token */
-} /* end of _mesa_glsl_lex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- * EOB_ACT_LAST_MATCH -
- * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- * EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
- int ret_val;
-
- if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--end of buffer missed" );
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
- { /* Don't try to fill the buffer, so this is an EOF. */
- if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
- {
- /* We matched a single character, the EOB, so
- * treat this as a final EOF.
- */
- return EOB_ACT_END_OF_FILE;
- }
-
- else
- {
- /* We matched some text prior to the EOB, first
- * process it.
- */
- return EOB_ACT_LAST_MATCH;
- }
- }
-
- /* Try to read more data. */
-
- /* First move last chars to start of buffer. */
- number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
- for ( i = 0; i < number_to_move; ++i )
- *(dest++) = *(source++);
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
- /* don't do the read, it's not guaranteed to return an EOF,
- * just force an EOF
- */
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
- else
- {
- int num_to_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
- while ( num_to_read <= 0 )
- { /* Not enough room in the buffer - grow it. */
-
- /* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
- int yy_c_buf_p_offset =
- (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
- if ( b->yy_is_our_buffer )
- {
- int new_size = b->yy_buf_size * 2;
-
- if ( new_size <= 0 )
- b->yy_buf_size += b->yy_buf_size / 8;
- else
- b->yy_buf_size *= 2;
-
- b->yy_ch_buf = (char *)
- /* Include room in for 2 EOB chars. */
- _mesa_glsl_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR(
- "fatal error - scanner input buffer overflow" );
-
- yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
- num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
-
- }
-
- if ( num_to_read > YY_READ_BUF_SIZE )
- num_to_read = YY_READ_BUF_SIZE;
-
- /* Read in more data. */
- YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, (size_t) num_to_read );
-
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- if ( yyg->yy_n_chars == 0 )
- {
- if ( number_to_move == YY_MORE_ADJ )
- {
- ret_val = EOB_ACT_END_OF_FILE;
- _mesa_glsl_restart(yyin ,yyscanner);
- }
-
- else
- {
- ret_val = EOB_ACT_LAST_MATCH;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
- YY_BUFFER_EOF_PENDING;
- }
- }
-
- else
- ret_val = EOB_ACT_CONTINUE_SCAN;
-
- if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
- /* Extend the array by 50%, plus the number we really need. */
- yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _mesa_glsl_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- yyg->yy_n_chars += number_to_move;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
- yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
- return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
- static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
- register yy_state_type yy_current_state;
- register char *yy_cp;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- yy_current_state = yyg->yy_start;
- yy_current_state += YY_AT_BOL();
-
- for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
- {
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 836 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- }
-
- return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- * next_state = yy_try_NUL_trans( current_state );
- */
- static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
- register int yy_is_jam;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register char *yy_cp = yyg->yy_c_buf_p;
-
- register YY_CHAR yy_c = 1;
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 836 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 835);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
- static int yyinput (yyscan_t yyscanner)
-#else
- static int input (yyscan_t yyscanner)
-#endif
-
-{
- int c;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
-
- if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
- {
- /* yy_c_buf_p now points to the character we want to return.
- * If this occurs *before* the EOB characters, then it's a
- * valid NUL; if not, then we've hit the end of the buffer.
- */
- if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
- /* This was really a NUL. */
- *yyg->yy_c_buf_p = '\0';
-
- else
- { /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
- ++yyg->yy_c_buf_p;
-
- switch ( yy_get_next_buffer( yyscanner ) )
- {
- case EOB_ACT_LAST_MATCH:
- /* This happens because yy_g_n_b()
- * sees that we've accumulated a
- * token and flags that we need to
- * try matching the token before
- * proceeding. But for input(),
- * there's no matching to consider.
- * So convert the EOB_ACT_LAST_MATCH
- * to EOB_ACT_END_OF_FILE.
- */
-
- /* Reset buffer status. */
- _mesa_glsl_restart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( _mesa_glsl_wrap(yyscanner ) )
- return EOF;
-
- if ( ! yyg->yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
-#ifdef __cplusplus
- return yyinput(yyscanner);
-#else
- return input(yyscanner);
-#endif
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
- break;
- }
- }
- }
-
- c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
- *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
- yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
- return c;
-}
-#endif /* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
- void _mesa_glsl_restart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- _mesa_glsl_ensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- _mesa_glsl__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- _mesa_glsl__load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
- void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* TODO. We should be able to replace this entire function body
- * with
- * _mesa_glsl_pop_buffer_state();
- * _mesa_glsl_push_buffer_state(new_buffer);
- */
- _mesa_glsl_ensure_buffer_stack (yyscanner);
- if ( YY_CURRENT_BUFFER == new_buffer )
- return;
-
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
- _mesa_glsl__load_buffer_state(yyscanner );
-
- /* We don't actually know whether we did this switch during
- * EOF (_mesa_glsl_wrap()) processing, but the only time this flag
- * is looked at is after _mesa_glsl_wrap() is called, so it's safe
- * to go ahead and always set it.
- */
- yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
- yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
- yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
- YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE * file, int size , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
-
- b->yy_buf_size = size;
-
- /* yy_ch_buf has to be 2 characters longer than the size given because
- * we need to put in 2 end-of-buffer characters.
- */
- b->yy_ch_buf = (char *) _mesa_glsl_alloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- _mesa_glsl__init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with _mesa_glsl__create_buffer()
- * @param yyscanner The scanner object.
- */
- void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! b )
- return;
-
- if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
- YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
- if ( b->yy_is_our_buffer )
- _mesa_glsl_free((void *) b->yy_ch_buf ,yyscanner );
-
- _mesa_glsl_free((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a _mesa_glsl_restart() or at EOF.
- */
- static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
-
-{
- int oerrno = errno;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- _mesa_glsl__flush_buffer(b ,yyscanner);
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
- /* If b is the current buffer, then _mesa_glsl__init_buffer was _probably_
- * called from _mesa_glsl_restart() or through yy_get_next_buffer.
- * In that case, we don't want to reset the lineno or column.
- */
- if (b != YY_CURRENT_BUFFER){
- b->yy_bs_lineno = 1;
- b->yy_bs_column = 0;
- }
-
- b->yy_is_interactive = 0;
-
- errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
- void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if ( ! b )
- return;
-
- b->yy_n_chars = 0;
-
- /* We always need two end-of-buffer characters. The first causes
- * a transition to the end-of-buffer state. The second causes
- * a jam in that state.
- */
- b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
- b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
- b->yy_buf_pos = &b->yy_ch_buf[0];
-
- b->yy_at_bol = 1;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- if ( b == YY_CURRENT_BUFFER )
- _mesa_glsl__load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- * the current state. This function will allocate the stack
- * if necessary.
- * @param new_buffer The new state.
- * @param yyscanner The scanner object.
- */
-void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (new_buffer == NULL)
- return;
-
- _mesa_glsl_ensure_buffer_stack(yyscanner);
-
- /* This block is copied from _mesa_glsl__switch_to_buffer. */
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- /* Only push if top exists. Otherwise, replace top. */
- if (YY_CURRENT_BUFFER)
- yyg->yy_buffer_stack_top++;
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
- /* copied from _mesa_glsl__switch_to_buffer. */
- _mesa_glsl__load_buffer_state(yyscanner );
- yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- * The next element becomes the new top.
- * @param yyscanner The scanner object.
- */
-void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (!YY_CURRENT_BUFFER)
- return;
-
- _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
- YY_CURRENT_BUFFER_LVALUE = NULL;
- if (yyg->yy_buffer_stack_top > 0)
- --yyg->yy_buffer_stack_top;
-
- if (YY_CURRENT_BUFFER) {
- _mesa_glsl__load_buffer_state(yyscanner );
- yyg->yy_did_buffer_switch_on_eof = 1;
- }
-}
-
-/* Allocates the stack if it does not exist.
- * Guarantees space for at least one push.
- */
-static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner)
-{
- int num_to_alloc;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (!yyg->yy_buffer_stack) {
-
- /* First allocation is just for 2 elements, since we don't know if this
- * scanner will even need a stack. We use 2 instead of 1 to avoid an
- * immediate realloc on the next call.
- */
- num_to_alloc = 1;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_alloc
- (num_to_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
- if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
-
- memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
- yyg->yy_buffer_stack_max = num_to_alloc;
- yyg->yy_buffer_stack_top = 0;
- return;
- }
-
- if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
- /* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
-
- num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_realloc
- (yyg->yy_buffer_stack,
- num_to_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
- if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
-
- /* zero only the new slots.*/
- memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
- yyg->yy_buffer_stack_max = num_to_alloc;
- }
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE _mesa_glsl__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
-
- if ( size < 2 ||
- base[size-2] != YY_END_OF_BUFFER_CHAR ||
- base[size-1] != YY_END_OF_BUFFER_CHAR )
- /* They forgot to leave room for the EOB's. */
- return 0;
-
- b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_buffer()" );
-
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
- b->yy_buf_pos = b->yy_ch_buf = base;
- b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
- b->yy_n_chars = b->yy_buf_size;
- b->yy_is_interactive = 0;
- b->yy_at_bol = 1;
- b->yy_fill_buffer = 0;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- _mesa_glsl__switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to _mesa_glsl_lex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- * _mesa_glsl__scan_bytes() instead.
- */
-YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
- return _mesa_glsl__scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to _mesa_glsl_lex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
- buf = (char *) _mesa_glsl_alloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_bytes()" );
-
- for ( i = 0; i < _yybytes_len; ++i )
- buf[i] = yybytes[i];
-
- buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
- b = _mesa_glsl__scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in _mesa_glsl__scan_bytes()" );
-
- /* It's okay to grow etc. this buffer, and we should throw it
- * away when we're done.
- */
- b->yy_is_our_buffer = 1;
-
- return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- yytext[yyleng] = yyg->yy_hold_char; \
- yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
- yyg->yy_hold_char = *yyg->yy_c_buf_p; \
- *yyg->yy_c_buf_p = '\0'; \
- yyleng = yyless_macro_arg; \
- } \
- while ( 0 )
-
-/* Accessor methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int _mesa_glsl_get_lineno (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (! YY_CURRENT_BUFFER)
- return 0;
-
- return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int _mesa_glsl_get_column (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (! YY_CURRENT_BUFFER)
- return 0;
-
- return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *_mesa_glsl_get_in (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *_mesa_glsl_get_out (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int _mesa_glsl_get_leng (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *_mesa_glsl_get_text (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void _mesa_glsl_set_lineno (int line_number , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* lineno is only valid if an input buffer exists. */
- if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "_mesa_glsl_set_lineno called with no buffer" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void _mesa_glsl_set_column (int column_no , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* column is only valid if an input buffer exists. */
- if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "_mesa_glsl_set_column called with no buffer" , yyscanner);
-
- yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see _mesa_glsl__switch_to_buffer
- */
-void _mesa_glsl_set_in (FILE * in_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
-}
-
-void _mesa_glsl_set_out (FILE * out_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int _mesa_glsl_get_debug (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yy_flex_debug;
-}
-
-void _mesa_glsl_set_debug (int bdebug , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yylval;
-}
-
-void _mesa_glsl_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yylval = yylval_param;
-}
-
-YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yylloc;
-}
-
-void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yylloc = yylloc_param;
-}
-
-/* User-visible API */
-
-/* _mesa_glsl_lex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int _mesa_glsl_lex_init(yyscan_t* ptr_yy_globals)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), NULL );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
- memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* _mesa_glsl_lex_init_extra has the same functionality as _mesa_glsl_lex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to _mesa_glsl_alloc in
- * the yyextra field.
- */
-
-int _mesa_glsl_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
- struct yyguts_t dummy_yyguts;
-
- _mesa_glsl_set_extra (yy_user_defined, &dummy_yyguts);
-
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- /* By setting to 0xAA, we expose bugs in
- yy_init_globals. Leave at 0x00 for releases. */
- memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
- _mesa_glsl_set_extra (yy_user_defined, *ptr_yy_globals);
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- /* Initialization is the same as for the non-reentrant scanner.
- * This function is called from _mesa_glsl_lex_destroy(), so don't allocate here.
- */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 0;
- yyg->yy_start = 0;
-
- yyg->yy_start_stack_ptr = 0;
- yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
- yyin = stdin;
- yyout = stdout;
-#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * _mesa_glsl_lex_init()
- */
- return 0;
-}
-
-/* _mesa_glsl_lex_destroy is for both reentrant and non-reentrant scanners. */
-int _mesa_glsl_lex_destroy (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* Pop the buffer stack, destroying each element. */
- while(YY_CURRENT_BUFFER){
- _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
- YY_CURRENT_BUFFER_LVALUE = NULL;
- _mesa_glsl_pop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- _mesa_glsl_free(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- _mesa_glsl_free(yyg->yy_start_stack ,yyscanner );
- yyg->yy_start_stack = NULL;
-
- /* Reset the globals. This is important in a non-reentrant scanner so the next time
- * _mesa_glsl_lex() is called, initialization will occur. */
- yy_init_globals( yyscanner);
-
- /* Destroy the main struct (reentrant only). */
- _mesa_glsl_free ( yyscanner , yyscanner );
- yyscanner = NULL;
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- register int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- register int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *_mesa_glsl_alloc (yy_size_t size , yyscan_t yyscanner)
-{
- return (void *) malloc( size );
-}
-
-void *_mesa_glsl_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
-{
- /* The cast to (char *) in the following accommodates both
- * implementations that use char* generic pointers, and those
- * that use void* generic pointers. It works with the latter
- * because both ANSI C and C++ allow castless assignment from
- * any pointer type to void*, and deal with argument conversions
- * as though doing an assignment.
- */
- return (void *) realloc( (char *) ptr, size );
-}
-
-void _mesa_glsl_free (void * ptr , yyscan_t yyscanner)
-{
- free( (char *) ptr ); /* see _mesa_glsl_realloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 426 "glsl_lexer.lpp"
-
-
-
-void
-_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
-{
- _mesa_glsl_lex_init_extra(state,& state->scanner);
- _mesa_glsl__scan_string(string,state->scanner);
-}
-
-void
-_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
-{
- _mesa_glsl_lex_destroy(state->scanner);
-}
-
+#line 2 "glsl_lexer.cpp"
+
+#line 4 "glsl_lexer.cpp"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE _mesa_glsl_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via _mesa_glsl_restart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void _mesa_glsl_restart (FILE *input_file ,yyscan_t yyscanner );
+void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner );
+
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner );
+static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner );
+static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER _mesa_glsl__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE _mesa_glsl__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *_mesa_glsl_alloc (yy_size_t ,yyscan_t yyscanner );
+void *_mesa_glsl_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void _mesa_glsl_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer _mesa_glsl__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ _mesa_glsl_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ _mesa_glsl_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define _mesa_glsl_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 210
+#define YY_END_OF_BUFFER 211
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[836] =
+ { 0,
+ 0, 0, 16, 16, 0, 0, 211, 209, 1, 21,
+ 209, 209, 209, 209, 209, 209, 209, 209, 120, 118,
+ 209, 209, 209, 208, 209, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 209, 1, 209, 210, 16,
+ 20, 210, 19, 17, 18, 14, 13, 1, 102, 111,
+ 103, 114, 108, 97, 110, 98, 117, 122, 109, 123,
+ 120, 0, 0, 125, 120, 0, 118, 118, 106, 99,
+ 101, 100, 107, 208, 115, 105, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 30, 208,
+
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 34, 208, 208, 61, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 116,
+ 104, 1, 0, 0, 2, 0, 0, 0, 0, 16,
+ 15, 19, 18, 0, 122, 121, 0, 123, 0, 124,
+ 119, 112, 113, 208, 128, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 33, 208, 208, 208,
+
+ 208, 208, 208, 208, 208, 208, 208, 26, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 62,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 0, 0, 0, 0, 15, 0, 122, 0, 121, 0,
+ 123, 124, 119, 208, 208, 24, 208, 208, 175, 168,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 32,
+ 131, 208, 208, 208, 208, 68, 208, 208, 136, 150,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+
+ 208, 208, 147, 171, 49, 50, 51, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 134, 126, 208,
+ 208, 27, 208, 208, 208, 208, 208, 208, 208, 46,
+ 47, 48, 95, 208, 208, 0, 0, 0, 0, 0,
+ 121, 208, 208, 28, 37, 38, 39, 208, 129, 208,
+ 23, 208, 208, 208, 208, 158, 159, 160, 208, 127,
+ 208, 151, 25, 161, 162, 163, 173, 155, 156, 157,
+ 208, 208, 208, 63, 153, 208, 208, 208, 40, 41,
+ 42, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+
+ 208, 208, 208, 208, 208, 208, 208, 148, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 130, 208,
+ 208, 170, 43, 44, 45, 208, 208, 31, 0, 0,
+ 0, 0, 178, 208, 208, 176, 208, 208, 208, 149,
+ 144, 181, 208, 208, 208, 208, 208, 208, 139, 208,
+ 208, 208, 96, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 208, 208, 208, 208, 154, 135, 208, 208,
+ 142, 36, 208, 208, 167, 69, 143, 94, 179, 137,
+ 208, 208, 208, 208, 208, 208, 208, 208, 0, 0,
+ 0, 0, 208, 208, 208, 138, 35, 208, 208, 208,
+
+ 208, 208, 208, 182, 183, 184, 208, 208, 208, 208,
+ 208, 172, 208, 208, 208, 208, 208, 208, 208, 208,
+ 132, 208, 208, 208, 208, 208, 64, 208, 208, 65,
+ 208, 0, 0, 0, 0, 0, 208, 66, 29, 145,
+ 186, 187, 188, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 140, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 133, 190, 191, 192, 208,
+ 208, 152, 208, 141, 0, 0, 6, 0, 0, 0,
+ 12, 3, 22, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 185, 146, 67, 208, 208, 208, 208, 169,
+
+ 208, 177, 174, 207, 71, 72, 73, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 0, 0, 0,
+ 0, 0, 0, 0, 208, 208, 208, 189, 208, 208,
+ 208, 208, 208, 82, 83, 84, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 193,
+ 88, 89, 90, 208, 4, 0, 5, 0, 0, 0,
+ 0, 0, 0, 208, 208, 208, 208, 208, 208, 208,
+ 204, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 74, 208, 208, 208, 208, 208, 208, 0,
+ 0, 0, 0, 208, 208, 205, 194, 208, 195, 208,
+
+ 208, 208, 85, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 206, 208, 208, 91, 0, 0,
+ 0, 196, 197, 208, 200, 208, 201, 208, 208, 70,
+ 208, 208, 208, 164, 208, 165, 180, 208, 198, 199,
+ 208, 208, 0, 0, 0, 208, 208, 208, 208, 75,
+ 208, 76, 208, 208, 208, 208, 208, 0, 0, 0,
+ 0, 208, 208, 86, 87, 208, 77, 208, 208, 78,
+ 208, 92, 93, 0, 0, 0, 0, 208, 208, 208,
+ 208, 208, 208, 0, 0, 0, 0, 208, 208, 208,
+ 208, 208, 79, 0, 0, 0, 7, 0, 0, 202,
+
+ 203, 208, 208, 208, 0, 0, 8, 0, 0, 208,
+ 208, 166, 0, 0, 0, 80, 81, 0, 0, 0,
+ 9, 0, 0, 10, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 11, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 1, 6, 1, 7, 8, 1, 9,
+ 10, 11, 12, 1, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 21, 21, 22, 22, 23, 1, 24,
+ 25, 26, 1, 1, 27, 28, 29, 30, 31, 32,
+ 33, 34, 34, 34, 34, 35, 34, 34, 34, 34,
+ 34, 36, 37, 38, 39, 34, 34, 40, 34, 34,
+ 1, 1, 1, 41, 42, 1, 43, 44, 45, 46,
+
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 34, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 1, 68, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[69] =
+ { 0,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ 3, 3, 1, 1, 1, 1, 4, 4, 4, 4,
+ 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
+ 1, 5, 4, 4, 4, 4, 3, 3, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[845] =
+ { 0,
+ 0, 67, 73, 0, 1210, 1209, 1211, 1214, 68, 1214,
+ 1185, 1184, 134, 1183, 131, 132, 130, 1182, 146, 198,
+ 129, 1181, 144, 0, 130, 113, 124, 141, 150, 126,
+ 181, 1148, 159, 192, 118, 129, 146, 1142, 147, 174,
+ 206, 192, 203, 222, 1153, 203, 221, 231, 1214, 260,
+ 1214, 1187, 279, 1214, 0, 1214, 1214, 270, 1214, 1214,
+ 1214, 1214, 1214, 1214, 1214, 1214, 1214, 244, 1214, 255,
+ 139, 290, 307, 1214, 1214, 0, 0, 1214, 1176, 1214,
+ 1214, 1214, 1175, 0, 1214, 1214, 1138, 1143, 1136, 1139,
+ 1148, 1147, 1133, 1136, 1148, 144, 1142, 1129, 1126, 1140,
+
+ 1126, 1123, 1123, 1129, 219, 193, 1123, 1134, 1119, 1125,
+ 1129, 1130, 0, 1121, 1132, 278, 1131, 1126, 1106, 224,
+ 1110, 1124, 1114, 232, 1107, 271, 1120, 1122, 1104, 1100,
+ 1108, 1105, 1094, 1103, 234, 1101, 1107, 1102, 1105, 1093,
+ 1096, 226, 145, 262, 1106, 1093, 1106, 263, 1099, 1214,
+ 1214, 338, 331, 343, 1214, 1084, 1097, 1088, 1099, 345,
+ 0, 334, 0, 345, 1214, 328, 391, 1214, 352, 398,
+ 338, 1214, 1214, 1094, 0, 1085, 1089, 1099, 1096, 332,
+ 1079, 1079, 1083, 320, 1094, 1091, 1091, 1089, 1086, 1077,
+ 1084, 1070, 1068, 1081, 1066, 1083, 0, 1080, 1067, 1075,
+
+ 1072, 1076, 1077, 1070, 1067, 1055, 1054, 1068, 1071, 1058,
+ 1067, 1054, 1061, 1051, 364, 1057, 1060, 1050, 1058, 1046,
+ 1050, 1041, 1056, 1046, 1037, 1056, 1039, 1037, 1048, 1037,
+ 1032, 1030, 1044, 1029, 1031, 1028, 1040, 1039, 1042, 1023,
+ 338, 1032, 1027, 1025, 1035, 1013, 403, 1032, 1034, 1022,
+ 1014, 1018, 1030, 1013, 0, 415, 422, 439, 1214, 446,
+ 455, 1214, 1214, 1008, 1019, 0, 1016, 406, 0, 0,
+ 1009, 1007, 1009, 1004, 1013, 1001, 1019, 1007, 409, 0,
+ 0, 1001, 1012, 1011, 1011, 0, 995, 429, 0, 0,
+ 997, 460, 1005, 1006, 996, 990, 989, 990, 989, 989,
+
+ 463, 984, 0, 0, 980, 979, 978, 980, 981, 986,
+ 980, 976, 990, 985, 984, 983, 974, 977, 977, 969,
+ 972, 967, 976, 981, 966, 979, 969, 0, 0, 976,
+ 972, 0, 963, 963, 969, 959, 967, 466, 964, 0,
+ 0, 0, 0, 953, 966, 965, 964, 961, 949, 472,
+ 479, 961, 963, 0, 0, 0, 0, 949, 0, 949,
+ 0, 948, 949, 943, 954, 0, 0, 0, 944, 0,
+ 940, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 951, 487, 950, 0, 0, 948, 944, 940, 0, 0,
+ 0, 932, 489, 494, 499, 937, 933, 939, 929, 927,
+
+ 941, 925, 925, 939, 927, 939, 934, 0, 932, 929,
+ 933, 916, 918, 925, 931, 926, 925, 912, 0, 914,
+ 915, 0, 0, 0, 0, 912, 916, 0, 910, 963,
+ 909, 912, 0, 900, 910, 0, 898, 898, 912, 0,
+ 914, 0, 503, 926, 925, 924, 891, 890, 0, 908,
+ 907, 902, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 890, 904, 890, 887, 0, 0, 893, 892,
+ 0, 0, 890, 882, 0, 0, 0, 0, 0, 0,
+ 879, 891, 506, 883, 890, 889, 886, 880, 873, 524,
+ 889, 874, 869, 883, 881, 0, 0, 873, 896, 895,
+
+ 894, 861, 860, 361, 365, 0, 873, 876, 874, 862,
+ 858, 0, 871, 868, 867, 856, 855, 854, 519, 863,
+ 0, 879, 878, 877, 844, 843, 0, 858, 844, 0,
+ 855, 850, 547, 553, 898, 843, 851, 0, 0, 0,
+ 870, 869, 0, 847, 850, 834, 842, 832, 840, 841,
+ 841, 840, 825, 559, 838, 0, 839, 827, 826, 822,
+ 850, 849, 848, 815, 814, 0, 848, 847, 0, 825,
+ 828, 0, 562, 0, 814, 580, 1214, 587, 0, 607,
+ 584, 1214, 0, 811, 810, 820, 820, 807, 822, 805,
+ 820, 815, 0, 0, 0, 831, 830, 829, 796, 0,
+
+ 796, 0, 0, 0, 502, 524, 820, 807, 810, 794,
+ 793, 803, 803, 819, 818, 817, 784, 789, 615, 640,
+ 550, 806, 796, 784, 782, 781, 792, 0, 795, 791,
+ 793, 789, 775, 806, 805, 0, 787, 779, 770, 778,
+ 768, 779, 775, 777, 775, 775, 762, 761, 772, 0,
+ 791, 790, 0, 772, 1214, 555, 1214, 647, 0, 667,
+ 785, 770, 752, 769, 768, 751, 743, 751, 741, 749,
+ 0, 746, 745, 756, 739, 742, 757, 740, 753, 754,
+ 751, 748, 757, 750, 749, 732, 731, 730, 741, 582,
+ 754, 724, 734, 718, 717, 0, 745, 717, 743, 715,
+
+ 719, 718, 0, 729, 732, 728, 730, 711, 725, 709,
+ 710, 718, 701, 700, 0, 706, 705, 0, 728, 713,
+ 706, 0, 0, 710, 0, 709, 0, 715, 714, 0,
+ 690, 698, 688, 716, 695, 0, 0, 708, 0, 0,
+ 707, 706, 746, 611, 696, 703, 702, 678, 677, 705,
+ 677, 703, 689, 674, 691, 670, 669, 190, 613, 557,
+ 667, 687, 686, 0, 0, 681, 0, 680, 686, 0,
+ 671, 0, 0, 671, 590, 343, 672, 645, 644, 654,
+ 635, 631, 612, 612, 604, 443, 635, 576, 575, 549,
+ 25, 87, 0, 183, 500, 552, 1214, 636, 591, 0,
+
+ 0, 196, 258, 254, 272, 609, 1214, 614, 598, 279,
+ 284, 0, 336, 348, 671, 0, 0, 362, 672, 688,
+ 1214, 394, 689, 1214, 408, 670, 691, 649, 651, 474,
+ 476, 693, 694, 1214, 1214, 704, 707, 710, 530, 591,
+ 713, 717, 720, 722
+ } ;
+
+static yyconst flex_int16_t yy_def[845] =
+ { 0,
+ 835, 1, 835, 3, 836, 836, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 837, 835, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 838, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 839, 835, 840,
+ 19, 835, 835, 835, 835, 841, 20, 835, 835, 835,
+ 835, 835, 835, 837, 835, 835, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 842, 835, 838, 835, 835, 840, 835, 835, 835, 835,
+ 841, 835, 835, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 835, 835, 835, 835, 842, 835, 835, 835, 835, 835,
+ 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 835, 835, 835, 835, 835,
+ 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
+ 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
+ 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 835, 835, 835, 835, 835, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 835, 835, 835, 835, 843, 835,
+ 835, 835, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 835, 835, 835,
+ 843, 835, 835, 835, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 835, 835, 835, 835, 844, 835,
+ 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 844,
+ 835, 835, 835, 837, 837, 837, 837, 837, 837, 837,
+
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 835, 835,
+ 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 835, 835, 835, 837, 837, 837, 837, 837,
+ 837, 837, 837, 837, 837, 837, 837, 835, 835, 835,
+ 835, 837, 837, 837, 837, 837, 837, 837, 837, 837,
+ 837, 837, 837, 835, 835, 835, 835, 837, 837, 837,
+ 837, 837, 837, 835, 835, 835, 835, 837, 837, 837,
+ 837, 837, 837, 835, 835, 835, 835, 835, 835, 837,
+
+ 837, 837, 837, 837, 835, 835, 835, 835, 835, 837,
+ 837, 837, 835, 835, 835, 837, 837, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 0, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1283] =
+ { 0,
+ 8, 9, 10, 9, 11, 8, 12, 13, 8, 8,
+ 14, 15, 16, 17, 18, 19, 20, 20, 20, 20,
+ 20, 20, 8, 21, 22, 23, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 24, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 24, 24, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 24, 24, 24, 46, 47, 58,
+ 803, 58, 48, 49, 50, 51, 50, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 52, 49, 53,
+ 53, 53, 53, 53, 53, 54, 49, 49, 49, 55,
+
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 49, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 49, 61, 64, 804, 66, 68, 68, 68, 68, 68,
+ 68, 68, 79, 80, 85, 65, 67, 87, 62, 70,
+ 119, 71, 71, 71, 71, 71, 71, 72, 82, 83,
+ 86, 121, 88, 89, 120, 122, 73, 74, 835, 101,
+ 90, 102, 91, 93, 75, 76, 92, 94, 123, 126,
+ 103, 758, 73, 74, 95, 241, 97, 96, 183, 184,
+
+ 98, 110, 124, 835, 242, 127, 99, 75, 128, 111,
+ 76, 70, 100, 77, 77, 77, 77, 77, 77, 77,
+ 129, 112, 152, 104, 58, 805, 153, 150, 73, 74,
+ 130, 105, 154, 155, 106, 195, 78, 107, 138, 113,
+ 774, 139, 114, 108, 73, 74, 115, 116, 131, 196,
+ 140, 117, 810, 142, 118, 132, 133, 141, 143, 78,
+ 134, 160, 144, 160, 146, 145, 135, 136, 147, 137,
+ 151, 58, 193, 58, 164, 165, 231, 156, 148, 213,
+ 239, 240, 218, 194, 157, 167, 168, 214, 158, 219,
+ 164, 165, 232, 159, 162, 162, 162, 162, 162, 162,
+
+ 162, 167, 168, 70, 243, 72, 72, 72, 72, 72,
+ 72, 72, 244, 248, 811, 221, 249, 812, 169, 169,
+ 73, 74, 170, 170, 170, 170, 170, 170, 170, 222,
+ 813, 205, 154, 155, 206, 207, 73, 74, 208, 152,
+ 209, 58, 816, 153, 154, 155, 160, 817, 160, 162,
+ 162, 162, 162, 162, 162, 162, 256, 256, 258, 259,
+ 257, 257, 257, 257, 257, 257, 257, 170, 170, 170,
+ 170, 170, 170, 170, 258, 259, 263, 156, 269, 274,
+ 275, 305, 306, 307, 157, 333, 818, 546, 158, 156,
+ 785, 548, 270, 159, 334, 819, 157, 547, 786, 263,
+
+ 158, 549, 260, 260, 822, 159, 261, 261, 261, 261,
+ 261, 261, 261, 170, 170, 170, 170, 170, 170, 170,
+ 340, 341, 342, 355, 356, 357, 366, 367, 368, 262,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 796, 262, 374, 375, 376, 825,
+ 350, 350, 797, 165, 351, 351, 351, 351, 351, 351,
+ 351, 261, 261, 261, 261, 261, 261, 261, 826, 165,
+ 261, 261, 261, 261, 261, 261, 261, 378, 379, 380,
+ 389, 390, 391, 423, 424, 425, 168, 351, 351, 351,
+ 351, 351, 351, 351, 351, 351, 351, 351, 351, 351,
+
+ 351, 806, 168, 444, 445, 446, 454, 455, 456, 807,
+ 259, 457, 458, 459, 447, 448, 460, 461, 462, 499,
+ 500, 501, 522, 523, 524, 490, 259, 831, 639, 832,
+ 502, 503, 68, 525, 526, 561, 562, 563, 640, 533,
+ 534, 534, 534, 534, 534, 534, 564, 565, 576, 577,
+ 641, 576, 577, 796, 576, 577, 656, 657, 775, 642,
+ 643, 797, 578, 578, 578, 578, 578, 578, 580, 580,
+ 580, 580, 580, 580, 580, 596, 597, 598, 614, 615,
+ 616, 576, 577, 656, 657, 581, 579, 599, 576, 577,
+ 617, 775, 808, 166, 802, 619, 620, 620, 620, 620,
+
+ 620, 620, 578, 578, 578, 578, 578, 578, 576, 577,
+ 806, 579, 759, 776, 759, 808, 656, 657, 807, 760,
+ 622, 760, 580, 580, 580, 580, 580, 580, 580, 623,
+ 658, 658, 658, 658, 658, 658, 798, 798, 801, 800,
+ 624, 656, 657, 799, 799, 814, 776, 809, 656, 657,
+ 829, 795, 829, 815, 659, 660, 660, 660, 660, 660,
+ 660, 660, 658, 658, 658, 658, 658, 658, 656, 657,
+ 809, 827, 820, 823, 794, 793, 792, 791, 828, 659,
+ 821, 824, 660, 660, 660, 660, 660, 660, 660, 820,
+ 823, 830, 827, 830, 833, 833, 790, 821, 824, 828,
+
+ 789, 788, 834, 834, 56, 56, 56, 56, 56, 84,
+ 84, 84, 163, 163, 163, 171, 171, 255, 787, 255,
+ 255, 255, 621, 621, 690, 690, 784, 783, 782, 781,
+ 780, 779, 778, 777, 773, 772, 771, 770, 769, 768,
+ 767, 766, 765, 764, 763, 762, 761, 758, 757, 756,
+ 755, 754, 753, 752, 751, 750, 749, 748, 747, 746,
+ 745, 744, 743, 742, 741, 740, 739, 738, 737, 736,
+ 735, 734, 733, 732, 731, 730, 729, 728, 727, 726,
+ 725, 724, 723, 722, 721, 720, 719, 718, 717, 716,
+ 715, 714, 713, 712, 711, 710, 709, 708, 707, 706,
+
+ 705, 704, 703, 702, 701, 700, 699, 698, 697, 696,
+ 695, 694, 693, 692, 691, 689, 688, 687, 686, 685,
+ 684, 683, 682, 681, 680, 679, 678, 677, 676, 675,
+ 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
+ 664, 663, 662, 661, 655, 654, 653, 652, 651, 650,
+ 649, 648, 647, 646, 645, 644, 638, 637, 636, 635,
+ 634, 633, 632, 631, 630, 629, 628, 627, 626, 625,
+ 618, 613, 612, 611, 610, 609, 608, 607, 606, 605,
+ 604, 603, 602, 601, 600, 595, 594, 593, 592, 591,
+ 590, 589, 588, 587, 586, 585, 584, 583, 582, 581,
+
+ 575, 574, 573, 572, 571, 570, 569, 568, 567, 566,
+ 560, 559, 558, 557, 556, 555, 554, 553, 552, 551,
+ 550, 545, 544, 543, 542, 541, 540, 539, 538, 537,
+ 536, 535, 532, 531, 530, 529, 528, 527, 521, 520,
+ 519, 518, 517, 516, 515, 514, 513, 512, 511, 510,
+ 509, 508, 507, 506, 505, 504, 498, 497, 496, 495,
+ 494, 493, 492, 491, 490, 489, 488, 487, 486, 485,
+ 484, 483, 482, 481, 480, 479, 478, 477, 476, 475,
+ 474, 473, 472, 471, 470, 469, 468, 467, 466, 465,
+ 464, 463, 453, 452, 451, 450, 449, 443, 442, 441,
+
+ 440, 439, 438, 437, 436, 435, 434, 433, 432, 431,
+ 430, 429, 428, 427, 426, 422, 421, 420, 419, 418,
+ 417, 416, 415, 414, 413, 412, 411, 410, 409, 408,
+ 407, 406, 405, 404, 403, 402, 401, 400, 399, 398,
+ 397, 396, 395, 394, 393, 392, 388, 387, 386, 385,
+ 384, 383, 382, 381, 377, 373, 372, 371, 370, 369,
+ 365, 364, 363, 362, 361, 360, 359, 358, 354, 353,
+ 352, 349, 348, 347, 346, 345, 344, 343, 339, 338,
+ 337, 336, 335, 332, 331, 330, 329, 328, 327, 326,
+ 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
+
+ 315, 314, 313, 312, 311, 310, 309, 308, 304, 303,
+ 302, 301, 300, 299, 298, 297, 296, 295, 294, 293,
+ 292, 291, 290, 289, 288, 287, 286, 285, 284, 283,
+ 282, 281, 280, 279, 278, 277, 276, 273, 272, 271,
+ 268, 267, 266, 265, 264, 254, 253, 252, 251, 250,
+ 247, 246, 245, 238, 237, 236, 235, 234, 233, 230,
+ 229, 228, 227, 226, 225, 224, 223, 220, 217, 216,
+ 215, 212, 211, 210, 204, 203, 202, 201, 200, 199,
+ 198, 197, 192, 191, 190, 189, 188, 187, 186, 185,
+ 182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
+
+ 172, 161, 149, 125, 109, 81, 69, 63, 60, 59,
+ 835, 57, 57, 7, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835
+ } ;
+
+static yyconst flex_int16_t yy_chk[1283] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 9,
+ 791, 9, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 13, 15, 792, 16, 17, 17, 17, 17, 17,
+ 17, 17, 21, 21, 25, 15, 16, 26, 13, 19,
+ 35, 19, 19, 19, 19, 19, 19, 19, 23, 23,
+ 25, 36, 26, 26, 35, 36, 19, 19, 71, 30,
+ 27, 30, 27, 28, 19, 19, 27, 28, 37, 39,
+ 30, 758, 19, 19, 28, 143, 29, 28, 96, 96,
+
+ 29, 33, 37, 71, 143, 39, 29, 19, 39, 33,
+ 19, 20, 29, 20, 20, 20, 20, 20, 20, 20,
+ 40, 33, 47, 31, 47, 794, 47, 46, 20, 20,
+ 40, 31, 48, 48, 31, 106, 20, 31, 42, 34,
+ 758, 42, 34, 31, 20, 20, 34, 34, 41, 106,
+ 42, 34, 802, 43, 34, 41, 41, 42, 43, 20,
+ 41, 50, 43, 50, 44, 43, 41, 41, 44, 41,
+ 46, 58, 105, 58, 68, 68, 135, 48, 44, 120,
+ 142, 142, 124, 105, 48, 70, 70, 120, 48, 124,
+ 68, 68, 135, 48, 53, 53, 53, 53, 53, 53,
+
+ 53, 70, 70, 72, 144, 72, 72, 72, 72, 72,
+ 72, 72, 144, 148, 803, 126, 148, 804, 73, 73,
+ 72, 72, 73, 73, 73, 73, 73, 73, 73, 126,
+ 805, 116, 153, 153, 116, 116, 72, 72, 116, 152,
+ 116, 152, 810, 152, 154, 154, 160, 811, 160, 162,
+ 162, 162, 162, 162, 162, 162, 164, 164, 166, 166,
+ 164, 164, 164, 164, 164, 164, 164, 169, 169, 169,
+ 169, 169, 169, 169, 166, 166, 171, 153, 180, 184,
+ 184, 215, 215, 215, 153, 241, 813, 504, 153, 154,
+ 776, 505, 180, 153, 241, 814, 154, 504, 776, 171,
+
+ 154, 505, 167, 167, 818, 154, 167, 167, 167, 167,
+ 167, 167, 167, 170, 170, 170, 170, 170, 170, 170,
+ 247, 247, 247, 268, 268, 268, 279, 279, 279, 170,
+ 256, 256, 256, 256, 256, 256, 256, 257, 257, 257,
+ 257, 257, 257, 257, 786, 170, 288, 288, 288, 822,
+ 258, 258, 786, 257, 258, 258, 258, 258, 258, 258,
+ 258, 260, 260, 260, 260, 260, 260, 260, 825, 257,
+ 261, 261, 261, 261, 261, 261, 261, 292, 292, 292,
+ 301, 301, 301, 338, 338, 338, 261, 350, 350, 350,
+ 350, 350, 350, 350, 351, 351, 351, 351, 351, 351,
+
+ 351, 795, 261, 382, 382, 382, 393, 393, 393, 795,
+ 351, 394, 394, 394, 382, 382, 395, 395, 395, 443,
+ 443, 443, 483, 483, 483, 490, 351, 830, 605, 831,
+ 443, 443, 839, 483, 483, 519, 519, 519, 605, 490,
+ 490, 490, 490, 490, 490, 490, 519, 519, 533, 533,
+ 606, 621, 621, 796, 534, 534, 656, 656, 760, 606,
+ 606, 796, 533, 533, 533, 533, 533, 533, 534, 534,
+ 534, 534, 534, 534, 534, 554, 554, 554, 573, 573,
+ 573, 576, 576, 690, 690, 581, 533, 554, 578, 578,
+ 573, 775, 799, 840, 790, 576, 576, 576, 576, 576,
+
+ 576, 576, 578, 578, 578, 578, 578, 578, 580, 580,
+ 806, 533, 744, 760, 759, 808, 619, 619, 806, 744,
+ 581, 759, 580, 580, 580, 580, 580, 580, 580, 581,
+ 619, 619, 619, 619, 619, 619, 787, 798, 789, 788,
+ 581, 620, 620, 787, 798, 809, 775, 799, 658, 658,
+ 828, 785, 829, 809, 619, 620, 620, 620, 620, 620,
+ 620, 620, 658, 658, 658, 658, 658, 658, 660, 660,
+ 808, 826, 815, 819, 784, 783, 782, 781, 826, 619,
+ 815, 819, 660, 660, 660, 660, 660, 660, 660, 820,
+ 823, 828, 827, 829, 832, 833, 780, 820, 823, 827,
+
+ 779, 778, 832, 833, 836, 836, 836, 836, 836, 837,
+ 837, 837, 838, 838, 838, 841, 841, 842, 777, 842,
+ 842, 842, 843, 843, 844, 844, 774, 771, 769, 768,
+ 766, 763, 762, 761, 757, 756, 755, 754, 753, 752,
+ 751, 750, 749, 748, 747, 746, 745, 743, 742, 741,
+ 738, 735, 734, 733, 732, 731, 729, 728, 726, 724,
+ 721, 720, 719, 717, 716, 714, 713, 712, 711, 710,
+ 709, 708, 707, 706, 705, 704, 702, 701, 700, 699,
+ 698, 697, 695, 694, 693, 692, 691, 689, 688, 687,
+ 686, 685, 684, 683, 682, 681, 680, 679, 678, 677,
+
+ 676, 675, 674, 673, 672, 670, 669, 668, 667, 666,
+ 665, 664, 663, 662, 661, 654, 652, 651, 649, 648,
+ 647, 646, 645, 644, 643, 642, 641, 640, 639, 638,
+ 637, 635, 634, 633, 632, 631, 630, 629, 627, 626,
+ 625, 624, 623, 622, 618, 617, 616, 615, 614, 613,
+ 612, 611, 610, 609, 608, 607, 601, 599, 598, 597,
+ 596, 592, 591, 590, 589, 588, 587, 586, 585, 584,
+ 575, 571, 570, 568, 567, 565, 564, 563, 562, 561,
+ 560, 559, 558, 557, 555, 553, 552, 551, 550, 549,
+ 548, 547, 546, 545, 544, 542, 541, 537, 536, 535,
+
+ 532, 531, 529, 528, 526, 525, 524, 523, 522, 520,
+ 518, 517, 516, 515, 514, 513, 511, 510, 509, 508,
+ 507, 503, 502, 501, 500, 499, 498, 495, 494, 493,
+ 492, 491, 489, 488, 487, 486, 485, 484, 482, 481,
+ 474, 473, 470, 469, 466, 465, 464, 463, 452, 451,
+ 450, 448, 447, 446, 445, 444, 441, 439, 438, 437,
+ 435, 434, 432, 431, 430, 429, 427, 426, 421, 420,
+ 418, 417, 416, 415, 414, 413, 412, 411, 410, 409,
+ 407, 406, 405, 404, 403, 402, 401, 400, 399, 398,
+ 397, 396, 392, 388, 387, 386, 383, 381, 371, 369,
+
+ 365, 364, 363, 362, 360, 358, 353, 352, 349, 348,
+ 347, 346, 345, 344, 339, 337, 336, 335, 334, 333,
+ 331, 330, 327, 326, 325, 324, 323, 322, 321, 320,
+ 319, 318, 317, 316, 315, 314, 313, 312, 311, 310,
+ 309, 308, 307, 306, 305, 302, 300, 299, 298, 297,
+ 296, 295, 294, 293, 291, 287, 285, 284, 283, 282,
+ 278, 277, 276, 275, 274, 273, 272, 271, 267, 265,
+ 264, 254, 253, 252, 251, 250, 249, 248, 246, 245,
+ 244, 243, 242, 240, 239, 238, 237, 236, 235, 234,
+ 233, 232, 231, 230, 229, 228, 227, 226, 225, 224,
+
+ 223, 222, 221, 220, 219, 218, 217, 216, 214, 213,
+ 212, 211, 210, 209, 208, 207, 206, 205, 204, 203,
+ 202, 201, 200, 199, 198, 196, 195, 194, 193, 192,
+ 191, 190, 189, 188, 187, 186, 185, 183, 182, 181,
+ 179, 178, 177, 176, 174, 159, 158, 157, 156, 149,
+ 147, 146, 145, 141, 140, 139, 138, 137, 136, 134,
+ 133, 132, 131, 130, 129, 128, 127, 125, 123, 122,
+ 121, 119, 118, 117, 115, 114, 112, 111, 110, 109,
+ 108, 107, 104, 103, 102, 101, 100, 99, 98, 97,
+ 95, 94, 93, 92, 91, 90, 89, 88, 87, 83,
+
+ 79, 52, 45, 38, 32, 22, 18, 14, 12, 11,
+ 7, 6, 5, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835, 835, 835, 835, 835, 835, 835, 835, 835,
+ 835, 835
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "glsl_lexer.lpp"
+#line 2 "glsl_lexer.lpp"
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <ctype.h>
+#include "strtod.h"
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno + 1; \
+ yycolumn += yyleng; \
+ } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
+
+/* A macro for handling reserved words and keywords across language versions.
+ *
+ * Certain words start out as identifiers, become reserved words in
+ * later language revisions, and finally become language keywords.
+ *
+ * For example, consider the following lexer rule:
+ * samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER)
+ *
+ * This means that "samplerBuffer" will be treated as:
+ * - a keyword (SAMPLERBUFFER token) ...in GLSL >= 1.40
+ * - a reserved word - error ...in GLSL >= 1.30
+ * - an identifier ...in GLSL < 1.30
+ */
+#define KEYWORD(reserved_version, allowed_version, token) \
+ do { \
+ if (yyextra->language_version >= allowed_version) { \
+ return token; \
+ } else if (yyextra->language_version >= reserved_version) { \
+ _mesa_glsl_error(yylloc, yyextra, \
+ "Illegal use of reserved word `%s'", yytext); \
+ return ERROR_TOK; \
+ } else { \
+ yylval->identifier = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+/* The ES macro can be used in KEYWORD checks:
+ *
+ * word KEYWORD(110 || ES, 400, TOKEN)
+ * ...means the word is reserved in GLSL ES 1.00, while
+ *
+ * word KEYWORD(110, 130 || ES, TOKEN)
+ * ...means the word is a legal keyword in GLSL ES 1.00.
+ */
+#define ES yyextra->es_shader
+
+#line 1071 "glsl_lexer.cpp"
+
+#define INITIAL 0
+#define PP 1
+#define PRAGMA 2
+
+#define YY_EXTRA_TYPE struct _mesa_glsl_parse_state *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int _mesa_glsl_lex_init (yyscan_t* scanner);
+
+int _mesa_glsl_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int _mesa_glsl_lex_destroy (yyscan_t yyscanner );
+
+int _mesa_glsl_get_debug (yyscan_t yyscanner );
+
+void _mesa_glsl_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner );
+
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_in (yyscan_t yyscanner );
+
+void _mesa_glsl_set_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_out (yyscan_t yyscanner );
+
+void _mesa_glsl_set_out (FILE * out_str ,yyscan_t yyscanner );
+
+int _mesa_glsl_get_leng (yyscan_t yyscanner );
+
+char *_mesa_glsl_get_text (yyscan_t yyscanner );
+
+int _mesa_glsl_get_lineno (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner );
+
+int _mesa_glsl_get_column (yyscan_t yyscanner );
+
+void _mesa_glsl_set_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner );
+
+ void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int _mesa_glsl_wrap (yyscan_t yyscanner );
+#else
+extern int _mesa_glsl_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ unsigned n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int _mesa_glsl_lex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int _mesa_glsl_lex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 95 "glsl_lexer.lpp"
+
+
+#line 1312 "glsl_lexer.cpp"
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ _mesa_glsl__load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 836 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 835 );
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 97 "glsl_lexer.lpp"
+;
+ YY_BREAK
+/* Preprocessor tokens. */
+case 2:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 100 "glsl_lexer.lpp"
+;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 101 "glsl_lexer.lpp"
+{ BEGIN PP; return VERSION; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 102 "glsl_lexer.lpp"
+{ BEGIN PP; return EXTENSION; }
+ YY_BREAK
+case 5:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 103 "glsl_lexer.lpp"
+{
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+ }
+ YY_BREAK
+case 6:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 118 "glsl_lexer.lpp"
+{
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 132 "glsl_lexer.lpp"
+{
+ BEGIN PP;
+ return PRAGMA_DEBUG_ON;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 136 "glsl_lexer.lpp"
+{
+ BEGIN PP;
+ return PRAGMA_DEBUG_OFF;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 140 "glsl_lexer.lpp"
+{
+ BEGIN PP;
+ return PRAGMA_OPTIMIZE_ON;
+ }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 144 "glsl_lexer.lpp"
+{
+ BEGIN PP;
+ return PRAGMA_OPTIMIZE_OFF;
+ }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 148 "glsl_lexer.lpp"
+{
+ BEGIN PP;
+ return PRAGMA_INVARIANT_ALL;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 152 "glsl_lexer.lpp"
+{ BEGIN PRAGMA; }
+ YY_BREAK
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 154 "glsl_lexer.lpp"
+{ BEGIN 0; yylineno++; yycolumn = 0; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 155 "glsl_lexer.lpp"
+{ }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 157 "glsl_lexer.lpp"
+{ }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 158 "glsl_lexer.lpp"
+{ }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 159 "glsl_lexer.lpp"
+return COLON;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 160 "glsl_lexer.lpp"
+{
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 164 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+ YY_BREAK
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 168 "glsl_lexer.lpp"
+{ BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+#line 170 "glsl_lexer.lpp"
+{ yylineno++; yycolumn = 0; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 172 "glsl_lexer.lpp"
+return ATTRIBUTE;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 173 "glsl_lexer.lpp"
+return CONST_TOK;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 174 "glsl_lexer.lpp"
+return BOOL_TOK;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 175 "glsl_lexer.lpp"
+return FLOAT_TOK;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 176 "glsl_lexer.lpp"
+return INT_TOK;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 177 "glsl_lexer.lpp"
+KEYWORD(130, 130, UINT_TOK);
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 179 "glsl_lexer.lpp"
+return BREAK;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 180 "glsl_lexer.lpp"
+return CONTINUE;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 181 "glsl_lexer.lpp"
+return DO;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 182 "glsl_lexer.lpp"
+return WHILE;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 183 "glsl_lexer.lpp"
+return ELSE;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 184 "glsl_lexer.lpp"
+return FOR;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 185 "glsl_lexer.lpp"
+return IF;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 186 "glsl_lexer.lpp"
+return DISCARD;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 187 "glsl_lexer.lpp"
+return RETURN;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 189 "glsl_lexer.lpp"
+return BVEC2;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 190 "glsl_lexer.lpp"
+return BVEC3;
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 191 "glsl_lexer.lpp"
+return BVEC4;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 192 "glsl_lexer.lpp"
+return IVEC2;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 193 "glsl_lexer.lpp"
+return IVEC3;
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 194 "glsl_lexer.lpp"
+return IVEC4;
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 195 "glsl_lexer.lpp"
+KEYWORD(130, 130, UVEC2);
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 196 "glsl_lexer.lpp"
+KEYWORD(130, 130, UVEC3);
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 197 "glsl_lexer.lpp"
+KEYWORD(130, 130, UVEC4);
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 198 "glsl_lexer.lpp"
+return VEC2;
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 199 "glsl_lexer.lpp"
+return VEC3;
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 200 "glsl_lexer.lpp"
+return VEC4;
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 201 "glsl_lexer.lpp"
+return MAT2X2;
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 202 "glsl_lexer.lpp"
+return MAT3X3;
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 203 "glsl_lexer.lpp"
+return MAT4X4;
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 204 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT2X2);
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 205 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT2X3);
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 206 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT2X4);
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 207 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT3X2);
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 208 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT3X3);
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 209 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT3X4);
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 210 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT4X2);
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 211 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT4X3);
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 212 "glsl_lexer.lpp"
+KEYWORD(120, 120, MAT4X4);
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 214 "glsl_lexer.lpp"
+return IN_TOK;
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 215 "glsl_lexer.lpp"
+return OUT_TOK;
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 216 "glsl_lexer.lpp"
+return INOUT_TOK;
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 217 "glsl_lexer.lpp"
+return UNIFORM;
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 218 "glsl_lexer.lpp"
+return VARYING;
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 219 "glsl_lexer.lpp"
+KEYWORD(120, 120, CENTROID);
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 220 "glsl_lexer.lpp"
+KEYWORD(120 || ES, 120 || ES, INVARIANT);
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 221 "glsl_lexer.lpp"
+KEYWORD(130 || ES, 130, FLAT);
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 222 "glsl_lexer.lpp"
+KEYWORD(130, 130, SMOOTH);
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 223 "glsl_lexer.lpp"
+KEYWORD(130, 130, NOPERSPECTIVE);
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 225 "glsl_lexer.lpp"
+return SAMPLER1D;
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 226 "glsl_lexer.lpp"
+return SAMPLER2D;
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 227 "glsl_lexer.lpp"
+return SAMPLER3D;
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 228 "glsl_lexer.lpp"
+return SAMPLERCUBE;
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 229 "glsl_lexer.lpp"
+KEYWORD(130, 130, SAMPLER1DARRAY);
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 230 "glsl_lexer.lpp"
+KEYWORD(130, 130, SAMPLER2DARRAY);
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 231 "glsl_lexer.lpp"
+return SAMPLER1DSHADOW;
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 232 "glsl_lexer.lpp"
+return SAMPLER2DSHADOW;
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 233 "glsl_lexer.lpp"
+KEYWORD(130, 130, SAMPLERCUBESHADOW);
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 234 "glsl_lexer.lpp"
+KEYWORD(130, 130, SAMPLER1DARRAYSHADOW);
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 235 "glsl_lexer.lpp"
+KEYWORD(130, 130, SAMPLER2DARRAYSHADOW);
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 236 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLER1D);
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 237 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLER2D);
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 238 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLER3D);
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 239 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLERCUBE);
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 240 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLER1DARRAY);
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 241 "glsl_lexer.lpp"
+KEYWORD(130, 130, ISAMPLER2DARRAY);
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 242 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLER1D);
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 243 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLER2D);
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 244 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLER3D);
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 245 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLERCUBE);
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 246 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLER1DARRAY);
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 247 "glsl_lexer.lpp"
+KEYWORD(130, 130, USAMPLER2DARRAY);
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 250 "glsl_lexer.lpp"
+return STRUCT;
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 251 "glsl_lexer.lpp"
+return VOID_TOK;
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 253 "glsl_lexer.lpp"
+{
+ if ((yyextra->language_version >= 140)
+ || yyextra->AMD_conservative_depth_enable
+ || yyextra->ARB_explicit_attrib_location_enable
+ || yyextra->ARB_fragment_coord_conventions_enable) {
+ return LAYOUT_TOK;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 265 "glsl_lexer.lpp"
+return INC_OP;
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 266 "glsl_lexer.lpp"
+return DEC_OP;
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 267 "glsl_lexer.lpp"
+return LE_OP;
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 268 "glsl_lexer.lpp"
+return GE_OP;
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 269 "glsl_lexer.lpp"
+return EQ_OP;
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 270 "glsl_lexer.lpp"
+return NE_OP;
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 271 "glsl_lexer.lpp"
+return AND_OP;
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 272 "glsl_lexer.lpp"
+return OR_OP;
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 273 "glsl_lexer.lpp"
+return XOR_OP;
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 274 "glsl_lexer.lpp"
+return LEFT_OP;
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 275 "glsl_lexer.lpp"
+return RIGHT_OP;
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 277 "glsl_lexer.lpp"
+return MUL_ASSIGN;
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 278 "glsl_lexer.lpp"
+return DIV_ASSIGN;
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 279 "glsl_lexer.lpp"
+return ADD_ASSIGN;
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 280 "glsl_lexer.lpp"
+return MOD_ASSIGN;
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 281 "glsl_lexer.lpp"
+return LEFT_ASSIGN;
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 282 "glsl_lexer.lpp"
+return RIGHT_ASSIGN;
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 283 "glsl_lexer.lpp"
+return AND_ASSIGN;
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 284 "glsl_lexer.lpp"
+return XOR_ASSIGN;
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 285 "glsl_lexer.lpp"
+return OR_ASSIGN;
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 286 "glsl_lexer.lpp"
+return SUB_ASSIGN;
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 288 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 10);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 292 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext + 2, NULL, 16);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 296 "glsl_lexer.lpp"
+{
+ yylval->n = strtol(yytext, NULL, 8);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 301 "glsl_lexer.lpp"
+{
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 305 "glsl_lexer.lpp"
+{
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 309 "glsl_lexer.lpp"
+{
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 313 "glsl_lexer.lpp"
+{
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 317 "glsl_lexer.lpp"
+{
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 322 "glsl_lexer.lpp"
+{
+ yylval->n = 1;
+ return BOOLCONSTANT;
+ }
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 326 "glsl_lexer.lpp"
+{
+ yylval->n = 0;
+ return BOOLCONSTANT;
+ }
+ YY_BREAK
+/* Reserved words in GLSL 1.10. */
+case 128:
+YY_RULE_SETUP
+#line 333 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, ASM);
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 334 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, CLASS);
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 335 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, UNION);
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 336 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, ENUM);
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 337 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, TYPEDEF);
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 338 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, TEMPLATE);
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 339 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, THIS);
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 340 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, PACKED_TOK);
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 341 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, GOTO);
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 342 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 130, SWITCH);
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 343 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 130, DEFAULT);
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 344 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, INLINE_TOK);
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 345 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, NOINLINE);
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 346 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, VOLATILE);
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 347 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, PUBLIC_TOK);
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 348 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, STATIC);
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 349 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, EXTERN);
+ YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 350 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, EXTERNAL);
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 351 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, INTERFACE);
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 352 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, LONG_TOK);
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 353 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, SHORT_TOK);
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 354 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 400, DOUBLE_TOK);
+ YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 355 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, HALF);
+ YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 356 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, FIXED_TOK);
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 357 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, UNSIGNED);
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 358 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, INPUT_TOK);
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 359 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, OUTPUT);
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 360 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, HVEC2);
+ YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 361 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, HVEC3);
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 362 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, HVEC4);
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 363 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 400, DVEC2);
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 364 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 400, DVEC3);
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 365 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 400, DVEC4);
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 366 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, FVEC2);
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 367 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, FVEC3);
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 368 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, FVEC4);
+ YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 369 "glsl_lexer.lpp"
+return SAMPLER2DRECT;
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 370 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, SAMPLER3DRECT);
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 371 "glsl_lexer.lpp"
+return SAMPLER2DRECTSHADOW;
+ YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 372 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, SIZEOF);
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 373 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, CAST);
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 374 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, NAMESPACE);
+ YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 375 "glsl_lexer.lpp"
+KEYWORD(110 || ES, 999, USING);
+ YY_BREAK
+/* Additional reserved words in GLSL 1.20. */
+case 171:
+YY_RULE_SETUP
+#line 378 "glsl_lexer.lpp"
+KEYWORD(120, 130 || ES, LOWP);
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 379 "glsl_lexer.lpp"
+KEYWORD(120, 130 || ES, MEDIUMP);
+ YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 380 "glsl_lexer.lpp"
+KEYWORD(120, 130 || ES, HIGHP);
+ YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 381 "glsl_lexer.lpp"
+KEYWORD(120, 130 || ES, PRECISION);
+ YY_BREAK
+/* Additional reserved words in GLSL 1.30. */
+case 175:
+YY_RULE_SETUP
+#line 384 "glsl_lexer.lpp"
+KEYWORD(130, 130, CASE);
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 385 "glsl_lexer.lpp"
+KEYWORD(130, 999, COMMON);
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 386 "glsl_lexer.lpp"
+KEYWORD(130, 999, PARTITION);
+ YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 387 "glsl_lexer.lpp"
+KEYWORD(130, 999, ACTIVE);
+ YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 388 "glsl_lexer.lpp"
+KEYWORD(130 || ES, 999, SUPERP);
+ YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 389 "glsl_lexer.lpp"
+KEYWORD(130, 140, SAMPLERBUFFER);
+ YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 390 "glsl_lexer.lpp"
+KEYWORD(130, 999, FILTER);
+ YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 391 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE1D);
+ YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 392 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE2D);
+ YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 393 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE3D);
+ YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 394 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGECUBE);
+ YY_BREAK
+case 186:
+YY_RULE_SETUP
+#line 395 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGE1D);
+ YY_BREAK
+case 187:
+YY_RULE_SETUP
+#line 396 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGE2D);
+ YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 397 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGE3D);
+ YY_BREAK
+case 189:
+YY_RULE_SETUP
+#line 398 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGECUBE);
+ YY_BREAK
+case 190:
+YY_RULE_SETUP
+#line 399 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGE1D);
+ YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 400 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGE2D);
+ YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 401 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGE3D);
+ YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 402 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGECUBE);
+ YY_BREAK
+case 194:
+YY_RULE_SETUP
+#line 403 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE1DARRAY);
+ YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 404 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE2DARRAY);
+ YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 405 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGE1DARRAY);
+ YY_BREAK
+case 197:
+YY_RULE_SETUP
+#line 406 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGE2DARRAY);
+ YY_BREAK
+case 198:
+YY_RULE_SETUP
+#line 407 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGE1DARRAY);
+ YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 408 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGE2DARRAY);
+ YY_BREAK
+case 200:
+YY_RULE_SETUP
+#line 409 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE1DSHADOW);
+ YY_BREAK
+case 201:
+YY_RULE_SETUP
+#line 410 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE2DSHADOW);
+ YY_BREAK
+case 202:
+YY_RULE_SETUP
+#line 411 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE1DARRAYSHADOW);
+ YY_BREAK
+case 203:
+YY_RULE_SETUP
+#line 412 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
+ YY_BREAK
+case 204:
+YY_RULE_SETUP
+#line 413 "glsl_lexer.lpp"
+KEYWORD(130, 999, IMAGEBUFFER);
+ YY_BREAK
+case 205:
+YY_RULE_SETUP
+#line 414 "glsl_lexer.lpp"
+KEYWORD(130, 999, IIMAGEBUFFER);
+ YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 415 "glsl_lexer.lpp"
+KEYWORD(130, 999, UIMAGEBUFFER);
+ YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 416 "glsl_lexer.lpp"
+KEYWORD(130, 999, ROW_MAJOR);
+ YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 418 "glsl_lexer.lpp"
+{
+ struct _mesa_glsl_parse_state *state = yyextra;
+ void *ctx = state;
+ yylval->identifier = talloc_strdup(ctx, yytext);
+ return IDENTIFIER;
+ }
+ YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 425 "glsl_lexer.lpp"
+{ return yytext[0]; }
+ YY_BREAK
+case 210:
+YY_RULE_SETUP
+#line 427 "glsl_lexer.lpp"
+ECHO;
+ YY_BREAK
+#line 2555 "glsl_lexer.cpp"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(PP):
+case YY_STATE_EOF(PRAGMA):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * _mesa_glsl_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( _mesa_glsl_wrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of _mesa_glsl_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ _mesa_glsl_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ _mesa_glsl_restart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _mesa_glsl_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 836 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 836 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 835);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ _mesa_glsl_restart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( _mesa_glsl_wrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void _mesa_glsl_restart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ _mesa_glsl__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * _mesa_glsl_pop_buffer_state();
+ * _mesa_glsl_push_buffer_state(new_buffer);
+ */
+ _mesa_glsl_ensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ _mesa_glsl__load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (_mesa_glsl_wrap()) processing, but the only time this flag
+ * is looked at is after _mesa_glsl_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) _mesa_glsl_alloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ _mesa_glsl__init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with _mesa_glsl__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ _mesa_glsl_free((void *) b->yy_ch_buf ,yyscanner );
+
+ _mesa_glsl_free((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a _mesa_glsl_restart() or at EOF.
+ */
+ static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ _mesa_glsl__flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then _mesa_glsl__init_buffer was _probably_
+ * called from _mesa_glsl_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ _mesa_glsl_ensure_buffer_stack(yyscanner);
+
+ /* This block is copied from _mesa_glsl__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from _mesa_glsl__switch_to_buffer. */
+ _mesa_glsl__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ _mesa_glsl__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_realloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ _mesa_glsl__switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * _mesa_glsl__scan_bytes() instead.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return _mesa_glsl__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) _mesa_glsl_alloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = _mesa_glsl__scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in _mesa_glsl__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *_mesa_glsl_get_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "_mesa_glsl_set_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "_mesa_glsl_set_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see _mesa_glsl__switch_to_buffer
+ */
+void _mesa_glsl_set_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void _mesa_glsl_set_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int _mesa_glsl_get_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void _mesa_glsl_set_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void _mesa_glsl_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* _mesa_glsl_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int _mesa_glsl_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* _mesa_glsl_lex_init_extra has the same functionality as _mesa_glsl_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to _mesa_glsl_alloc in
+ * the yyextra field.
+ */
+
+int _mesa_glsl_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ _mesa_glsl_set_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ _mesa_glsl_set_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from _mesa_glsl_lex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * _mesa_glsl_lex_init()
+ */
+ return 0;
+}
+
+/* _mesa_glsl_lex_destroy is for both reentrant and non-reentrant scanners. */
+int _mesa_glsl_lex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ _mesa_glsl_pop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ _mesa_glsl_free(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ _mesa_glsl_free(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * _mesa_glsl_lex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ _mesa_glsl_free ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *_mesa_glsl_alloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *_mesa_glsl_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void _mesa_glsl_free (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see _mesa_glsl_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 427 "glsl_lexer.lpp"
+
+
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+ _mesa_glsl_lex_init_extra(state,& state->scanner);
+ _mesa_glsl__scan_string(string,state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+ _mesa_glsl_lex_destroy(state->scanner);
+}
+
diff --git a/mesalib/src/glsl/glsl_lexer.lpp b/mesalib/src/glsl/glsl_lexer.lpp
index 35405dad6..4d6866390 100644
--- a/mesalib/src/glsl/glsl_lexer.lpp
+++ b/mesalib/src/glsl/glsl_lexer.lpp
@@ -1,439 +1,440 @@
-%{
-/*
- * Copyright © 2008, 2009 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 <ctype.h>
-#include "strtod.h"
-#include "ast.h"
-#include "glsl_parser_extras.h"
-#include "glsl_parser.h"
-
-#define YY_USER_ACTION \
- do { \
- yylloc->source = 0; \
- yylloc->first_column = yycolumn + 1; \
- yylloc->first_line = yylineno + 1; \
- yycolumn += yyleng; \
- } while(0);
-
-#define YY_USER_INIT yylineno = 0; yycolumn = 0;
-
-#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
-
-/* A macro for handling reserved words and keywords across language versions.
- *
- * Certain words start out as identifiers, become reserved words in
- * later language revisions, and finally become language keywords.
- *
- * For example, consider the following lexer rule:
- * samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER)
- *
- * This means that "samplerBuffer" will be treated as:
- * - a keyword (SAMPLERBUFFER token) ...in GLSL >= 1.40
- * - a reserved word - error ...in GLSL >= 1.30
- * - an identifier ...in GLSL < 1.30
- */
-#define KEYWORD(reserved_version, allowed_version, token) \
- do { \
- if (yyextra->language_version >= allowed_version) { \
- return token; \
- } else if (yyextra->language_version >= reserved_version) { \
- _mesa_glsl_error(yylloc, yyextra, \
- "Illegal use of reserved word `%s'", yytext); \
- return ERROR_TOK; \
- } else { \
- yylval->identifier = strdup(yytext); \
- return IDENTIFIER; \
- } \
- } while (0)
-
-/* The ES macro can be used in KEYWORD checks:
- *
- * word KEYWORD(110 || ES, 400, TOKEN)
- * ...means the word is reserved in GLSL ES 1.00, while
- *
- * word KEYWORD(110, 130 || ES, TOKEN)
- * ...means the word is a legal keyword in GLSL ES 1.00.
- */
-#define ES yyextra->es_shader
-%}
-
-%option bison-bridge bison-locations reentrant noyywrap
-%option nounput noyy_top_state
-%option never-interactive
-%option prefix="_mesa_glsl_"
-%option extra-type="struct _mesa_glsl_parse_state *"
-
-%x PP PRAGMA
-
-DEC_INT [1-9][0-9]*
-HEX_INT 0[xX][0-9a-fA-F]+
-OCT_INT 0[0-7]*
-INT ({DEC_INT}|{HEX_INT}|{OCT_INT})
-SPC [ \t]*
-SPCP [ \t]+
-HASH ^{SPC}#{SPC}
-%%
-
-[ \r\t]+ ;
-
- /* Preprocessor tokens. */
-^[ \t]*#[ \t]*$ ;
-^[ \t]*#[ \t]*version { BEGIN PP; return VERSION; }
-^[ \t]*#[ \t]*extension { BEGIN PP; return EXTENSION; }
-{HASH}line{SPCP}{INT}{SPCP}{INT}{SPC}$ {
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
- yylloc->source = strtol(ptr, NULL, 0);
- }
-{HASH}line{SPCP}{INT}{SPC}$ {
- /* Eat characters until the first digit is
- * encountered
- */
- char *ptr = yytext;
- while (!isdigit(*ptr))
- ptr++;
-
- /* Subtract one from the line number because
- * yylineno is zero-based instead of
- * one-based.
- */
- yylineno = strtol(ptr, &ptr, 0) - 1;
- }
-^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}on{SPC}\) {
- BEGIN PP;
- return PRAGMA_DEBUG_ON;
- }
-^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}off{SPC}\) {
- BEGIN PP;
- return PRAGMA_DEBUG_OFF;
- }
-^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}on{SPC}\) {
- BEGIN PP;
- return PRAGMA_OPTIMIZE_ON;
- }
-^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}off{SPC}\) {
- BEGIN PP;
- return PRAGMA_OPTIMIZE_OFF;
- }
-^{SPC}#{SPC}pragma{SPCP}STDGL{SPCP}invariant{SPC}\({SPC}all{SPC}\) {
- BEGIN PP;
- return PRAGMA_INVARIANT_ALL;
- }
-^{SPC}#{SPC}pragma{SPCP} { BEGIN PRAGMA; }
-
-<PRAGMA>\n { BEGIN 0; yylineno++; yycolumn = 0; }
-<PRAGMA>. { }
-
-<PP>\/\/[^\n]* { }
-<PP>[ \t\r]* { }
-<PP>: return COLON;
-<PP>[_a-zA-Z][_a-zA-Z0-9]* {
- yylval->identifier = strdup(yytext);
- return IDENTIFIER;
- }
-<PP>[1-9][0-9]* {
- yylval->n = strtol(yytext, NULL, 10);
- return INTCONSTANT;
- }
-<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
-
-\n { yylineno++; yycolumn = 0; }
-
-attribute return ATTRIBUTE;
-const return CONST_TOK;
-bool return BOOL_TOK;
-float return FLOAT_TOK;
-int return INT_TOK;
-uint KEYWORD(130, 130, UINT_TOK);
-
-break return BREAK;
-continue return CONTINUE;
-do return DO;
-while return WHILE;
-else return ELSE;
-for return FOR;
-if return IF;
-discard return DISCARD;
-return return RETURN;
-
-bvec2 return BVEC2;
-bvec3 return BVEC3;
-bvec4 return BVEC4;
-ivec2 return IVEC2;
-ivec3 return IVEC3;
-ivec4 return IVEC4;
-uvec2 KEYWORD(130, 130, UVEC2);
-uvec3 KEYWORD(130, 130, UVEC3);
-uvec4 KEYWORD(130, 130, UVEC4);
-vec2 return VEC2;
-vec3 return VEC3;
-vec4 return VEC4;
-mat2 return MAT2X2;
-mat3 return MAT3X3;
-mat4 return MAT4X4;
-mat2x2 KEYWORD(120, 120, MAT2X2);
-mat2x3 KEYWORD(120, 120, MAT2X3);
-mat2x4 KEYWORD(120, 120, MAT2X4);
-mat3x2 KEYWORD(120, 120, MAT3X2);
-mat3x3 KEYWORD(120, 120, MAT3X3);
-mat3x4 KEYWORD(120, 120, MAT3X4);
-mat4x2 KEYWORD(120, 120, MAT4X2);
-mat4x3 KEYWORD(120, 120, MAT4X3);
-mat4x4 KEYWORD(120, 120, MAT4X4);
-
-in return IN_TOK;
-out return OUT_TOK;
-inout return INOUT_TOK;
-uniform return UNIFORM;
-varying return VARYING;
-centroid KEYWORD(120, 120, CENTROID);
-invariant KEYWORD(120 || ES, 120 || ES, INVARIANT);
-flat KEYWORD(130 || ES, 130, FLAT);
-smooth KEYWORD(130, 130, SMOOTH);
-noperspective KEYWORD(130, 130, NOPERSPECTIVE);
-
-sampler1D return SAMPLER1D;
-sampler2D return SAMPLER2D;
-sampler3D return SAMPLER3D;
-samplerCube return SAMPLERCUBE;
-sampler1DArray KEYWORD(130, 130, SAMPLER1DARRAY);
-sampler2DArray KEYWORD(130, 130, SAMPLER2DARRAY);
-sampler1DShadow return SAMPLER1DSHADOW;
-sampler2DShadow return SAMPLER2DSHADOW;
-samplerCubeShadow KEYWORD(130, 130, SAMPLERCUBESHADOW);
-sampler1DArrayShadow KEYWORD(130, 130, SAMPLER1DARRAYSHADOW);
-sampler2DArrayShadow KEYWORD(130, 130, SAMPLER2DARRAYSHADOW);
-isampler1D KEYWORD(130, 130, ISAMPLER1D);
-isampler2D KEYWORD(130, 130, ISAMPLER2D);
-isampler3D KEYWORD(130, 130, ISAMPLER3D);
-isamplerCube KEYWORD(130, 130, ISAMPLERCUBE);
-isampler1DArray KEYWORD(130, 130, ISAMPLER1DARRAY);
-isampler2DArray KEYWORD(130, 130, ISAMPLER2DARRAY);
-usampler1D KEYWORD(130, 130, USAMPLER1D);
-usampler2D KEYWORD(130, 130, USAMPLER2D);
-usampler3D KEYWORD(130, 130, USAMPLER3D);
-usamplerCube KEYWORD(130, 130, USAMPLERCUBE);
-usampler1DArray KEYWORD(130, 130, USAMPLER1DARRAY);
-usampler2DArray KEYWORD(130, 130, USAMPLER2DARRAY);
-
-
-struct return STRUCT;
-void return VOID_TOK;
-
-layout {
- if ((yyextra->language_version >= 140)
- || yyextra->ARB_explicit_attrib_location_enable
- || (yyextra->ARB_fragment_coord_conventions_enable)){
- return LAYOUT_TOK;
- } else {
- yylval->identifier = strdup(yytext);
- return IDENTIFIER;
- }
- }
-
-\+\+ return INC_OP;
--- return DEC_OP;
-\<= return LE_OP;
->= return GE_OP;
-== return EQ_OP;
-!= return NE_OP;
-&& return AND_OP;
-\|\| return OR_OP;
-"^^" return XOR_OP;
-"<<" return LEFT_OP;
-">>" return RIGHT_OP;
-
-\*= return MUL_ASSIGN;
-\/= return DIV_ASSIGN;
-\+= return ADD_ASSIGN;
-\%= return MOD_ASSIGN;
-\<\<= return LEFT_ASSIGN;
->>= return RIGHT_ASSIGN;
-&= return AND_ASSIGN;
-"^=" return XOR_ASSIGN;
-\|= return OR_ASSIGN;
--= return SUB_ASSIGN;
-
-[1-9][0-9]*[uU]? {
- yylval->n = strtol(yytext, NULL, 10);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
-0[xX][0-9a-fA-F]+[uU]? {
- yylval->n = strtol(yytext + 2, NULL, 16);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
-0[0-7]*[uU]? {
- yylval->n = strtol(yytext, NULL, 8);
- return IS_UINT ? UINTCONSTANT : INTCONSTANT;
- }
-
-[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
-\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
-[0-9]+\.([eE][+-]?[0-9]+)?[fF]? {
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
-[0-9]+[eE][+-]?[0-9]+[fF]? {
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
-[0-9]+[fF] {
- yylval->real = glsl_strtod(yytext, NULL);
- return FLOATCONSTANT;
- }
-
-true {
- yylval->n = 1;
- return BOOLCONSTANT;
- }
-false {
- yylval->n = 0;
- return BOOLCONSTANT;
- }
-
-
- /* Reserved words in GLSL 1.10. */
-asm KEYWORD(110 || ES, 999, ASM);
-class KEYWORD(110 || ES, 999, CLASS);
-union KEYWORD(110 || ES, 999, UNION);
-enum KEYWORD(110 || ES, 999, ENUM);
-typedef KEYWORD(110 || ES, 999, TYPEDEF);
-template KEYWORD(110 || ES, 999, TEMPLATE);
-this KEYWORD(110 || ES, 999, THIS);
-packed KEYWORD(110 || ES, 999, PACKED_TOK);
-goto KEYWORD(110 || ES, 999, GOTO);
-switch KEYWORD(110 || ES, 130, SWITCH);
-default KEYWORD(110 || ES, 130, DEFAULT);
-inline KEYWORD(110 || ES, 999, INLINE_TOK);
-noinline KEYWORD(110 || ES, 999, NOINLINE);
-volatile KEYWORD(110 || ES, 999, VOLATILE);
-public KEYWORD(110 || ES, 999, PUBLIC_TOK);
-static KEYWORD(110 || ES, 999, STATIC);
-extern KEYWORD(110 || ES, 999, EXTERN);
-external KEYWORD(110 || ES, 999, EXTERNAL);
-interface KEYWORD(110 || ES, 999, INTERFACE);
-long KEYWORD(110 || ES, 999, LONG_TOK);
-short KEYWORD(110 || ES, 999, SHORT_TOK);
-double KEYWORD(110 || ES, 400, DOUBLE_TOK);
-half KEYWORD(110 || ES, 999, HALF);
-fixed KEYWORD(110 || ES, 999, FIXED_TOK);
-unsigned KEYWORD(110 || ES, 999, UNSIGNED);
-input KEYWORD(110 || ES, 999, INPUT_TOK);
-output KEYWORD(110 || ES, 999, OUTPUT);
-hvec2 KEYWORD(110 || ES, 999, HVEC2);
-hvec3 KEYWORD(110 || ES, 999, HVEC3);
-hvec4 KEYWORD(110 || ES, 999, HVEC4);
-dvec2 KEYWORD(110 || ES, 400, DVEC2);
-dvec3 KEYWORD(110 || ES, 400, DVEC3);
-dvec4 KEYWORD(110 || ES, 400, DVEC4);
-fvec2 KEYWORD(110 || ES, 999, FVEC2);
-fvec3 KEYWORD(110 || ES, 999, FVEC3);
-fvec4 KEYWORD(110 || ES, 999, FVEC4);
-sampler2DRect return SAMPLER2DRECT;
-sampler3DRect KEYWORD(110 || ES, 999, SAMPLER3DRECT);
-sampler2DRectShadow return SAMPLER2DRECTSHADOW;
-sizeof KEYWORD(110 || ES, 999, SIZEOF);
-cast KEYWORD(110 || ES, 999, CAST);
-namespace KEYWORD(110 || ES, 999, NAMESPACE);
-using KEYWORD(110 || ES, 999, USING);
-
- /* Additional reserved words in GLSL 1.20. */
-lowp KEYWORD(120, 130 || ES, LOWP);
-mediump KEYWORD(120, 130 || ES, MEDIUMP);
-highp KEYWORD(120, 130 || ES, HIGHP);
-precision KEYWORD(120, 130 || ES, PRECISION);
-
- /* Additional reserved words in GLSL 1.30. */
-case KEYWORD(130, 130, CASE);
-common KEYWORD(130, 999, COMMON);
-partition KEYWORD(130, 999, PARTITION);
-active KEYWORD(130, 999, ACTIVE);
-superp KEYWORD(130 || ES, 999, SUPERP);
-samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER);
-filter KEYWORD(130, 999, FILTER);
-image1D KEYWORD(130, 999, IMAGE1D);
-image2D KEYWORD(130, 999, IMAGE2D);
-image3D KEYWORD(130, 999, IMAGE3D);
-imageCube KEYWORD(130, 999, IMAGECUBE);
-iimage1D KEYWORD(130, 999, IIMAGE1D);
-iimage2D KEYWORD(130, 999, IIMAGE2D);
-iimage3D KEYWORD(130, 999, IIMAGE3D);
-iimageCube KEYWORD(130, 999, IIMAGECUBE);
-uimage1D KEYWORD(130, 999, UIMAGE1D);
-uimage2D KEYWORD(130, 999, UIMAGE2D);
-uimage3D KEYWORD(130, 999, UIMAGE3D);
-uimageCube KEYWORD(130, 999, UIMAGECUBE);
-image1DArray KEYWORD(130, 999, IMAGE1DARRAY);
-image2DArray KEYWORD(130, 999, IMAGE2DARRAY);
-iimage1DArray KEYWORD(130, 999, IIMAGE1DARRAY);
-iimage2DArray KEYWORD(130, 999, IIMAGE2DARRAY);
-uimage1DArray KEYWORD(130, 999, UIMAGE1DARRAY);
-uimage2DArray KEYWORD(130, 999, UIMAGE2DARRAY);
-image1DShadow KEYWORD(130, 999, IMAGE1DSHADOW);
-image2DShadow KEYWORD(130, 999, IMAGE2DSHADOW);
-image1DArrayShadow KEYWORD(130, 999, IMAGE1DARRAYSHADOW);
-image2DArrayShadow KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
-imageBuffer KEYWORD(130, 999, IMAGEBUFFER);
-iimageBuffer KEYWORD(130, 999, IIMAGEBUFFER);
-uimageBuffer KEYWORD(130, 999, UIMAGEBUFFER);
-row_major KEYWORD(130, 999, ROW_MAJOR);
-
-[_a-zA-Z][_a-zA-Z0-9]* {
- struct _mesa_glsl_parse_state *state = yyextra;
- void *ctx = state;
- yylval->identifier = talloc_strdup(ctx, yytext);
- return IDENTIFIER;
- }
-
-. { return yytext[0]; }
-
-%%
-
-void
-_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
-{
- yylex_init_extra(state, & state->scanner);
- yy_scan_string(string, state->scanner);
-}
-
-void
-_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
-{
- yylex_destroy(state->scanner);
-}
+%{
+/*
+ * Copyright © 2008, 2009 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <ctype.h>
+#include "strtod.h"
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->source = 0; \
+ yylloc->first_column = yycolumn + 1; \
+ yylloc->first_line = yylineno + 1; \
+ yycolumn += yyleng; \
+ } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
+
+/* A macro for handling reserved words and keywords across language versions.
+ *
+ * Certain words start out as identifiers, become reserved words in
+ * later language revisions, and finally become language keywords.
+ *
+ * For example, consider the following lexer rule:
+ * samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER)
+ *
+ * This means that "samplerBuffer" will be treated as:
+ * - a keyword (SAMPLERBUFFER token) ...in GLSL >= 1.40
+ * - a reserved word - error ...in GLSL >= 1.30
+ * - an identifier ...in GLSL < 1.30
+ */
+#define KEYWORD(reserved_version, allowed_version, token) \
+ do { \
+ if (yyextra->language_version >= allowed_version) { \
+ return token; \
+ } else if (yyextra->language_version >= reserved_version) { \
+ _mesa_glsl_error(yylloc, yyextra, \
+ "Illegal use of reserved word `%s'", yytext); \
+ return ERROR_TOK; \
+ } else { \
+ yylval->identifier = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+/* The ES macro can be used in KEYWORD checks:
+ *
+ * word KEYWORD(110 || ES, 400, TOKEN)
+ * ...means the word is reserved in GLSL ES 1.00, while
+ *
+ * word KEYWORD(110, 130 || ES, TOKEN)
+ * ...means the word is a legal keyword in GLSL ES 1.00.
+ */
+#define ES yyextra->es_shader
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option nounput noyy_top_state
+%option never-interactive
+%option prefix="_mesa_glsl_"
+%option extra-type="struct _mesa_glsl_parse_state *"
+
+%x PP PRAGMA
+
+DEC_INT [1-9][0-9]*
+HEX_INT 0[xX][0-9a-fA-F]+
+OCT_INT 0[0-7]*
+INT ({DEC_INT}|{HEX_INT}|{OCT_INT})
+SPC [ \t]*
+SPCP [ \t]+
+HASH ^{SPC}#{SPC}
+%%
+
+[ \r\t]+ ;
+
+ /* Preprocessor tokens. */
+^[ \t]*#[ \t]*$ ;
+^[ \t]*#[ \t]*version { BEGIN PP; return VERSION; }
+^[ \t]*#[ \t]*extension { BEGIN PP; return EXTENSION; }
+{HASH}line{SPCP}{INT}{SPCP}{INT}{SPC}$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+ }
+{HASH}line{SPCP}{INT}{SPC}$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ }
+^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}on{SPC}\) {
+ BEGIN PP;
+ return PRAGMA_DEBUG_ON;
+ }
+^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}off{SPC}\) {
+ BEGIN PP;
+ return PRAGMA_DEBUG_OFF;
+ }
+^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}on{SPC}\) {
+ BEGIN PP;
+ return PRAGMA_OPTIMIZE_ON;
+ }
+^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}off{SPC}\) {
+ BEGIN PP;
+ return PRAGMA_OPTIMIZE_OFF;
+ }
+^{SPC}#{SPC}pragma{SPCP}STDGL{SPCP}invariant{SPC}\({SPC}all{SPC}\) {
+ BEGIN PP;
+ return PRAGMA_INVARIANT_ALL;
+ }
+^{SPC}#{SPC}pragma{SPCP} { BEGIN PRAGMA; }
+
+<PRAGMA>\n { BEGIN 0; yylineno++; yycolumn = 0; }
+<PRAGMA>. { }
+
+<PP>\/\/[^\n]* { }
+<PP>[ \t\r]* { }
+<PP>: return COLON;
+<PP>[_a-zA-Z][_a-zA-Z0-9]* {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+<PP>[1-9][0-9]* {
+ yylval->n = strtol(yytext, NULL, 10);
+ return INTCONSTANT;
+ }
+<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+
+\n { yylineno++; yycolumn = 0; }
+
+attribute return ATTRIBUTE;
+const return CONST_TOK;
+bool return BOOL_TOK;
+float return FLOAT_TOK;
+int return INT_TOK;
+uint KEYWORD(130, 130, UINT_TOK);
+
+break return BREAK;
+continue return CONTINUE;
+do return DO;
+while return WHILE;
+else return ELSE;
+for return FOR;
+if return IF;
+discard return DISCARD;
+return return RETURN;
+
+bvec2 return BVEC2;
+bvec3 return BVEC3;
+bvec4 return BVEC4;
+ivec2 return IVEC2;
+ivec3 return IVEC3;
+ivec4 return IVEC4;
+uvec2 KEYWORD(130, 130, UVEC2);
+uvec3 KEYWORD(130, 130, UVEC3);
+uvec4 KEYWORD(130, 130, UVEC4);
+vec2 return VEC2;
+vec3 return VEC3;
+vec4 return VEC4;
+mat2 return MAT2X2;
+mat3 return MAT3X3;
+mat4 return MAT4X4;
+mat2x2 KEYWORD(120, 120, MAT2X2);
+mat2x3 KEYWORD(120, 120, MAT2X3);
+mat2x4 KEYWORD(120, 120, MAT2X4);
+mat3x2 KEYWORD(120, 120, MAT3X2);
+mat3x3 KEYWORD(120, 120, MAT3X3);
+mat3x4 KEYWORD(120, 120, MAT3X4);
+mat4x2 KEYWORD(120, 120, MAT4X2);
+mat4x3 KEYWORD(120, 120, MAT4X3);
+mat4x4 KEYWORD(120, 120, MAT4X4);
+
+in return IN_TOK;
+out return OUT_TOK;
+inout return INOUT_TOK;
+uniform return UNIFORM;
+varying return VARYING;
+centroid KEYWORD(120, 120, CENTROID);
+invariant KEYWORD(120 || ES, 120 || ES, INVARIANT);
+flat KEYWORD(130 || ES, 130, FLAT);
+smooth KEYWORD(130, 130, SMOOTH);
+noperspective KEYWORD(130, 130, NOPERSPECTIVE);
+
+sampler1D return SAMPLER1D;
+sampler2D return SAMPLER2D;
+sampler3D return SAMPLER3D;
+samplerCube return SAMPLERCUBE;
+sampler1DArray KEYWORD(130, 130, SAMPLER1DARRAY);
+sampler2DArray KEYWORD(130, 130, SAMPLER2DARRAY);
+sampler1DShadow return SAMPLER1DSHADOW;
+sampler2DShadow return SAMPLER2DSHADOW;
+samplerCubeShadow KEYWORD(130, 130, SAMPLERCUBESHADOW);
+sampler1DArrayShadow KEYWORD(130, 130, SAMPLER1DARRAYSHADOW);
+sampler2DArrayShadow KEYWORD(130, 130, SAMPLER2DARRAYSHADOW);
+isampler1D KEYWORD(130, 130, ISAMPLER1D);
+isampler2D KEYWORD(130, 130, ISAMPLER2D);
+isampler3D KEYWORD(130, 130, ISAMPLER3D);
+isamplerCube KEYWORD(130, 130, ISAMPLERCUBE);
+isampler1DArray KEYWORD(130, 130, ISAMPLER1DARRAY);
+isampler2DArray KEYWORD(130, 130, ISAMPLER2DARRAY);
+usampler1D KEYWORD(130, 130, USAMPLER1D);
+usampler2D KEYWORD(130, 130, USAMPLER2D);
+usampler3D KEYWORD(130, 130, USAMPLER3D);
+usamplerCube KEYWORD(130, 130, USAMPLERCUBE);
+usampler1DArray KEYWORD(130, 130, USAMPLER1DARRAY);
+usampler2DArray KEYWORD(130, 130, USAMPLER2DARRAY);
+
+
+struct return STRUCT;
+void return VOID_TOK;
+
+layout {
+ if ((yyextra->language_version >= 140)
+ || yyextra->AMD_conservative_depth_enable
+ || yyextra->ARB_explicit_attrib_location_enable
+ || yyextra->ARB_fragment_coord_conventions_enable) {
+ return LAYOUT_TOK;
+ } else {
+ yylval->identifier = strdup(yytext);
+ return IDENTIFIER;
+ }
+ }
+
+\+\+ return INC_OP;
+-- return DEC_OP;
+\<= return LE_OP;
+>= return GE_OP;
+== return EQ_OP;
+!= return NE_OP;
+&& return AND_OP;
+\|\| return OR_OP;
+"^^" return XOR_OP;
+"<<" return LEFT_OP;
+">>" return RIGHT_OP;
+
+\*= return MUL_ASSIGN;
+\/= return DIV_ASSIGN;
+\+= return ADD_ASSIGN;
+\%= return MOD_ASSIGN;
+\<\<= return LEFT_ASSIGN;
+>>= return RIGHT_ASSIGN;
+&= return AND_ASSIGN;
+"^=" return XOR_ASSIGN;
+\|= return OR_ASSIGN;
+-= return SUB_ASSIGN;
+
+[1-9][0-9]*[uU]? {
+ yylval->n = strtol(yytext, NULL, 10);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+0[xX][0-9a-fA-F]+[uU]? {
+ yylval->n = strtol(yytext + 2, NULL, 16);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+0[0-7]*[uU]? {
+ yylval->n = strtol(yytext, NULL, 8);
+ return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+ }
+
+[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+\.([eE][+-]?[0-9]+)?[fF]? {
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+[eE][+-]?[0-9]+[fF]? {
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+[0-9]+[fF] {
+ yylval->real = glsl_strtod(yytext, NULL);
+ return FLOATCONSTANT;
+ }
+
+true {
+ yylval->n = 1;
+ return BOOLCONSTANT;
+ }
+false {
+ yylval->n = 0;
+ return BOOLCONSTANT;
+ }
+
+
+ /* Reserved words in GLSL 1.10. */
+asm KEYWORD(110 || ES, 999, ASM);
+class KEYWORD(110 || ES, 999, CLASS);
+union KEYWORD(110 || ES, 999, UNION);
+enum KEYWORD(110 || ES, 999, ENUM);
+typedef KEYWORD(110 || ES, 999, TYPEDEF);
+template KEYWORD(110 || ES, 999, TEMPLATE);
+this KEYWORD(110 || ES, 999, THIS);
+packed KEYWORD(110 || ES, 999, PACKED_TOK);
+goto KEYWORD(110 || ES, 999, GOTO);
+switch KEYWORD(110 || ES, 130, SWITCH);
+default KEYWORD(110 || ES, 130, DEFAULT);
+inline KEYWORD(110 || ES, 999, INLINE_TOK);
+noinline KEYWORD(110 || ES, 999, NOINLINE);
+volatile KEYWORD(110 || ES, 999, VOLATILE);
+public KEYWORD(110 || ES, 999, PUBLIC_TOK);
+static KEYWORD(110 || ES, 999, STATIC);
+extern KEYWORD(110 || ES, 999, EXTERN);
+external KEYWORD(110 || ES, 999, EXTERNAL);
+interface KEYWORD(110 || ES, 999, INTERFACE);
+long KEYWORD(110 || ES, 999, LONG_TOK);
+short KEYWORD(110 || ES, 999, SHORT_TOK);
+double KEYWORD(110 || ES, 400, DOUBLE_TOK);
+half KEYWORD(110 || ES, 999, HALF);
+fixed KEYWORD(110 || ES, 999, FIXED_TOK);
+unsigned KEYWORD(110 || ES, 999, UNSIGNED);
+input KEYWORD(110 || ES, 999, INPUT_TOK);
+output KEYWORD(110 || ES, 999, OUTPUT);
+hvec2 KEYWORD(110 || ES, 999, HVEC2);
+hvec3 KEYWORD(110 || ES, 999, HVEC3);
+hvec4 KEYWORD(110 || ES, 999, HVEC4);
+dvec2 KEYWORD(110 || ES, 400, DVEC2);
+dvec3 KEYWORD(110 || ES, 400, DVEC3);
+dvec4 KEYWORD(110 || ES, 400, DVEC4);
+fvec2 KEYWORD(110 || ES, 999, FVEC2);
+fvec3 KEYWORD(110 || ES, 999, FVEC3);
+fvec4 KEYWORD(110 || ES, 999, FVEC4);
+sampler2DRect return SAMPLER2DRECT;
+sampler3DRect KEYWORD(110 || ES, 999, SAMPLER3DRECT);
+sampler2DRectShadow return SAMPLER2DRECTSHADOW;
+sizeof KEYWORD(110 || ES, 999, SIZEOF);
+cast KEYWORD(110 || ES, 999, CAST);
+namespace KEYWORD(110 || ES, 999, NAMESPACE);
+using KEYWORD(110 || ES, 999, USING);
+
+ /* Additional reserved words in GLSL 1.20. */
+lowp KEYWORD(120, 130 || ES, LOWP);
+mediump KEYWORD(120, 130 || ES, MEDIUMP);
+highp KEYWORD(120, 130 || ES, HIGHP);
+precision KEYWORD(120, 130 || ES, PRECISION);
+
+ /* Additional reserved words in GLSL 1.30. */
+case KEYWORD(130, 130, CASE);
+common KEYWORD(130, 999, COMMON);
+partition KEYWORD(130, 999, PARTITION);
+active KEYWORD(130, 999, ACTIVE);
+superp KEYWORD(130 || ES, 999, SUPERP);
+samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER);
+filter KEYWORD(130, 999, FILTER);
+image1D KEYWORD(130, 999, IMAGE1D);
+image2D KEYWORD(130, 999, IMAGE2D);
+image3D KEYWORD(130, 999, IMAGE3D);
+imageCube KEYWORD(130, 999, IMAGECUBE);
+iimage1D KEYWORD(130, 999, IIMAGE1D);
+iimage2D KEYWORD(130, 999, IIMAGE2D);
+iimage3D KEYWORD(130, 999, IIMAGE3D);
+iimageCube KEYWORD(130, 999, IIMAGECUBE);
+uimage1D KEYWORD(130, 999, UIMAGE1D);
+uimage2D KEYWORD(130, 999, UIMAGE2D);
+uimage3D KEYWORD(130, 999, UIMAGE3D);
+uimageCube KEYWORD(130, 999, UIMAGECUBE);
+image1DArray KEYWORD(130, 999, IMAGE1DARRAY);
+image2DArray KEYWORD(130, 999, IMAGE2DARRAY);
+iimage1DArray KEYWORD(130, 999, IIMAGE1DARRAY);
+iimage2DArray KEYWORD(130, 999, IIMAGE2DARRAY);
+uimage1DArray KEYWORD(130, 999, UIMAGE1DARRAY);
+uimage2DArray KEYWORD(130, 999, UIMAGE2DARRAY);
+image1DShadow KEYWORD(130, 999, IMAGE1DSHADOW);
+image2DShadow KEYWORD(130, 999, IMAGE2DSHADOW);
+image1DArrayShadow KEYWORD(130, 999, IMAGE1DARRAYSHADOW);
+image2DArrayShadow KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
+imageBuffer KEYWORD(130, 999, IMAGEBUFFER);
+iimageBuffer KEYWORD(130, 999, IIMAGEBUFFER);
+uimageBuffer KEYWORD(130, 999, UIMAGEBUFFER);
+row_major KEYWORD(130, 999, ROW_MAJOR);
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+ struct _mesa_glsl_parse_state *state = yyextra;
+ void *ctx = state;
+ yylval->identifier = talloc_strdup(ctx, yytext);
+ return IDENTIFIER;
+ }
+
+. { return yytext[0]; }
+
+%%
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+ yylex_init_extra(state, & state->scanner);
+ yy_scan_string(string, state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+ yylex_destroy(state->scanner);
+}
diff --git a/mesalib/src/glsl/glsl_parser.cpp b/mesalib/src/glsl/glsl_parser.cpp
index 8b196ae7f..360676cf8 100644
--- a/mesalib/src/glsl/glsl_parser.cpp
+++ b/mesalib/src/glsl/glsl_parser.cpp
@@ -821,20 +821,20 @@ static const yytype_uint16 yyrline[] =
770, 777, 782, 793, 806, 809, 814, 819, 828, 832,
833, 842, 851, 860, 869, 878, 891, 902, 911, 920,
929, 938, 947, 956, 970, 977, 988, 995, 996, 1015,
- 1044, 1085, 1090, 1095, 1103, 1111, 1112, 1113, 1118, 1119,
- 1124, 1129, 1135, 1143, 1148, 1153, 1158, 1164, 1169, 1174,
- 1179, 1184, 1192, 1196, 1204, 1205, 1211, 1220, 1226, 1232,
- 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250,
- 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260,
- 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270,
- 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280,
- 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290,
- 1291, 1295, 1305, 1315, 1328, 1334, 1343, 1348, 1356, 1371,
- 1376, 1384, 1390, 1399, 1403, 1409, 1410, 1414, 1415, 1416,
- 1417, 1418, 1419, 1420, 1424, 1430, 1439, 1440, 1444, 1450,
- 1459, 1469, 1481, 1487, 1496, 1505, 1510, 1518, 1522, 1536,
- 1540, 1541, 1545, 1552, 1559, 1569, 1570, 1574, 1576, 1582,
- 1587, 1596, 1602, 1608, 1614, 1620, 1629, 1630, 1631, 1635
+ 1067, 1108, 1113, 1118, 1126, 1134, 1135, 1136, 1141, 1142,
+ 1147, 1152, 1158, 1166, 1171, 1176, 1181, 1187, 1192, 1197,
+ 1202, 1207, 1215, 1219, 1227, 1228, 1234, 1243, 1249, 1255,
+ 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273,
+ 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283,
+ 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293,
+ 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303,
+ 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313,
+ 1314, 1318, 1328, 1338, 1351, 1357, 1366, 1371, 1379, 1394,
+ 1399, 1407, 1413, 1422, 1426, 1432, 1433, 1437, 1438, 1439,
+ 1440, 1441, 1442, 1443, 1447, 1453, 1462, 1463, 1467, 1473,
+ 1482, 1492, 1504, 1510, 1519, 1528, 1533, 1541, 1545, 1559,
+ 1563, 1564, 1568, 1575, 1582, 1592, 1593, 1597, 1599, 1605,
+ 1610, 1619, 1625, 1631, 1637, 1643, 1652, 1653, 1654, 1658
};
#endif
@@ -3946,7 +3946,8 @@ yyreduce:
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
- if (state->ARB_fragment_coord_conventions_enable) {
+ /* Layout qualifiers for ARB_fragment_coord_conventions. */
+ if (!got_one && state->ARB_fragment_coord_conventions_enable) {
if (strcmp((yyvsp[(1) - (1)].identifier), "origin_upper_left") == 0) {
got_one = true;
(yyval.type_qualifier).flags.q.origin_upper_left = 1;
@@ -3954,19 +3955,41 @@ yyreduce:
got_one = true;
(yyval.type_qualifier).flags.q.pixel_center_integer = 1;
}
+
+ if (got_one && state->ARB_fragment_coord_conventions_warn) {
+ _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+ "GL_ARB_fragment_coord_conventions layout "
+ "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
+ }
+ }
+
+ /* Layout qualifiers for AMD_conservative_depth. */
+ if (!got_one && state->AMD_conservative_depth_enable) {
+ if (strcmp((yyvsp[(1) - (1)].identifier), "depth_any") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).flags.q.depth_any = 1;
+ } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_greater") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).flags.q.depth_greater = 1;
+ } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_less") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).flags.q.depth_less = 1;
+ } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_unchanged") == 0) {
+ got_one = true;
+ (yyval.type_qualifier).flags.q.depth_unchanged = 1;
+ }
+
+ if (got_one && state->AMD_conservative_depth_warn) {
+ _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+ "GL_AMD_conservative_depth "
+ "layout qualifier `%s' is used\n", (yyvsp[(1) - (1)].identifier));
+ }
}
- /* If the identifier didn't match any known layout identifiers,
- * emit an error.
- */
if (!got_one) {
_mesa_glsl_error(& (yylsp[(1) - (1)]), state, "unrecognized layout identifier "
"`%s'\n", (yyvsp[(1) - (1)].identifier));
YYERROR;
- } else if (state->ARB_fragment_coord_conventions_warn) {
- _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
- "GL_ARB_fragment_coord_conventions layout "
- "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
}
;}
break;
@@ -3974,7 +3997,7 @@ yyreduce:
case 140:
/* Line 1464 of yacc.c */
-#line 1045 "glsl_parser.ypp"
+#line 1068 "glsl_parser.ypp"
{
bool got_one = false;
@@ -4017,7 +4040,7 @@ yyreduce:
case 141:
/* Line 1464 of yacc.c */
-#line 1086 "glsl_parser.ypp"
+#line 1109 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.smooth = 1;
@@ -4027,7 +4050,7 @@ yyreduce:
case 142:
/* Line 1464 of yacc.c */
-#line 1091 "glsl_parser.ypp"
+#line 1114 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.flat = 1;
@@ -4037,7 +4060,7 @@ yyreduce:
case 143:
/* Line 1464 of yacc.c */
-#line 1096 "glsl_parser.ypp"
+#line 1119 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.noperspective = 1;
@@ -4047,7 +4070,7 @@ yyreduce:
case 144:
/* Line 1464 of yacc.c */
-#line 1104 "glsl_parser.ypp"
+#line 1127 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.constant = 1;
@@ -4057,7 +4080,7 @@ yyreduce:
case 147:
/* Line 1464 of yacc.c */
-#line 1114 "glsl_parser.ypp"
+#line 1137 "glsl_parser.ypp"
{
(yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier);
(yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i;
@@ -4067,7 +4090,7 @@ yyreduce:
case 149:
/* Line 1464 of yacc.c */
-#line 1120 "glsl_parser.ypp"
+#line 1143 "glsl_parser.ypp"
{
(yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier);
(yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i;
@@ -4077,7 +4100,7 @@ yyreduce:
case 150:
/* Line 1464 of yacc.c */
-#line 1125 "glsl_parser.ypp"
+#line 1148 "glsl_parser.ypp"
{
(yyval.type_qualifier) = (yyvsp[(2) - (2)].type_qualifier);
(yyval.type_qualifier).flags.q.invariant = 1;
@@ -4087,7 +4110,7 @@ yyreduce:
case 151:
/* Line 1464 of yacc.c */
-#line 1130 "glsl_parser.ypp"
+#line 1153 "glsl_parser.ypp"
{
(yyval.type_qualifier) = (yyvsp[(2) - (3)].type_qualifier);
(yyval.type_qualifier).flags.i |= (yyvsp[(3) - (3)].type_qualifier).flags.i;
@@ -4098,7 +4121,7 @@ yyreduce:
case 152:
/* Line 1464 of yacc.c */
-#line 1136 "glsl_parser.ypp"
+#line 1159 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.invariant = 1;
@@ -4108,7 +4131,7 @@ yyreduce:
case 153:
/* Line 1464 of yacc.c */
-#line 1144 "glsl_parser.ypp"
+#line 1167 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.constant = 1;
@@ -4118,7 +4141,7 @@ yyreduce:
case 154:
/* Line 1464 of yacc.c */
-#line 1149 "glsl_parser.ypp"
+#line 1172 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.attribute = 1;
@@ -4128,7 +4151,7 @@ yyreduce:
case 155:
/* Line 1464 of yacc.c */
-#line 1154 "glsl_parser.ypp"
+#line 1177 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.varying = 1;
@@ -4138,7 +4161,7 @@ yyreduce:
case 156:
/* Line 1464 of yacc.c */
-#line 1159 "glsl_parser.ypp"
+#line 1182 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.centroid = 1;
@@ -4149,7 +4172,7 @@ yyreduce:
case 157:
/* Line 1464 of yacc.c */
-#line 1165 "glsl_parser.ypp"
+#line 1188 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.in = 1;
@@ -4159,7 +4182,7 @@ yyreduce:
case 158:
/* Line 1464 of yacc.c */
-#line 1170 "glsl_parser.ypp"
+#line 1193 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.out = 1;
@@ -4169,7 +4192,7 @@ yyreduce:
case 159:
/* Line 1464 of yacc.c */
-#line 1175 "glsl_parser.ypp"
+#line 1198 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.in = 1;
@@ -4179,7 +4202,7 @@ yyreduce:
case 160:
/* Line 1464 of yacc.c */
-#line 1180 "glsl_parser.ypp"
+#line 1203 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.out = 1;
@@ -4189,7 +4212,7 @@ yyreduce:
case 161:
/* Line 1464 of yacc.c */
-#line 1185 "glsl_parser.ypp"
+#line 1208 "glsl_parser.ypp"
{
memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
(yyval.type_qualifier).flags.q.uniform = 1;
@@ -4199,7 +4222,7 @@ yyreduce:
case 162:
/* Line 1464 of yacc.c */
-#line 1193 "glsl_parser.ypp"
+#line 1216 "glsl_parser.ypp"
{
(yyval.type_specifier) = (yyvsp[(1) - (1)].type_specifier);
;}
@@ -4208,7 +4231,7 @@ yyreduce:
case 163:
/* Line 1464 of yacc.c */
-#line 1197 "glsl_parser.ypp"
+#line 1220 "glsl_parser.ypp"
{
(yyval.type_specifier) = (yyvsp[(2) - (2)].type_specifier);
(yyval.type_specifier)->precision = (yyvsp[(1) - (2)].n);
@@ -4218,7 +4241,7 @@ yyreduce:
case 165:
/* Line 1464 of yacc.c */
-#line 1206 "glsl_parser.ypp"
+#line 1229 "glsl_parser.ypp"
{
(yyval.type_specifier) = (yyvsp[(1) - (3)].type_specifier);
(yyval.type_specifier)->is_array = true;
@@ -4229,7 +4252,7 @@ yyreduce:
case 166:
/* Line 1464 of yacc.c */
-#line 1212 "glsl_parser.ypp"
+#line 1235 "glsl_parser.ypp"
{
(yyval.type_specifier) = (yyvsp[(1) - (4)].type_specifier);
(yyval.type_specifier)->is_array = true;
@@ -4240,7 +4263,7 @@ yyreduce:
case 167:
/* Line 1464 of yacc.c */
-#line 1221 "glsl_parser.ypp"
+#line 1244 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].n));
@@ -4251,7 +4274,7 @@ yyreduce:
case 168:
/* Line 1464 of yacc.c */
-#line 1227 "glsl_parser.ypp"
+#line 1250 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].struct_specifier));
@@ -4262,7 +4285,7 @@ yyreduce:
case 169:
/* Line 1464 of yacc.c */
-#line 1233 "glsl_parser.ypp"
+#line 1256 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].identifier));
@@ -4273,364 +4296,364 @@ yyreduce:
case 170:
/* Line 1464 of yacc.c */
-#line 1241 "glsl_parser.ypp"
+#line 1264 "glsl_parser.ypp"
{ (yyval.n) = ast_void; ;}
break;
case 171:
/* Line 1464 of yacc.c */
-#line 1242 "glsl_parser.ypp"
+#line 1265 "glsl_parser.ypp"
{ (yyval.n) = ast_float; ;}
break;
case 172:
/* Line 1464 of yacc.c */
-#line 1243 "glsl_parser.ypp"
+#line 1266 "glsl_parser.ypp"
{ (yyval.n) = ast_int; ;}
break;
case 173:
/* Line 1464 of yacc.c */
-#line 1244 "glsl_parser.ypp"
+#line 1267 "glsl_parser.ypp"
{ (yyval.n) = ast_uint; ;}
break;
case 174:
/* Line 1464 of yacc.c */
-#line 1245 "glsl_parser.ypp"
+#line 1268 "glsl_parser.ypp"
{ (yyval.n) = ast_bool; ;}
break;
case 175:
/* Line 1464 of yacc.c */
-#line 1246 "glsl_parser.ypp"
+#line 1269 "glsl_parser.ypp"
{ (yyval.n) = ast_vec2; ;}
break;
case 176:
/* Line 1464 of yacc.c */
-#line 1247 "glsl_parser.ypp"
+#line 1270 "glsl_parser.ypp"
{ (yyval.n) = ast_vec3; ;}
break;
case 177:
/* Line 1464 of yacc.c */
-#line 1248 "glsl_parser.ypp"
+#line 1271 "glsl_parser.ypp"
{ (yyval.n) = ast_vec4; ;}
break;
case 178:
/* Line 1464 of yacc.c */
-#line 1249 "glsl_parser.ypp"
+#line 1272 "glsl_parser.ypp"
{ (yyval.n) = ast_bvec2; ;}
break;
case 179:
/* Line 1464 of yacc.c */
-#line 1250 "glsl_parser.ypp"
+#line 1273 "glsl_parser.ypp"
{ (yyval.n) = ast_bvec3; ;}
break;
case 180:
/* Line 1464 of yacc.c */
-#line 1251 "glsl_parser.ypp"
+#line 1274 "glsl_parser.ypp"
{ (yyval.n) = ast_bvec4; ;}
break;
case 181:
/* Line 1464 of yacc.c */
-#line 1252 "glsl_parser.ypp"
+#line 1275 "glsl_parser.ypp"
{ (yyval.n) = ast_ivec2; ;}
break;
case 182:
/* Line 1464 of yacc.c */
-#line 1253 "glsl_parser.ypp"
+#line 1276 "glsl_parser.ypp"
{ (yyval.n) = ast_ivec3; ;}
break;
case 183:
/* Line 1464 of yacc.c */
-#line 1254 "glsl_parser.ypp"
+#line 1277 "glsl_parser.ypp"
{ (yyval.n) = ast_ivec4; ;}
break;
case 184:
/* Line 1464 of yacc.c */
-#line 1255 "glsl_parser.ypp"
+#line 1278 "glsl_parser.ypp"
{ (yyval.n) = ast_uvec2; ;}
break;
case 185:
/* Line 1464 of yacc.c */
-#line 1256 "glsl_parser.ypp"
+#line 1279 "glsl_parser.ypp"
{ (yyval.n) = ast_uvec3; ;}
break;
case 186:
/* Line 1464 of yacc.c */
-#line 1257 "glsl_parser.ypp"
+#line 1280 "glsl_parser.ypp"
{ (yyval.n) = ast_uvec4; ;}
break;
case 187:
/* Line 1464 of yacc.c */
-#line 1258 "glsl_parser.ypp"
+#line 1281 "glsl_parser.ypp"
{ (yyval.n) = ast_mat2; ;}
break;
case 188:
/* Line 1464 of yacc.c */
-#line 1259 "glsl_parser.ypp"
+#line 1282 "glsl_parser.ypp"
{ (yyval.n) = ast_mat2x3; ;}
break;
case 189:
/* Line 1464 of yacc.c */
-#line 1260 "glsl_parser.ypp"
+#line 1283 "glsl_parser.ypp"
{ (yyval.n) = ast_mat2x4; ;}
break;
case 190:
/* Line 1464 of yacc.c */
-#line 1261 "glsl_parser.ypp"
+#line 1284 "glsl_parser.ypp"
{ (yyval.n) = ast_mat3x2; ;}
break;
case 191:
/* Line 1464 of yacc.c */
-#line 1262 "glsl_parser.ypp"
+#line 1285 "glsl_parser.ypp"
{ (yyval.n) = ast_mat3; ;}
break;
case 192:
/* Line 1464 of yacc.c */
-#line 1263 "glsl_parser.ypp"
+#line 1286 "glsl_parser.ypp"
{ (yyval.n) = ast_mat3x4; ;}
break;
case 193:
/* Line 1464 of yacc.c */
-#line 1264 "glsl_parser.ypp"
+#line 1287 "glsl_parser.ypp"
{ (yyval.n) = ast_mat4x2; ;}
break;
case 194:
/* Line 1464 of yacc.c */
-#line 1265 "glsl_parser.ypp"
+#line 1288 "glsl_parser.ypp"
{ (yyval.n) = ast_mat4x3; ;}
break;
case 195:
/* Line 1464 of yacc.c */
-#line 1266 "glsl_parser.ypp"
+#line 1289 "glsl_parser.ypp"
{ (yyval.n) = ast_mat4; ;}
break;
case 196:
/* Line 1464 of yacc.c */
-#line 1267 "glsl_parser.ypp"
+#line 1290 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler1d; ;}
break;
case 197:
/* Line 1464 of yacc.c */
-#line 1268 "glsl_parser.ypp"
+#line 1291 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2d; ;}
break;
case 198:
/* Line 1464 of yacc.c */
-#line 1269 "glsl_parser.ypp"
+#line 1292 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2drect; ;}
break;
case 199:
/* Line 1464 of yacc.c */
-#line 1270 "glsl_parser.ypp"
+#line 1293 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler3d; ;}
break;
case 200:
/* Line 1464 of yacc.c */
-#line 1271 "glsl_parser.ypp"
+#line 1294 "glsl_parser.ypp"
{ (yyval.n) = ast_samplercube; ;}
break;
case 201:
/* Line 1464 of yacc.c */
-#line 1272 "glsl_parser.ypp"
+#line 1295 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler1dshadow; ;}
break;
case 202:
/* Line 1464 of yacc.c */
-#line 1273 "glsl_parser.ypp"
+#line 1296 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2dshadow; ;}
break;
case 203:
/* Line 1464 of yacc.c */
-#line 1274 "glsl_parser.ypp"
+#line 1297 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2drectshadow; ;}
break;
case 204:
/* Line 1464 of yacc.c */
-#line 1275 "glsl_parser.ypp"
+#line 1298 "glsl_parser.ypp"
{ (yyval.n) = ast_samplercubeshadow; ;}
break;
case 205:
/* Line 1464 of yacc.c */
-#line 1276 "glsl_parser.ypp"
+#line 1299 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler1darray; ;}
break;
case 206:
/* Line 1464 of yacc.c */
-#line 1277 "glsl_parser.ypp"
+#line 1300 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2darray; ;}
break;
case 207:
/* Line 1464 of yacc.c */
-#line 1278 "glsl_parser.ypp"
+#line 1301 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler1darrayshadow; ;}
break;
case 208:
/* Line 1464 of yacc.c */
-#line 1279 "glsl_parser.ypp"
+#line 1302 "glsl_parser.ypp"
{ (yyval.n) = ast_sampler2darrayshadow; ;}
break;
case 209:
/* Line 1464 of yacc.c */
-#line 1280 "glsl_parser.ypp"
+#line 1303 "glsl_parser.ypp"
{ (yyval.n) = ast_isampler1d; ;}
break;
case 210:
/* Line 1464 of yacc.c */
-#line 1281 "glsl_parser.ypp"
+#line 1304 "glsl_parser.ypp"
{ (yyval.n) = ast_isampler2d; ;}
break;
case 211:
/* Line 1464 of yacc.c */
-#line 1282 "glsl_parser.ypp"
+#line 1305 "glsl_parser.ypp"
{ (yyval.n) = ast_isampler3d; ;}
break;
case 212:
/* Line 1464 of yacc.c */
-#line 1283 "glsl_parser.ypp"
+#line 1306 "glsl_parser.ypp"
{ (yyval.n) = ast_isamplercube; ;}
break;
case 213:
/* Line 1464 of yacc.c */
-#line 1284 "glsl_parser.ypp"
+#line 1307 "glsl_parser.ypp"
{ (yyval.n) = ast_isampler1darray; ;}
break;
case 214:
/* Line 1464 of yacc.c */
-#line 1285 "glsl_parser.ypp"
+#line 1308 "glsl_parser.ypp"
{ (yyval.n) = ast_isampler2darray; ;}
break;
case 215:
/* Line 1464 of yacc.c */
-#line 1286 "glsl_parser.ypp"
+#line 1309 "glsl_parser.ypp"
{ (yyval.n) = ast_usampler1d; ;}
break;
case 216:
/* Line 1464 of yacc.c */
-#line 1287 "glsl_parser.ypp"
+#line 1310 "glsl_parser.ypp"
{ (yyval.n) = ast_usampler2d; ;}
break;
case 217:
/* Line 1464 of yacc.c */
-#line 1288 "glsl_parser.ypp"
+#line 1311 "glsl_parser.ypp"
{ (yyval.n) = ast_usampler3d; ;}
break;
case 218:
/* Line 1464 of yacc.c */
-#line 1289 "glsl_parser.ypp"
+#line 1312 "glsl_parser.ypp"
{ (yyval.n) = ast_usamplercube; ;}
break;
case 219:
/* Line 1464 of yacc.c */
-#line 1290 "glsl_parser.ypp"
+#line 1313 "glsl_parser.ypp"
{ (yyval.n) = ast_usampler1darray; ;}
break;
case 220:
/* Line 1464 of yacc.c */
-#line 1291 "glsl_parser.ypp"
+#line 1314 "glsl_parser.ypp"
{ (yyval.n) = ast_usampler2darray; ;}
break;
case 221:
/* Line 1464 of yacc.c */
-#line 1295 "glsl_parser.ypp"
+#line 1318 "glsl_parser.ypp"
{
if (!state->es_shader && state->language_version < 130)
_mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4646,7 +4669,7 @@ yyreduce:
case 222:
/* Line 1464 of yacc.c */
-#line 1305 "glsl_parser.ypp"
+#line 1328 "glsl_parser.ypp"
{
if (!state->es_shader && state->language_version < 130)
_mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4662,7 +4685,7 @@ yyreduce:
case 223:
/* Line 1464 of yacc.c */
-#line 1315 "glsl_parser.ypp"
+#line 1338 "glsl_parser.ypp"
{
if (!state->es_shader && state->language_version < 130)
_mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4678,7 +4701,7 @@ yyreduce:
case 224:
/* Line 1464 of yacc.c */
-#line 1329 "glsl_parser.ypp"
+#line 1352 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.struct_specifier) = new(ctx) ast_struct_specifier((yyvsp[(2) - (5)].identifier), (yyvsp[(4) - (5)].node));
@@ -4689,7 +4712,7 @@ yyreduce:
case 225:
/* Line 1464 of yacc.c */
-#line 1335 "glsl_parser.ypp"
+#line 1358 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.struct_specifier) = new(ctx) ast_struct_specifier(NULL, (yyvsp[(3) - (4)].node));
@@ -4700,7 +4723,7 @@ yyreduce:
case 226:
/* Line 1464 of yacc.c */
-#line 1344 "glsl_parser.ypp"
+#line 1367 "glsl_parser.ypp"
{
(yyval.node) = (ast_node *) (yyvsp[(1) - (1)].declarator_list);
(yyvsp[(1) - (1)].declarator_list)->link.self_link();
@@ -4710,7 +4733,7 @@ yyreduce:
case 227:
/* Line 1464 of yacc.c */
-#line 1349 "glsl_parser.ypp"
+#line 1372 "glsl_parser.ypp"
{
(yyval.node) = (ast_node *) (yyvsp[(1) - (2)].node);
(yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].declarator_list)->link);
@@ -4720,7 +4743,7 @@ yyreduce:
case 228:
/* Line 1464 of yacc.c */
-#line 1357 "glsl_parser.ypp"
+#line 1380 "glsl_parser.ypp"
{
void *ctx = state;
ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
@@ -4737,7 +4760,7 @@ yyreduce:
case 229:
/* Line 1464 of yacc.c */
-#line 1372 "glsl_parser.ypp"
+#line 1395 "glsl_parser.ypp"
{
(yyval.declaration) = (yyvsp[(1) - (1)].declaration);
(yyvsp[(1) - (1)].declaration)->link.self_link();
@@ -4747,7 +4770,7 @@ yyreduce:
case 230:
/* Line 1464 of yacc.c */
-#line 1377 "glsl_parser.ypp"
+#line 1400 "glsl_parser.ypp"
{
(yyval.declaration) = (yyvsp[(1) - (3)].declaration);
(yyval.declaration)->link.insert_before(& (yyvsp[(3) - (3)].declaration)->link);
@@ -4757,7 +4780,7 @@ yyreduce:
case 231:
/* Line 1464 of yacc.c */
-#line 1385 "glsl_parser.ypp"
+#line 1408 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (1)].identifier), false, NULL, NULL);
@@ -4768,7 +4791,7 @@ yyreduce:
case 232:
/* Line 1464 of yacc.c */
-#line 1391 "glsl_parser.ypp"
+#line 1414 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (4)].identifier), true, (yyvsp[(3) - (4)].expression), NULL);
@@ -4779,28 +4802,28 @@ yyreduce:
case 235:
/* Line 1464 of yacc.c */
-#line 1409 "glsl_parser.ypp"
+#line 1432 "glsl_parser.ypp"
{ (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
break;
case 240:
/* Line 1464 of yacc.c */
-#line 1417 "glsl_parser.ypp"
+#line 1440 "glsl_parser.ypp"
{ (yyval.node) = NULL; ;}
break;
case 241:
/* Line 1464 of yacc.c */
-#line 1418 "glsl_parser.ypp"
+#line 1441 "glsl_parser.ypp"
{ (yyval.node) = NULL; ;}
break;
case 244:
/* Line 1464 of yacc.c */
-#line 1425 "glsl_parser.ypp"
+#line 1448 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.compound_statement) = new(ctx) ast_compound_statement(true, NULL);
@@ -4811,7 +4834,7 @@ yyreduce:
case 245:
/* Line 1464 of yacc.c */
-#line 1431 "glsl_parser.ypp"
+#line 1454 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(2) - (3)].node));
@@ -4822,14 +4845,14 @@ yyreduce:
case 246:
/* Line 1464 of yacc.c */
-#line 1439 "glsl_parser.ypp"
+#line 1462 "glsl_parser.ypp"
{ (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
break;
case 248:
/* Line 1464 of yacc.c */
-#line 1445 "glsl_parser.ypp"
+#line 1468 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.compound_statement) = new(ctx) ast_compound_statement(false, NULL);
@@ -4840,7 +4863,7 @@ yyreduce:
case 249:
/* Line 1464 of yacc.c */
-#line 1451 "glsl_parser.ypp"
+#line 1474 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.compound_statement) = new(ctx) ast_compound_statement(false, (yyvsp[(2) - (3)].node));
@@ -4851,7 +4874,7 @@ yyreduce:
case 250:
/* Line 1464 of yacc.c */
-#line 1460 "glsl_parser.ypp"
+#line 1483 "glsl_parser.ypp"
{
if ((yyvsp[(1) - (1)].node) == NULL) {
_mesa_glsl_error(& (yylsp[(1) - (1)]), state, "<nil> statement\n");
@@ -4866,7 +4889,7 @@ yyreduce:
case 251:
/* Line 1464 of yacc.c */
-#line 1470 "glsl_parser.ypp"
+#line 1493 "glsl_parser.ypp"
{
if ((yyvsp[(2) - (2)].node) == NULL) {
_mesa_glsl_error(& (yylsp[(2) - (2)]), state, "<nil> statement\n");
@@ -4880,7 +4903,7 @@ yyreduce:
case 252:
/* Line 1464 of yacc.c */
-#line 1482 "glsl_parser.ypp"
+#line 1505 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_expression_statement(NULL);
@@ -4891,7 +4914,7 @@ yyreduce:
case 253:
/* Line 1464 of yacc.c */
-#line 1488 "glsl_parser.ypp"
+#line 1511 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_expression_statement((yyvsp[(1) - (2)].expression));
@@ -4902,7 +4925,7 @@ yyreduce:
case 254:
/* Line 1464 of yacc.c */
-#line 1497 "glsl_parser.ypp"
+#line 1520 "glsl_parser.ypp"
{
(yyval.node) = new(state) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].selection_rest_statement).then_statement,
(yyvsp[(5) - (5)].selection_rest_statement).else_statement);
@@ -4913,7 +4936,7 @@ yyreduce:
case 255:
/* Line 1464 of yacc.c */
-#line 1506 "glsl_parser.ypp"
+#line 1529 "glsl_parser.ypp"
{
(yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (3)].node);
(yyval.selection_rest_statement).else_statement = (yyvsp[(3) - (3)].node);
@@ -4923,7 +4946,7 @@ yyreduce:
case 256:
/* Line 1464 of yacc.c */
-#line 1511 "glsl_parser.ypp"
+#line 1534 "glsl_parser.ypp"
{
(yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (1)].node);
(yyval.selection_rest_statement).else_statement = NULL;
@@ -4933,7 +4956,7 @@ yyreduce:
case 257:
/* Line 1464 of yacc.c */
-#line 1519 "glsl_parser.ypp"
+#line 1542 "glsl_parser.ypp"
{
(yyval.node) = (ast_node *) (yyvsp[(1) - (1)].expression);
;}
@@ -4942,7 +4965,7 @@ yyreduce:
case 258:
/* Line 1464 of yacc.c */
-#line 1523 "glsl_parser.ypp"
+#line 1546 "glsl_parser.ypp"
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
@@ -4958,7 +4981,7 @@ yyreduce:
case 262:
/* Line 1464 of yacc.c */
-#line 1546 "glsl_parser.ypp"
+#line 1569 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
@@ -4970,7 +4993,7 @@ yyreduce:
case 263:
/* Line 1464 of yacc.c */
-#line 1553 "glsl_parser.ypp"
+#line 1576 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
@@ -4982,7 +5005,7 @@ yyreduce:
case 264:
/* Line 1464 of yacc.c */
-#line 1560 "glsl_parser.ypp"
+#line 1583 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
@@ -4994,7 +5017,7 @@ yyreduce:
case 268:
/* Line 1464 of yacc.c */
-#line 1576 "glsl_parser.ypp"
+#line 1599 "glsl_parser.ypp"
{
(yyval.node) = NULL;
;}
@@ -5003,7 +5026,7 @@ yyreduce:
case 269:
/* Line 1464 of yacc.c */
-#line 1583 "glsl_parser.ypp"
+#line 1606 "glsl_parser.ypp"
{
(yyval.for_rest_statement).cond = (yyvsp[(1) - (2)].node);
(yyval.for_rest_statement).rest = NULL;
@@ -5013,7 +5036,7 @@ yyreduce:
case 270:
/* Line 1464 of yacc.c */
-#line 1588 "glsl_parser.ypp"
+#line 1611 "glsl_parser.ypp"
{
(yyval.for_rest_statement).cond = (yyvsp[(1) - (3)].node);
(yyval.for_rest_statement).rest = (yyvsp[(3) - (3)].expression);
@@ -5023,7 +5046,7 @@ yyreduce:
case 271:
/* Line 1464 of yacc.c */
-#line 1597 "glsl_parser.ypp"
+#line 1620 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
@@ -5034,7 +5057,7 @@ yyreduce:
case 272:
/* Line 1464 of yacc.c */
-#line 1603 "glsl_parser.ypp"
+#line 1626 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
@@ -5045,7 +5068,7 @@ yyreduce:
case 273:
/* Line 1464 of yacc.c */
-#line 1609 "glsl_parser.ypp"
+#line 1632 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
@@ -5056,7 +5079,7 @@ yyreduce:
case 274:
/* Line 1464 of yacc.c */
-#line 1615 "glsl_parser.ypp"
+#line 1638 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, (yyvsp[(2) - (3)].expression));
@@ -5067,7 +5090,7 @@ yyreduce:
case 275:
/* Line 1464 of yacc.c */
-#line 1621 "glsl_parser.ypp"
+#line 1644 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
@@ -5078,28 +5101,28 @@ yyreduce:
case 276:
/* Line 1464 of yacc.c */
-#line 1629 "glsl_parser.ypp"
+#line 1652 "glsl_parser.ypp"
{ (yyval.node) = (yyvsp[(1) - (1)].function_definition); ;}
break;
case 277:
/* Line 1464 of yacc.c */
-#line 1630 "glsl_parser.ypp"
+#line 1653 "glsl_parser.ypp"
{ (yyval.node) = (yyvsp[(1) - (1)].node); ;}
break;
case 278:
/* Line 1464 of yacc.c */
-#line 1631 "glsl_parser.ypp"
+#line 1654 "glsl_parser.ypp"
{ (yyval.node) = NULL; ;}
break;
case 279:
/* Line 1464 of yacc.c */
-#line 1636 "glsl_parser.ypp"
+#line 1659 "glsl_parser.ypp"
{
void *ctx = state;
(yyval.function_definition) = new(ctx) ast_function_definition();
@@ -5112,7 +5135,7 @@ yyreduce:
/* Line 1464 of yacc.c */
-#line 5116 "glsl_parser.cpp"
+#line 5139 "glsl_parser.cpp"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/mesalib/src/glsl/glsl_parser.ypp b/mesalib/src/glsl/glsl_parser.ypp
index 3982167c4..3955648eb 100644
--- a/mesalib/src/glsl/glsl_parser.ypp
+++ b/mesalib/src/glsl/glsl_parser.ypp
@@ -1018,7 +1018,8 @@ layout_qualifier_id:
memset(& $$, 0, sizeof($$));
- if (state->ARB_fragment_coord_conventions_enable) {
+ /* Layout qualifiers for ARB_fragment_coord_conventions. */
+ if (!got_one && state->ARB_fragment_coord_conventions_enable) {
if (strcmp($1, "origin_upper_left") == 0) {
got_one = true;
$$.flags.q.origin_upper_left = 1;
@@ -1026,19 +1027,41 @@ layout_qualifier_id:
got_one = true;
$$.flags.q.pixel_center_integer = 1;
}
+
+ if (got_one && state->ARB_fragment_coord_conventions_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "GL_ARB_fragment_coord_conventions layout "
+ "identifier `%s' used\n", $1);
+ }
+ }
+
+ /* Layout qualifiers for AMD_conservative_depth. */
+ if (!got_one && state->AMD_conservative_depth_enable) {
+ if (strcmp($1, "depth_any") == 0) {
+ got_one = true;
+ $$.flags.q.depth_any = 1;
+ } else if (strcmp($1, "depth_greater") == 0) {
+ got_one = true;
+ $$.flags.q.depth_greater = 1;
+ } else if (strcmp($1, "depth_less") == 0) {
+ got_one = true;
+ $$.flags.q.depth_less = 1;
+ } else if (strcmp($1, "depth_unchanged") == 0) {
+ got_one = true;
+ $$.flags.q.depth_unchanged = 1;
+ }
+
+ if (got_one && state->AMD_conservative_depth_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "GL_AMD_conservative_depth "
+ "layout qualifier `%s' is used\n", $1);
+ }
}
- /* If the identifier didn't match any known layout identifiers,
- * emit an error.
- */
if (!got_one) {
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'\n", $1);
YYERROR;
- } else if (state->ARB_fragment_coord_conventions_warn) {
- _mesa_glsl_warning(& @1, state,
- "GL_ARB_fragment_coord_conventions layout "
- "identifier `%s' used\n", $1);
}
}
| IDENTIFIER '=' INTCONSTANT
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 77885d4e1..c9a8a2cb2 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -219,6 +219,13 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn);
unsupported = !state->extensions->ARB_shader_stencil_export;
}
+ } else if (strcmp(name, "GL_AMD_conservative_depth") == 0) {
+ /* The AMD_conservative spec does not forbid requiring the extension in
+ * the vertex shader.
+ */
+ state->AMD_conservative_depth_enable = (ext_mode != extension_disable);
+ state->AMD_conservative_depth_warn = (ext_mode == extension_warn);
+ unsupported = !state->extensions->AMD_conservative_depth;
} else {
unsupported = true;
}
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 9c16d5de8..92029e2e8 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -1,249 +1,251 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#pragma once
-#ifndef GLSL_PARSER_EXTRAS_H
-#define GLSL_PARSER_EXTRAS_H
-
-/*
- * Most of the definitions here only apply to C++
- */
-#ifdef __cplusplus
-
-
-#include <cstdlib>
-#include "glsl_symbol_table.h"
-
-enum _mesa_glsl_parser_targets {
- vertex_shader,
- geometry_shader,
- fragment_shader
-};
-
-struct gl_context;
-
-struct _mesa_glsl_parse_state {
- _mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
- void *mem_ctx);
-
- /* Callers of this talloc-based new need not call delete. It's
- * easier to just talloc_free 'ctx' (or any of its ancestors). */
- static void* operator new(size_t size, void *ctx)
- {
- void *mem = talloc_zero_size(ctx, size);
- assert(mem != NULL);
-
- return mem;
- }
-
- /* If the user *does* call delete, that's OK, we will just
- * talloc_free in that case. */
- static void operator delete(void *mem)
- {
- talloc_free(mem);
- }
-
- void *scanner;
- exec_list translation_unit;
- glsl_symbol_table *symbols;
-
- bool es_shader;
- unsigned language_version;
- const char *version_string;
- enum _mesa_glsl_parser_targets target;
-
- /**
- * Implementation defined limits that affect built-in variables, etc.
- *
- * \sa struct gl_constants (in mtypes.h)
- */
- struct {
- /* 1.10 */
- unsigned MaxLights;
- unsigned MaxClipPlanes;
- unsigned MaxTextureUnits;
- unsigned MaxTextureCoords;
- unsigned MaxVertexAttribs;
- unsigned MaxVertexUniformComponents;
- unsigned MaxVaryingFloats;
- unsigned MaxVertexTextureImageUnits;
- unsigned MaxCombinedTextureImageUnits;
- unsigned MaxTextureImageUnits;
- unsigned MaxFragmentUniformComponents;
-
- /* ARB_draw_buffers */
- unsigned MaxDrawBuffers;
- } Const;
-
- /**
- * During AST to IR conversion, pointer to current IR function
- *
- * Will be \c NULL whenever the AST to IR conversion is not inside a
- * function definition.
- */
- class ir_function_signature *current_function;
-
- /** Have we found a return statement in this function? */
- bool found_return;
-
- /** Was there an error during compilation? */
- bool error;
-
- /**
- * Are all shader inputs / outputs invariant?
- *
- * This is set when the 'STDGL invariant(all)' pragma is used.
- */
- bool all_invariant;
-
- /** Loop or switch statement containing the current instructions. */
- class ir_instruction *loop_or_switch_nesting;
- class ast_iteration_statement *loop_or_switch_nesting_ast;
-
- /** List of structures defined in user code. */
- const glsl_type **user_structures;
- unsigned num_user_structures;
-
- char *info_log;
-
- /**
- * \name Enable bits for GLSL extensions
- */
- /*@{*/
- unsigned ARB_draw_buffers_enable:1;
- unsigned ARB_draw_buffers_warn:1;
- unsigned ARB_draw_instanced_enable:1;
- unsigned ARB_draw_instanced_warn:1;
- unsigned ARB_explicit_attrib_location_enable:1;
- unsigned ARB_explicit_attrib_location_warn:1;
- unsigned ARB_fragment_coord_conventions_enable:1;
- unsigned ARB_fragment_coord_conventions_warn:1;
- unsigned ARB_texture_rectangle_enable:1;
- unsigned ARB_texture_rectangle_warn:1;
- unsigned EXT_texture_array_enable:1;
- unsigned EXT_texture_array_warn:1;
- unsigned ARB_shader_stencil_export_enable:1;
- unsigned ARB_shader_stencil_export_warn:1;
- /*@}*/
-
- /** Extensions supported by the OpenGL implementation. */
- const struct gl_extensions *extensions;
-
- /** Shaders containing built-in functions that are used for linking. */
- struct gl_shader *builtins_to_link[16];
- unsigned num_builtins_to_link;
-};
-
-typedef struct YYLTYPE {
- int first_line;
- int first_column;
- int last_line;
- int last_column;
- unsigned source;
-} YYLTYPE;
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
-do { \
- if (N) \
- { \
- (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC(Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC(Rhs, 0).last_column; \
- } \
- (Current).source = 0; \
-} while (0)
-
-extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
- const char *fmt, ...);
-
-/**
- * Emit a warning to the shader log
- *
- * \sa _mesa_glsl_error
- */
-extern void _mesa_glsl_warning(const YYLTYPE *locp,
- _mesa_glsl_parse_state *state,
- const char *fmt, ...);
-
-extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
- const char *string);
-
-extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state);
-
-union YYSTYPE;
-extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc,
- void *scanner);
-
-extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *);
-
-/**
- * Process elements of the #extension directive
- *
- * \return
- * If \c name and \c behavior are valid, \c true is returned. Otherwise
- * \c false is returned.
- */
-extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
- const char *behavior,
- YYLTYPE *behavior_locp,
- _mesa_glsl_parse_state *state);
-
-/**
- * Get the textual name of the specified shader target
- */
-extern const char *
-_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target);
-
-
-#endif /* __cplusplus */
-
-
-/*
- * These definitions apply to C and C++
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int preprocess(void *ctx, const char **shader, char **info_log,
- const struct gl_extensions *extensions, int api);
-
-extern void _mesa_destroy_shader_compiler();
-extern void _mesa_destroy_shader_compiler_caches();
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* GLSL_PARSER_EXTRAS_H */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef GLSL_PARSER_EXTRAS_H
+#define GLSL_PARSER_EXTRAS_H
+
+/*
+ * Most of the definitions here only apply to C++
+ */
+#ifdef __cplusplus
+
+
+#include <cstdlib>
+#include "glsl_symbol_table.h"
+
+enum _mesa_glsl_parser_targets {
+ vertex_shader,
+ geometry_shader,
+ fragment_shader
+};
+
+struct gl_context;
+
+struct _mesa_glsl_parse_state {
+ _mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
+ void *mem_ctx);
+
+ /* Callers of this talloc-based new need not call delete. It's
+ * easier to just talloc_free 'ctx' (or any of its ancestors). */
+ static void* operator new(size_t size, void *ctx)
+ {
+ void *mem = talloc_zero_size(ctx, size);
+ assert(mem != NULL);
+
+ return mem;
+ }
+
+ /* If the user *does* call delete, that's OK, we will just
+ * talloc_free in that case. */
+ static void operator delete(void *mem)
+ {
+ talloc_free(mem);
+ }
+
+ void *scanner;
+ exec_list translation_unit;
+ glsl_symbol_table *symbols;
+
+ bool es_shader;
+ unsigned language_version;
+ const char *version_string;
+ enum _mesa_glsl_parser_targets target;
+
+ /**
+ * Implementation defined limits that affect built-in variables, etc.
+ *
+ * \sa struct gl_constants (in mtypes.h)
+ */
+ struct {
+ /* 1.10 */
+ unsigned MaxLights;
+ unsigned MaxClipPlanes;
+ unsigned MaxTextureUnits;
+ unsigned MaxTextureCoords;
+ unsigned MaxVertexAttribs;
+ unsigned MaxVertexUniformComponents;
+ unsigned MaxVaryingFloats;
+ unsigned MaxVertexTextureImageUnits;
+ unsigned MaxCombinedTextureImageUnits;
+ unsigned MaxTextureImageUnits;
+ unsigned MaxFragmentUniformComponents;
+
+ /* ARB_draw_buffers */
+ unsigned MaxDrawBuffers;
+ } Const;
+
+ /**
+ * During AST to IR conversion, pointer to current IR function
+ *
+ * Will be \c NULL whenever the AST to IR conversion is not inside a
+ * function definition.
+ */
+ class ir_function_signature *current_function;
+
+ /** Have we found a return statement in this function? */
+ bool found_return;
+
+ /** Was there an error during compilation? */
+ bool error;
+
+ /**
+ * Are all shader inputs / outputs invariant?
+ *
+ * This is set when the 'STDGL invariant(all)' pragma is used.
+ */
+ bool all_invariant;
+
+ /** Loop or switch statement containing the current instructions. */
+ class ir_instruction *loop_or_switch_nesting;
+ class ast_iteration_statement *loop_or_switch_nesting_ast;
+
+ /** List of structures defined in user code. */
+ const glsl_type **user_structures;
+ unsigned num_user_structures;
+
+ char *info_log;
+
+ /**
+ * \name Enable bits for GLSL extensions
+ */
+ /*@{*/
+ unsigned ARB_draw_buffers_enable:1;
+ unsigned ARB_draw_buffers_warn:1;
+ unsigned ARB_draw_instanced_enable:1;
+ unsigned ARB_draw_instanced_warn:1;
+ unsigned ARB_explicit_attrib_location_enable:1;
+ unsigned ARB_explicit_attrib_location_warn:1;
+ unsigned ARB_fragment_coord_conventions_enable:1;
+ unsigned ARB_fragment_coord_conventions_warn:1;
+ unsigned ARB_texture_rectangle_enable:1;
+ unsigned ARB_texture_rectangle_warn:1;
+ unsigned EXT_texture_array_enable:1;
+ unsigned EXT_texture_array_warn:1;
+ unsigned ARB_shader_stencil_export_enable:1;
+ unsigned ARB_shader_stencil_export_warn:1;
+ unsigned AMD_conservative_depth_enable:1;
+ unsigned AMD_conservative_depth_warn:1;
+ /*@}*/
+
+ /** Extensions supported by the OpenGL implementation. */
+ const struct gl_extensions *extensions;
+
+ /** Shaders containing built-in functions that are used for linking. */
+ struct gl_shader *builtins_to_link[16];
+ unsigned num_builtins_to_link;
+};
+
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ unsigned source;
+} YYLTYPE;
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+do { \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC(Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC(Rhs, 0).last_column; \
+ } \
+ (Current).source = 0; \
+} while (0)
+
+extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+ const char *fmt, ...);
+
+/**
+ * Emit a warning to the shader log
+ *
+ * \sa _mesa_glsl_error
+ */
+extern void _mesa_glsl_warning(const YYLTYPE *locp,
+ _mesa_glsl_parse_state *state,
+ const char *fmt, ...);
+
+extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
+ const char *string);
+
+extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state);
+
+union YYSTYPE;
+extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc,
+ void *scanner);
+
+extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *);
+
+/**
+ * Process elements of the #extension directive
+ *
+ * \return
+ * If \c name and \c behavior are valid, \c true is returned. Otherwise
+ * \c false is returned.
+ */
+extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
+ const char *behavior,
+ YYLTYPE *behavior_locp,
+ _mesa_glsl_parse_state *state);
+
+/**
+ * Get the textual name of the specified shader target
+ */
+extern const char *
+_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target);
+
+
+#endif /* __cplusplus */
+
+
+/*
+ * These definitions apply to C and C++
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int preprocess(void *ctx, const char **shader, char **info_log,
+ const struct gl_extensions *extensions, int api);
+
+extern void _mesa_destroy_shader_compiler();
+extern void _mesa_destroy_shader_compiler_caches();
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* GLSL_PARSER_EXTRAS_H */
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 28fe3f4ac..b4ceb5bba 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1,1544 +1,1561 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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 <string.h>
-#include "main/core.h" /* for MAX2 */
-#include "ir.h"
-#include "ir_visitor.h"
-#include "glsl_types.h"
-
-ir_rvalue::ir_rvalue()
-{
- this->type = glsl_type::error_type;
-}
-
-bool ir_rvalue::is_zero() const
-{
- return false;
-}
-
-bool ir_rvalue::is_one() const
-{
- return false;
-}
-
-bool ir_rvalue::is_negative_one() const
-{
- return false;
-}
-
-/**
- * Modify the swizzle make to move one component to another
- *
- * \param m IR swizzle to be modified
- * \param from Component in the RHS that is to be swizzled
- * \param to Desired swizzle location of \c from
- */
-static void
-update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to)
-{
- switch (to) {
- case 0: m.x = from; break;
- case 1: m.y = from; break;
- case 2: m.z = from; break;
- case 3: m.w = from; break;
- default: assert(!"Should not get here.");
- }
-
- m.num_components = MAX2(m.num_components, (to + 1));
-}
-
-void
-ir_assignment::set_lhs(ir_rvalue *lhs)
-{
- void *mem_ctx = this;
- bool swizzled = false;
-
- while (lhs != NULL) {
- ir_swizzle *swiz = lhs->as_swizzle();
-
- if (swiz == NULL)
- break;
-
- unsigned write_mask = 0;
- ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
-
- for (unsigned i = 0; i < swiz->mask.num_components; i++) {
- unsigned c = 0;
-
- switch (i) {
- case 0: c = swiz->mask.x; break;
- case 1: c = swiz->mask.y; break;
- case 2: c = swiz->mask.z; break;
- case 3: c = swiz->mask.w; break;
- default: assert(!"Should not get here.");
- }
-
- write_mask |= (((this->write_mask >> i) & 1) << c);
- update_rhs_swizzle(rhs_swiz, i, c);
- }
-
- this->write_mask = write_mask;
- lhs = swiz->val;
-
- this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz);
- swizzled = true;
- }
-
- if (swizzled) {
- /* Now, RHS channels line up with the LHS writemask. Collapse it
- * to just the channels that will be written.
- */
- ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
- int rhs_chan = 0;
- for (int i = 0; i < 4; i++) {
- if (write_mask & (1 << i))
- update_rhs_swizzle(rhs_swiz, i, rhs_chan++);
- }
- this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz);
- }
-
- assert((lhs == NULL) || lhs->as_dereference());
-
- this->lhs = (ir_dereference *) lhs;
-}
-
-ir_variable *
-ir_assignment::whole_variable_written()
-{
- ir_variable *v = this->lhs->whole_variable_referenced();
-
- if (v == NULL)
- return NULL;
-
- if (v->type->is_scalar())
- return v;
-
- if (v->type->is_vector()) {
- const unsigned mask = (1U << v->type->vector_elements) - 1;
-
- if (mask != this->write_mask)
- return NULL;
- }
-
- /* Either all the vector components are assigned or the variable is some
- * composite type (and the whole thing is assigned.
- */
- return v;
-}
-
-ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
- ir_rvalue *condition, unsigned write_mask)
-{
- this->ir_type = ir_type_assignment;
- this->condition = condition;
- this->rhs = rhs;
- this->lhs = lhs;
- this->write_mask = write_mask;
-
- if (lhs->type->is_scalar() || lhs->type->is_vector()) {
- int lhs_components = 0;
- for (int i = 0; i < 4; i++) {
- if (write_mask & (1 << i))
- lhs_components++;
- }
-
- assert(lhs_components == this->rhs->type->vector_elements);
- }
-}
-
-ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
- ir_rvalue *condition)
-{
- this->ir_type = ir_type_assignment;
- this->condition = condition;
- this->rhs = rhs;
-
- /* If the RHS is a vector type, assume that all components of the vector
- * type are being written to the LHS. The write mask comes from the RHS
- * because we can have a case where the LHS is a vec4 and the RHS is a
- * vec3. In that case, the assignment is:
- *
- * (assign (...) (xyz) (var_ref lhs) (var_ref rhs))
- */
- if (rhs->type->is_vector())
- this->write_mask = (1U << rhs->type->vector_elements) - 1;
- else if (rhs->type->is_scalar())
- this->write_mask = 1;
- else
- this->write_mask = 0;
-
- this->set_lhs(lhs);
-}
-
-
-ir_expression::ir_expression(int op, const struct glsl_type *type,
- ir_rvalue *op0)
-{
- assert(get_num_operands(ir_expression_operation(op)) == 1);
- this->ir_type = ir_type_expression;
- this->type = type;
- this->operation = ir_expression_operation(op);
- this->operands[0] = op0;
- this->operands[1] = NULL;
- this->operands[2] = NULL;
- this->operands[3] = NULL;
-}
-
-ir_expression::ir_expression(int op, const struct glsl_type *type,
- ir_rvalue *op0, ir_rvalue *op1)
-{
- assert(((op1 == NULL) && (get_num_operands(ir_expression_operation(op)) == 1))
- || (get_num_operands(ir_expression_operation(op)) == 2));
- this->ir_type = ir_type_expression;
- this->type = type;
- this->operation = ir_expression_operation(op);
- this->operands[0] = op0;
- this->operands[1] = op1;
- this->operands[2] = NULL;
- this->operands[3] = NULL;
-}
-
-ir_expression::ir_expression(int op, const struct glsl_type *type,
- ir_rvalue *op0, ir_rvalue *op1,
- ir_rvalue *op2, ir_rvalue *op3)
-{
- this->ir_type = ir_type_expression;
- this->type = type;
- this->operation = ir_expression_operation(op);
- this->operands[0] = op0;
- this->operands[1] = op1;
- this->operands[2] = op2;
- this->operands[3] = op3;
-}
-
-ir_expression::ir_expression(int op, ir_rvalue *op0)
-{
- this->ir_type = ir_type_expression;
-
- this->operation = ir_expression_operation(op);
- this->operands[0] = op0;
- this->operands[1] = NULL;
- this->operands[2] = NULL;
- this->operands[3] = NULL;
-
- assert(op <= ir_last_unop);
-
- switch (this->operation) {
- case ir_unop_bit_not:
- case ir_unop_logic_not:
- case ir_unop_neg:
- case ir_unop_abs:
- case ir_unop_sign:
- case ir_unop_rcp:
- case ir_unop_rsq:
- case ir_unop_sqrt:
- case ir_unop_exp:
- case ir_unop_log:
- case ir_unop_exp2:
- case ir_unop_log2:
- case ir_unop_trunc:
- case ir_unop_ceil:
- case ir_unop_floor:
- case ir_unop_fract:
- case ir_unop_round_even:
- case ir_unop_sin:
- case ir_unop_cos:
- case ir_unop_sin_reduced:
- case ir_unop_cos_reduced:
- case ir_unop_dFdx:
- case ir_unop_dFdy:
- this->type = op0->type;
- break;
-
- case ir_unop_f2i:
- case ir_unop_b2i:
- this->type = glsl_type::get_instance(GLSL_TYPE_INT,
- op0->type->vector_elements, 1);
- break;
-
- case ir_unop_b2f:
- case ir_unop_i2f:
- case ir_unop_u2f:
- this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
- op0->type->vector_elements, 1);
- break;
-
- case ir_unop_f2b:
- case ir_unop_i2b:
- this->type = glsl_type::get_instance(GLSL_TYPE_BOOL,
- op0->type->vector_elements, 1);
- break;
-
- case ir_unop_noise:
- this->type = glsl_type::float_type;
- break;
-
- case ir_unop_any:
- this->type = glsl_type::bool_type;
- break;
-
- default:
- assert(!"not reached: missing automatic type setup for ir_expression");
- this->type = op0->type;
- break;
- }
-}
-
-ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
-{
- this->ir_type = ir_type_expression;
-
- this->operation = ir_expression_operation(op);
- this->operands[0] = op0;
- this->operands[1] = op1;
- this->operands[2] = NULL;
- this->operands[3] = NULL;
-
- assert(op > ir_last_unop);
-
- switch (this->operation) {
- case ir_binop_all_equal:
- case ir_binop_any_nequal:
- this->type = glsl_type::bool_type;
- break;
-
- case ir_binop_add:
- case ir_binop_sub:
- case ir_binop_min:
- case ir_binop_max:
- case ir_binop_pow:
- case ir_binop_mul:
- case ir_binop_div:
- case ir_binop_mod:
- if (op0->type->is_scalar()) {
- this->type = op1->type;
- } else if (op1->type->is_scalar()) {
- this->type = op0->type;
- } else {
- /* FINISHME: matrix types */
- assert(!op0->type->is_matrix() && !op1->type->is_matrix());
- assert(op0->type == op1->type);
- this->type = op0->type;
- }
- break;
-
- case ir_binop_logic_and:
- case ir_binop_logic_xor:
- case ir_binop_logic_or:
- case ir_binop_bit_and:
- case ir_binop_bit_xor:
- case ir_binop_bit_or:
- if (op0->type->is_scalar()) {
- this->type = op1->type;
- } else if (op1->type->is_scalar()) {
- this->type = op0->type;
- }
- break;
-
- case ir_binop_equal:
- case ir_binop_nequal:
- case ir_binop_lequal:
- case ir_binop_gequal:
- case ir_binop_less:
- case ir_binop_greater:
- assert(op0->type == op1->type);
- this->type = glsl_type::get_instance(GLSL_TYPE_BOOL,
- op0->type->vector_elements, 1);
- break;
-
- case ir_binop_dot:
- this->type = glsl_type::float_type;
- break;
-
- case ir_binop_lshift:
- case ir_binop_rshift:
- this->type = op0->type;
- break;
-
- default:
- assert(!"not reached: missing automatic type setup for ir_expression");
- this->type = glsl_type::float_type;
- }
-}
-
-unsigned int
-ir_expression::get_num_operands(ir_expression_operation op)
-{
- assert(op <= ir_last_opcode);
-
- if (op <= ir_last_unop)
- return 1;
-
- if (op <= ir_last_binop)
- return 2;
-
- if (op == ir_quadop_vector)
- return 4;
-
- assert(false);
- return 0;
-}
-
-static const char *const operator_strs[] = {
- "~",
- "!",
- "neg",
- "abs",
- "sign",
- "rcp",
- "rsq",
- "sqrt",
- "exp",
- "log",
- "exp2",
- "log2",
- "f2i",
- "i2f",
- "f2b",
- "b2f",
- "i2b",
- "b2i",
- "u2f",
- "any",
- "trunc",
- "ceil",
- "floor",
- "fract",
- "round_even",
- "sin",
- "cos",
- "sin_reduced",
- "cos_reduced",
- "dFdx",
- "dFdy",
- "noise",
- "+",
- "-",
- "*",
- "/",
- "%",
- "<",
- ">",
- "<=",
- ">=",
- "==",
- "!=",
- "all_equal",
- "any_nequal",
- "<<",
- ">>",
- "&",
- "^",
- "|",
- "&&",
- "^^",
- "||",
- "dot",
- "min",
- "max",
- "pow",
- "vector",
-};
-
-const char *ir_expression::operator_string(ir_expression_operation op)
-{
- assert((unsigned int) op < Elements(operator_strs));
- assert(Elements(operator_strs) == (ir_quadop_vector + 1));
- return operator_strs[op];
-}
-
-const char *ir_expression::operator_string()
-{
- return operator_string(this->operation);
-}
-
-ir_expression_operation
-ir_expression::get_operator(const char *str)
-{
- const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]);
- for (int op = 0; op < operator_count; op++) {
- if (strcmp(str, operator_strs[op]) == 0)
- return (ir_expression_operation) op;
- }
- return (ir_expression_operation) -1;
-}
-
-ir_constant::ir_constant()
-{
- this->ir_type = ir_type_constant;
-}
-
-ir_constant::ir_constant(const struct glsl_type *type,
- const ir_constant_data *data)
-{
- assert((type->base_type >= GLSL_TYPE_UINT)
- && (type->base_type <= GLSL_TYPE_BOOL));
-
- this->ir_type = ir_type_constant;
- this->type = type;
- memcpy(& this->value, data, sizeof(this->value));
-}
-
-ir_constant::ir_constant(float f)
-{
- this->ir_type = ir_type_constant;
- this->type = glsl_type::float_type;
- this->value.f[0] = f;
- for (int i = 1; i < 16; i++) {
- this->value.f[i] = 0;
- }
-}
-
-ir_constant::ir_constant(unsigned int u)
-{
- this->ir_type = ir_type_constant;
- this->type = glsl_type::uint_type;
- this->value.u[0] = u;
- for (int i = 1; i < 16; i++) {
- this->value.u[i] = 0;
- }
-}
-
-ir_constant::ir_constant(int i)
-{
- this->ir_type = ir_type_constant;
- this->type = glsl_type::int_type;
- this->value.i[0] = i;
- for (int i = 1; i < 16; i++) {
- this->value.i[i] = 0;
- }
-}
-
-ir_constant::ir_constant(bool b)
-{
- this->ir_type = ir_type_constant;
- this->type = glsl_type::bool_type;
- this->value.b[0] = b;
- for (int i = 1; i < 16; i++) {
- this->value.b[i] = false;
- }
-}
-
-ir_constant::ir_constant(const ir_constant *c, unsigned i)
-{
- this->ir_type = ir_type_constant;
- this->type = c->type->get_base_type();
-
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break;
- case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break;
- case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
- case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break;
- default: assert(!"Should not get here."); break;
- }
-}
-
-ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
-{
- this->ir_type = ir_type_constant;
- this->type = type;
-
- assert(type->is_scalar() || type->is_vector() || type->is_matrix()
- || type->is_record() || type->is_array());
-
- if (type->is_array()) {
- this->array_elements = talloc_array(this, ir_constant *, type->length);
- unsigned i = 0;
- foreach_list(node, value_list) {
- ir_constant *value = (ir_constant *) node;
- assert(value->as_constant() != NULL);
-
- this->array_elements[i++] = value;
- }
- return;
- }
-
- /* If the constant is a record, the types of each of the entries in
- * value_list must be a 1-for-1 match with the structure components. Each
- * entry must also be a constant. Just move the nodes from the value_list
- * to the list in the ir_constant.
- */
- /* FINISHME: Should there be some type checking and / or assertions here? */
- /* FINISHME: Should the new constant take ownership of the nodes from
- * FINISHME: value_list, or should it make copies?
- */
- if (type->is_record()) {
- value_list->move_nodes_to(& this->components);
- return;
- }
-
- for (unsigned i = 0; i < 16; i++) {
- this->value.u[i] = 0;
- }
-
- ir_constant *value = (ir_constant *) (value_list->head);
-
- /* Constructors with exactly one scalar argument are special for vectors
- * and matrices. For vectors, the scalar value is replicated to fill all
- * the components. For matrices, the scalar fills the components of the
- * diagonal while the rest is filled with 0.
- */
- if (value->type->is_scalar() && value->next->is_tail_sentinel()) {
- if (type->is_matrix()) {
- /* Matrix - fill diagonal (rest is already set to 0) */
- assert(type->base_type == GLSL_TYPE_FLOAT);
- for (unsigned i = 0; i < type->matrix_columns; i++)
- this->value.f[i * type->vector_elements + i] = value->value.f[0];
- } else {
- /* Vector or scalar - fill all components */
- switch (type->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- for (unsigned i = 0; i < type->components(); i++)
- this->value.u[i] = value->value.u[0];
- break;
- case GLSL_TYPE_FLOAT:
- for (unsigned i = 0; i < type->components(); i++)
- this->value.f[i] = value->value.f[0];
- break;
- case GLSL_TYPE_BOOL:
- for (unsigned i = 0; i < type->components(); i++)
- this->value.b[i] = value->value.b[0];
- break;
- default:
- assert(!"Should not get here.");
- break;
- }
- }
- return;
- }
-
- if (type->is_matrix() && value->type->is_matrix()) {
- assert(value->next->is_tail_sentinel());
-
- /* From section 5.4.2 of the GLSL 1.20 spec:
- * "If a matrix is constructed from a matrix, then each component
- * (column i, row j) in the result that has a corresponding component
- * (column i, row j) in the argument will be initialized from there."
- */
- unsigned cols = MIN2(type->matrix_columns, value->type->matrix_columns);
- unsigned rows = MIN2(type->vector_elements, value->type->vector_elements);
- for (unsigned i = 0; i < cols; i++) {
- for (unsigned j = 0; j < rows; j++) {
- const unsigned src = i * value->type->vector_elements + j;
- const unsigned dst = i * type->vector_elements + j;
- this->value.f[dst] = value->value.f[src];
- }
- }
-
- /* "All other components will be initialized to the identity matrix." */
- for (unsigned i = cols; i < type->matrix_columns; i++)
- this->value.f[i * type->vector_elements + i] = 1.0;
-
- return;
- }
-
- /* Use each component from each entry in the value_list to initialize one
- * component of the constant being constructed.
- */
- for (unsigned i = 0; i < type->components(); /* empty */) {
- assert(value->as_constant() != NULL);
- assert(!value->is_tail_sentinel());
-
- for (unsigned j = 0; j < value->type->components(); j++) {
- switch (type->base_type) {
- case GLSL_TYPE_UINT:
- this->value.u[i] = value->get_uint_component(j);
- break;
- case GLSL_TYPE_INT:
- this->value.i[i] = value->get_int_component(j);
- break;
- case GLSL_TYPE_FLOAT:
- this->value.f[i] = value->get_float_component(j);
- break;
- case GLSL_TYPE_BOOL:
- this->value.b[i] = value->get_bool_component(j);
- break;
- default:
- /* FINISHME: What to do? Exceptions are not the answer.
- */
- break;
- }
-
- i++;
- if (i >= type->components())
- break;
- }
-
- value = (ir_constant *) value->next;
- }
-}
-
-ir_constant *
-ir_constant::zero(void *mem_ctx, const glsl_type *type)
-{
- assert(type->is_numeric() || type->is_boolean());
-
- ir_constant *c = new(mem_ctx) ir_constant;
- c->type = type;
- memset(&c->value, 0, sizeof(c->value));
-
- return c;
-}
-
-bool
-ir_constant::get_bool_component(unsigned i) const
-{
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT: return this->value.u[i] != 0;
- case GLSL_TYPE_INT: return this->value.i[i] != 0;
- case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
- case GLSL_TYPE_BOOL: return this->value.b[i];
- default: assert(!"Should not get here."); break;
- }
-
- /* Must return something to make the compiler happy. This is clearly an
- * error case.
- */
- return false;
-}
-
-float
-ir_constant::get_float_component(unsigned i) const
-{
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT: return (float) this->value.u[i];
- case GLSL_TYPE_INT: return (float) this->value.i[i];
- case GLSL_TYPE_FLOAT: return this->value.f[i];
- case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0;
- default: assert(!"Should not get here."); break;
- }
-
- /* Must return something to make the compiler happy. This is clearly an
- * error case.
- */
- return 0.0;
-}
-
-int
-ir_constant::get_int_component(unsigned i) const
-{
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT: return this->value.u[i];
- case GLSL_TYPE_INT: return this->value.i[i];
- case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
- case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
- default: assert(!"Should not get here."); break;
- }
-
- /* Must return something to make the compiler happy. This is clearly an
- * error case.
- */
- return 0;
-}
-
-unsigned
-ir_constant::get_uint_component(unsigned i) const
-{
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT: return this->value.u[i];
- case GLSL_TYPE_INT: return this->value.i[i];
- case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
- case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
- default: assert(!"Should not get here."); break;
- }
-
- /* Must return something to make the compiler happy. This is clearly an
- * error case.
- */
- return 0;
-}
-
-ir_constant *
-ir_constant::get_array_element(unsigned i) const
-{
- assert(this->type->is_array());
-
- /* From page 35 (page 41 of the PDF) of the GLSL 1.20 spec:
- *
- * "Behavior is undefined if a shader subscripts an array with an index
- * less than 0 or greater than or equal to the size the array was
- * declared with."
- *
- * Most out-of-bounds accesses are removed before things could get this far.
- * There are cases where non-constant array index values can get constant
- * folded.
- */
- if (int(i) < 0)
- i = 0;
- else if (i >= this->type->length)
- i = this->type->length - 1;
-
- return array_elements[i];
-}
-
-ir_constant *
-ir_constant::get_record_field(const char *name)
-{
- int idx = this->type->field_index(name);
-
- if (idx < 0)
- return NULL;
-
- if (this->components.is_empty())
- return NULL;
-
- exec_node *node = this->components.head;
- for (int i = 0; i < idx; i++) {
- node = node->next;
-
- /* If the end of the list is encountered before the element matching the
- * requested field is found, return NULL.
- */
- if (node->is_tail_sentinel())
- return NULL;
- }
-
- return (ir_constant *) node;
-}
-
-
-bool
-ir_constant::has_value(const ir_constant *c) const
-{
- if (this->type != c->type)
- return false;
-
- if (this->type->is_array()) {
- for (unsigned i = 0; i < this->type->length; i++) {
- if (!this->array_elements[i]->has_value(c->array_elements[i]))
- return false;
- }
- return true;
- }
-
- if (this->type->base_type == GLSL_TYPE_STRUCT) {
- const exec_node *a_node = this->components.head;
- const exec_node *b_node = c->components.head;
-
- while (!a_node->is_tail_sentinel()) {
- assert(!b_node->is_tail_sentinel());
-
- const ir_constant *const a_field = (ir_constant *) a_node;
- const ir_constant *const b_field = (ir_constant *) b_node;
-
- if (!a_field->has_value(b_field))
- return false;
-
- a_node = a_node->next;
- b_node = b_node->next;
- }
-
- return true;
- }
-
- for (unsigned i = 0; i < this->type->components(); i++) {
- switch (this->type->base_type) {
- case GLSL_TYPE_UINT:
- if (this->value.u[i] != c->value.u[i])
- return false;
- break;
- case GLSL_TYPE_INT:
- if (this->value.i[i] != c->value.i[i])
- return false;
- break;
- case GLSL_TYPE_FLOAT:
- if (this->value.f[i] != c->value.f[i])
- return false;
- break;
- case GLSL_TYPE_BOOL:
- if (this->value.b[i] != c->value.b[i])
- return false;
- break;
- default:
- assert(!"Should not get here.");
- return false;
- }
- }
-
- return true;
-}
-
-bool
-ir_constant::is_zero() const
-{
- if (!this->type->is_scalar() && !this->type->is_vector())
- return false;
-
- for (unsigned c = 0; c < this->type->vector_elements; c++) {
- switch (this->type->base_type) {
- case GLSL_TYPE_FLOAT:
- if (this->value.f[c] != 0.0)
- return false;
- break;
- case GLSL_TYPE_INT:
- if (this->value.i[c] != 0)
- return false;
- break;
- case GLSL_TYPE_UINT:
- if (this->value.u[c] != 0)
- return false;
- break;
- case GLSL_TYPE_BOOL:
- if (this->value.b[c] != false)
- return false;
- break;
- default:
- /* The only other base types are structures, arrays, and samplers.
- * Samplers cannot be constants, and the others should have been
- * filtered out above.
- */
- assert(!"Should not get here.");
- return false;
- }
- }
-
- return true;
-}
-
-bool
-ir_constant::is_one() const
-{
- if (!this->type->is_scalar() && !this->type->is_vector())
- return false;
-
- for (unsigned c = 0; c < this->type->vector_elements; c++) {
- switch (this->type->base_type) {
- case GLSL_TYPE_FLOAT:
- if (this->value.f[c] != 1.0)
- return false;
- break;
- case GLSL_TYPE_INT:
- if (this->value.i[c] != 1)
- return false;
- break;
- case GLSL_TYPE_UINT:
- if (this->value.u[c] != 1)
- return false;
- break;
- case GLSL_TYPE_BOOL:
- if (this->value.b[c] != true)
- return false;
- break;
- default:
- /* The only other base types are structures, arrays, and samplers.
- * Samplers cannot be constants, and the others should have been
- * filtered out above.
- */
- assert(!"Should not get here.");
- return false;
- }
- }
-
- return true;
-}
-
-bool
-ir_constant::is_negative_one() const
-{
- if (!this->type->is_scalar() && !this->type->is_vector())
- return false;
-
- if (this->type->is_boolean())
- return false;
-
- for (unsigned c = 0; c < this->type->vector_elements; c++) {
- switch (this->type->base_type) {
- case GLSL_TYPE_FLOAT:
- if (this->value.f[c] != -1.0)
- return false;
- break;
- case GLSL_TYPE_INT:
- if (this->value.i[c] != -1)
- return false;
- break;
- case GLSL_TYPE_UINT:
- if (int(this->value.u[c]) != -1)
- return false;
- break;
- default:
- /* The only other base types are structures, arrays, samplers, and
- * booleans. Samplers cannot be constants, and the others should
- * have been filtered out above.
- */
- assert(!"Should not get here.");
- return false;
- }
- }
-
- return true;
-}
-
-ir_loop::ir_loop()
-{
- this->ir_type = ir_type_loop;
- this->cmp = ir_unop_neg;
- this->from = NULL;
- this->to = NULL;
- this->increment = NULL;
- this->counter = NULL;
-}
-
-
-ir_dereference_variable::ir_dereference_variable(ir_variable *var)
-{
- this->ir_type = ir_type_dereference_variable;
- this->var = var;
- this->type = (var != NULL) ? var->type : glsl_type::error_type;
-}
-
-
-ir_dereference_array::ir_dereference_array(ir_rvalue *value,
- ir_rvalue *array_index)
-{
- this->ir_type = ir_type_dereference_array;
- this->array_index = array_index;
- this->set_array(value);
-}
-
-
-ir_dereference_array::ir_dereference_array(ir_variable *var,
- ir_rvalue *array_index)
-{
- void *ctx = talloc_parent(var);
-
- this->ir_type = ir_type_dereference_array;
- this->array_index = array_index;
- this->set_array(new(ctx) ir_dereference_variable(var));
-}
-
-
-void
-ir_dereference_array::set_array(ir_rvalue *value)
-{
- this->array = value;
- this->type = glsl_type::error_type;
-
- if (this->array != NULL) {
- const glsl_type *const vt = this->array->type;
-
- if (vt->is_array()) {
- type = vt->element_type();
- } else if (vt->is_matrix()) {
- type = vt->column_type();
- } else if (vt->is_vector()) {
- type = vt->get_base_type();
- }
- }
-}
-
-
-ir_dereference_record::ir_dereference_record(ir_rvalue *value,
- const char *field)
-{
- this->ir_type = ir_type_dereference_record;
- this->record = value;
- this->field = talloc_strdup(this, field);
- this->type = (this->record != NULL)
- ? this->record->type->field_type(field) : glsl_type::error_type;
-}
-
-
-ir_dereference_record::ir_dereference_record(ir_variable *var,
- const char *field)
-{
- void *ctx = talloc_parent(var);
-
- this->ir_type = ir_type_dereference_record;
- this->record = new(ctx) ir_dereference_variable(var);
- this->field = talloc_strdup(this, field);
- this->type = (this->record != NULL)
- ? this->record->type->field_type(field) : glsl_type::error_type;
-}
-
-bool type_contains_sampler(const glsl_type *type)
-{
- if (type->is_array()) {
- return type_contains_sampler(type->fields.array);
- } else if (type->is_record()) {
- for (unsigned int i = 0; i < type->length; i++) {
- if (type_contains_sampler(type->fields.structure[i].type))
- return true;
- }
- return false;
- } else {
- return type->is_sampler();
- }
-}
-
-bool
-ir_dereference::is_lvalue()
-{
- ir_variable *var = this->variable_referenced();
-
- /* Every l-value derference chain eventually ends in a variable.
- */
- if ((var == NULL) || var->read_only)
- return false;
-
- if (this->type->is_array() && !var->array_lvalue)
- return false;
-
- /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
- *
- * "Samplers cannot be treated as l-values; hence cannot be used
- * as out or inout function parameters, nor can they be
- * assigned into."
- */
- if (type_contains_sampler(this->type))
- return false;
-
- return true;
-}
-
-
-const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" };
-
-const char *ir_texture::opcode_string()
-{
- assert((unsigned int) op <=
- sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]));
- return tex_opcode_strs[op];
-}
-
-ir_texture_opcode
-ir_texture::get_opcode(const char *str)
-{
- const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]);
- for (int op = 0; op < count; op++) {
- if (strcmp(str, tex_opcode_strs[op]) == 0)
- return (ir_texture_opcode) op;
- }
- return (ir_texture_opcode) -1;
-}
-
-
-void
-ir_texture::set_sampler(ir_dereference *sampler)
-{
- assert(sampler != NULL);
- this->sampler = sampler;
-
- switch (sampler->type->sampler_type) {
- case GLSL_TYPE_FLOAT:
- this->type = glsl_type::vec4_type;
- break;
- case GLSL_TYPE_INT:
- this->type = glsl_type::ivec4_type;
- break;
- case GLSL_TYPE_UINT:
- this->type = glsl_type::uvec4_type;
- break;
- }
-}
-
-
-void
-ir_swizzle::init_mask(const unsigned *comp, unsigned count)
-{
- assert((count >= 1) && (count <= 4));
-
- memset(&this->mask, 0, sizeof(this->mask));
- this->mask.num_components = count;
-
- unsigned dup_mask = 0;
- switch (count) {
- case 4:
- assert(comp[3] <= 3);
- dup_mask |= (1U << comp[3])
- & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2]));
- this->mask.w = comp[3];
-
- case 3:
- assert(comp[2] <= 3);
- dup_mask |= (1U << comp[2])
- & ((1U << comp[0]) | (1U << comp[1]));
- this->mask.z = comp[2];
-
- case 2:
- assert(comp[1] <= 3);
- dup_mask |= (1U << comp[1])
- & ((1U << comp[0]));
- this->mask.y = comp[1];
-
- case 1:
- assert(comp[0] <= 3);
- this->mask.x = comp[0];
- }
-
- this->mask.has_duplicates = dup_mask != 0;
-
- /* Based on the number of elements in the swizzle and the base type
- * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
- * generate the type of the resulting value.
- */
- type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
-}
-
-ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
- unsigned w, unsigned count)
- : val(val)
-{
- const unsigned components[4] = { x, y, z, w };
- this->ir_type = ir_type_swizzle;
- this->init_mask(components, count);
-}
-
-ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
- unsigned count)
- : val(val)
-{
- this->ir_type = ir_type_swizzle;
- this->init_mask(comp, count);
-}
-
-ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
-{
- this->ir_type = ir_type_swizzle;
- this->val = val;
- this->mask = mask;
- this->type = glsl_type::get_instance(val->type->base_type,
- mask.num_components, 1);
-}
-
-#define X 1
-#define R 5
-#define S 9
-#define I 13
-
-ir_swizzle *
-ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
-{
- void *ctx = talloc_parent(val);
-
- /* For each possible swizzle character, this table encodes the value in
- * \c idx_map that represents the 0th element of the vector. For invalid
- * swizzle characters (e.g., 'k'), a special value is used that will allow
- * detection of errors.
- */
- static const unsigned char base_idx[26] = {
- /* a b c d e f g h i j k l m */
- R, R, I, I, I, I, R, I, I, I, I, I, I,
- /* n o p q r s t u v w x y z */
- I, I, S, S, R, S, S, I, I, X, X, X, X
- };
-
- /* Each valid swizzle character has an entry in the previous table. This
- * table encodes the base index encoded in the previous table plus the actual
- * index of the swizzle character. When processing swizzles, the first
- * character in the string is indexed in the previous table. Each character
- * in the string is indexed in this table, and the value found there has the
- * value form the first table subtracted. The result must be on the range
- * [0,3].
- *
- * For example, the string "wzyx" will get X from the first table. Each of
- * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
- * subtraction, the swizzle values are { 3, 2, 1, 0 }.
- *
- * The string "wzrg" will get X from the first table. Each of the characters
- * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
- * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
- * [0,3], the error is detected.
- */
- static const unsigned char idx_map[26] = {
- /* a b c d e f g h i j k l m */
- R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
- /* n o p q r s t u v w x y z */
- 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
- };
-
- int swiz_idx[4] = { 0, 0, 0, 0 };
- unsigned i;
-
-
- /* Validate the first character in the swizzle string and look up the base
- * index value as described above.
- */
- if ((str[0] < 'a') || (str[0] > 'z'))
- return NULL;
-
- const unsigned base = base_idx[str[0] - 'a'];
-
-
- for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
- /* Validate the next character, and, as described above, convert it to a
- * swizzle index.
- */
- if ((str[i] < 'a') || (str[i] > 'z'))
- return NULL;
-
- swiz_idx[i] = idx_map[str[i] - 'a'] - base;
- if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
- return NULL;
- }
-
- if (str[i] != '\0')
- return NULL;
-
- return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
- swiz_idx[3], i);
-}
-
-#undef X
-#undef R
-#undef S
-#undef I
-
-ir_variable *
-ir_swizzle::variable_referenced()
-{
- return this->val->variable_referenced();
-}
-
-
-ir_variable::ir_variable(const struct glsl_type *type, const char *name,
- ir_variable_mode mode)
- : max_array_access(0), read_only(false), centroid(false), invariant(false),
- mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
-{
- this->ir_type = ir_type_variable;
- this->type = type;
- this->name = talloc_strdup(this, name);
- this->explicit_location = false;
- this->location = -1;
- this->warn_extension = NULL;
- this->constant_value = NULL;
- this->origin_upper_left = false;
- this->pixel_center_integer = false;
- this->used = false;
-
- if (type && type->base_type == GLSL_TYPE_SAMPLER)
- this->read_only = true;
-}
-
-
-const char *
-ir_variable::interpolation_string() const
-{
- switch (this->interpolation) {
- case ir_var_smooth: return "smooth";
- case ir_var_flat: return "flat";
- case ir_var_noperspective: return "noperspective";
- }
-
- assert(!"Should not get here.");
- return "";
-}
-
-
-unsigned
-ir_variable::component_slots() const
-{
- /* FINISHME: Sparsely accessed arrays require fewer slots. */
- return this->type->component_slots();
-}
-
-
-ir_function_signature::ir_function_signature(const glsl_type *return_type)
- : return_type(return_type), is_defined(false), _function(NULL)
-{
- this->ir_type = ir_type_function_signature;
- this->is_builtin = false;
-}
-
-
-const char *
-ir_function_signature::qualifiers_match(exec_list *params)
-{
- exec_list_iterator iter_a = parameters.iterator();
- exec_list_iterator iter_b = params->iterator();
-
- /* check that the qualifiers match. */
- while (iter_a.has_next()) {
- ir_variable *a = (ir_variable *)iter_a.get();
- ir_variable *b = (ir_variable *)iter_b.get();
-
- if (a->read_only != b->read_only ||
- a->mode != b->mode ||
- a->interpolation != b->interpolation ||
- a->centroid != b->centroid) {
-
- /* parameter a's qualifiers don't match */
- return a->name;
- }
-
- iter_a.next();
- iter_b.next();
- }
- return NULL;
-}
-
-
-void
-ir_function_signature::replace_parameters(exec_list *new_params)
-{
- /* Destroy all of the previous parameter information. If the previous
- * parameter information comes from the function prototype, it may either
- * specify incorrect parameter names or not have names at all.
- */
- foreach_iter(exec_list_iterator, iter, parameters) {
- assert(((ir_instruction *) iter.get())->as_variable() != NULL);
-
- iter.remove();
- }
-
- new_params->move_nodes_to(&parameters);
-}
-
-
-ir_function::ir_function(const char *name)
-{
- this->ir_type = ir_type_function;
- this->name = talloc_strdup(this, name);
-}
-
-
-bool
-ir_function::has_user_signature()
-{
- foreach_list(n, &this->signatures) {
- ir_function_signature *const sig = (ir_function_signature *) n;
- if (!sig->is_builtin)
- return true;
- }
- return false;
-}
-
-
-ir_call *
-ir_call::get_error_instruction(void *ctx)
-{
- ir_call *call = new(ctx) ir_call;
-
- call->type = glsl_type::error_type;
- return call;
-}
-
-void
-ir_call::set_callee(ir_function_signature *sig)
-{
- assert((this->type == NULL) || (this->type == sig->return_type));
-
- this->callee = sig;
-}
-
-void
-visit_exec_list(exec_list *list, ir_visitor *visitor)
-{
- foreach_iter(exec_list_iterator, iter, *list) {
- ((ir_instruction *)iter.get())->accept(visitor);
- }
-}
-
-
-static void
-steal_memory(ir_instruction *ir, void *new_ctx)
-{
- ir_variable *var = ir->as_variable();
- ir_constant *constant = ir->as_constant();
- if (var != NULL && var->constant_value != NULL)
- steal_memory(var->constant_value, ir);
-
- /* The components of aggregate constants are not visited by the normal
- * visitor, so steal their values by hand.
- */
- if (constant != NULL) {
- if (constant->type->is_record()) {
- foreach_iter(exec_list_iterator, iter, constant->components) {
- ir_constant *field = (ir_constant *)iter.get();
- steal_memory(field, ir);
- }
- } else if (constant->type->is_array()) {
- for (unsigned int i = 0; i < constant->type->length; i++) {
- steal_memory(constant->array_elements[i], ir);
- }
- }
- }
-
- talloc_steal(new_ctx, ir);
-}
-
-
-void
-reparent_ir(exec_list *list, void *mem_ctx)
-{
- foreach_list(node, list) {
- visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
- }
-}
-
-
-static ir_rvalue *
-try_min_one(ir_rvalue *ir)
-{
- ir_expression *expr = ir->as_expression();
-
- if (!expr || expr->operation != ir_binop_min)
- return NULL;
-
- if (expr->operands[0]->is_one())
- return expr->operands[1];
-
- if (expr->operands[1]->is_one())
- return expr->operands[0];
-
- return NULL;
-}
-
-static ir_rvalue *
-try_max_zero(ir_rvalue *ir)
-{
- ir_expression *expr = ir->as_expression();
-
- if (!expr || expr->operation != ir_binop_max)
- return NULL;
-
- if (expr->operands[0]->is_zero())
- return expr->operands[1];
-
- if (expr->operands[1]->is_zero())
- return expr->operands[0];
-
- return NULL;
-}
-
-ir_rvalue *
-ir_rvalue::as_rvalue_to_saturate()
-{
- ir_expression *expr = this->as_expression();
-
- if (!expr)
- return NULL;
-
- ir_rvalue *max_zero = try_max_zero(expr);
- if (max_zero) {
- return try_min_one(max_zero);
- } else {
- ir_rvalue *min_one = try_min_one(expr);
- if (min_one) {
- return try_max_zero(min_one);
- }
- }
-
- return NULL;
-}
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 <string.h>
+#include "main/core.h" /* for MAX2 */
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+ir_rvalue::ir_rvalue()
+{
+ this->type = glsl_type::error_type;
+}
+
+bool ir_rvalue::is_zero() const
+{
+ return false;
+}
+
+bool ir_rvalue::is_one() const
+{
+ return false;
+}
+
+bool ir_rvalue::is_negative_one() const
+{
+ return false;
+}
+
+/**
+ * Modify the swizzle make to move one component to another
+ *
+ * \param m IR swizzle to be modified
+ * \param from Component in the RHS that is to be swizzled
+ * \param to Desired swizzle location of \c from
+ */
+static void
+update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to)
+{
+ switch (to) {
+ case 0: m.x = from; break;
+ case 1: m.y = from; break;
+ case 2: m.z = from; break;
+ case 3: m.w = from; break;
+ default: assert(!"Should not get here.");
+ }
+
+ m.num_components = MAX2(m.num_components, (to + 1));
+}
+
+void
+ir_assignment::set_lhs(ir_rvalue *lhs)
+{
+ void *mem_ctx = this;
+ bool swizzled = false;
+
+ while (lhs != NULL) {
+ ir_swizzle *swiz = lhs->as_swizzle();
+
+ if (swiz == NULL)
+ break;
+
+ unsigned write_mask = 0;
+ ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
+
+ for (unsigned i = 0; i < swiz->mask.num_components; i++) {
+ unsigned c = 0;
+
+ switch (i) {
+ case 0: c = swiz->mask.x; break;
+ case 1: c = swiz->mask.y; break;
+ case 2: c = swiz->mask.z; break;
+ case 3: c = swiz->mask.w; break;
+ default: assert(!"Should not get here.");
+ }
+
+ write_mask |= (((this->write_mask >> i) & 1) << c);
+ update_rhs_swizzle(rhs_swiz, i, c);
+ }
+
+ this->write_mask = write_mask;
+ lhs = swiz->val;
+
+ this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz);
+ swizzled = true;
+ }
+
+ if (swizzled) {
+ /* Now, RHS channels line up with the LHS writemask. Collapse it
+ * to just the channels that will be written.
+ */
+ ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
+ int rhs_chan = 0;
+ for (int i = 0; i < 4; i++) {
+ if (write_mask & (1 << i))
+ update_rhs_swizzle(rhs_swiz, i, rhs_chan++);
+ }
+ this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz);
+ }
+
+ assert((lhs == NULL) || lhs->as_dereference());
+
+ this->lhs = (ir_dereference *) lhs;
+}
+
+ir_variable *
+ir_assignment::whole_variable_written()
+{
+ ir_variable *v = this->lhs->whole_variable_referenced();
+
+ if (v == NULL)
+ return NULL;
+
+ if (v->type->is_scalar())
+ return v;
+
+ if (v->type->is_vector()) {
+ const unsigned mask = (1U << v->type->vector_elements) - 1;
+
+ if (mask != this->write_mask)
+ return NULL;
+ }
+
+ /* Either all the vector components are assigned or the variable is some
+ * composite type (and the whole thing is assigned.
+ */
+ return v;
+}
+
+ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
+ ir_rvalue *condition, unsigned write_mask)
+{
+ this->ir_type = ir_type_assignment;
+ this->condition = condition;
+ this->rhs = rhs;
+ this->lhs = lhs;
+ this->write_mask = write_mask;
+
+ if (lhs->type->is_scalar() || lhs->type->is_vector()) {
+ int lhs_components = 0;
+ for (int i = 0; i < 4; i++) {
+ if (write_mask & (1 << i))
+ lhs_components++;
+ }
+
+ assert(lhs_components == this->rhs->type->vector_elements);
+ }
+}
+
+ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
+ ir_rvalue *condition)
+{
+ this->ir_type = ir_type_assignment;
+ this->condition = condition;
+ this->rhs = rhs;
+
+ /* If the RHS is a vector type, assume that all components of the vector
+ * type are being written to the LHS. The write mask comes from the RHS
+ * because we can have a case where the LHS is a vec4 and the RHS is a
+ * vec3. In that case, the assignment is:
+ *
+ * (assign (...) (xyz) (var_ref lhs) (var_ref rhs))
+ */
+ if (rhs->type->is_vector())
+ this->write_mask = (1U << rhs->type->vector_elements) - 1;
+ else if (rhs->type->is_scalar())
+ this->write_mask = 1;
+ else
+ this->write_mask = 0;
+
+ this->set_lhs(lhs);
+}
+
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *op0)
+{
+ assert(get_num_operands(ir_expression_operation(op)) == 1);
+ this->ir_type = ir_type_expression;
+ this->type = type;
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = NULL;
+ this->operands[2] = NULL;
+ this->operands[3] = NULL;
+}
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *op0, ir_rvalue *op1)
+{
+ assert(((op1 == NULL) && (get_num_operands(ir_expression_operation(op)) == 1))
+ || (get_num_operands(ir_expression_operation(op)) == 2));
+ this->ir_type = ir_type_expression;
+ this->type = type;
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = op1;
+ this->operands[2] = NULL;
+ this->operands[3] = NULL;
+}
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *op0, ir_rvalue *op1,
+ ir_rvalue *op2, ir_rvalue *op3)
+{
+ this->ir_type = ir_type_expression;
+ this->type = type;
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = op1;
+ this->operands[2] = op2;
+ this->operands[3] = op3;
+}
+
+ir_expression::ir_expression(int op, ir_rvalue *op0)
+{
+ this->ir_type = ir_type_expression;
+
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = NULL;
+ this->operands[2] = NULL;
+ this->operands[3] = NULL;
+
+ assert(op <= ir_last_unop);
+
+ switch (this->operation) {
+ case ir_unop_bit_not:
+ case ir_unop_logic_not:
+ case ir_unop_neg:
+ case ir_unop_abs:
+ case ir_unop_sign:
+ case ir_unop_rcp:
+ case ir_unop_rsq:
+ case ir_unop_sqrt:
+ case ir_unop_exp:
+ case ir_unop_log:
+ case ir_unop_exp2:
+ case ir_unop_log2:
+ case ir_unop_trunc:
+ case ir_unop_ceil:
+ case ir_unop_floor:
+ case ir_unop_fract:
+ case ir_unop_round_even:
+ case ir_unop_sin:
+ case ir_unop_cos:
+ case ir_unop_sin_reduced:
+ case ir_unop_cos_reduced:
+ case ir_unop_dFdx:
+ case ir_unop_dFdy:
+ this->type = op0->type;
+ break;
+
+ case ir_unop_f2i:
+ case ir_unop_b2i:
+ this->type = glsl_type::get_instance(GLSL_TYPE_INT,
+ op0->type->vector_elements, 1);
+ break;
+
+ case ir_unop_b2f:
+ case ir_unop_i2f:
+ case ir_unop_u2f:
+ this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+ op0->type->vector_elements, 1);
+ break;
+
+ case ir_unop_f2b:
+ case ir_unop_i2b:
+ this->type = glsl_type::get_instance(GLSL_TYPE_BOOL,
+ op0->type->vector_elements, 1);
+ break;
+
+ case ir_unop_noise:
+ this->type = glsl_type::float_type;
+ break;
+
+ case ir_unop_any:
+ this->type = glsl_type::bool_type;
+ break;
+
+ default:
+ assert(!"not reached: missing automatic type setup for ir_expression");
+ this->type = op0->type;
+ break;
+ }
+}
+
+ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
+{
+ this->ir_type = ir_type_expression;
+
+ this->operation = ir_expression_operation(op);
+ this->operands[0] = op0;
+ this->operands[1] = op1;
+ this->operands[2] = NULL;
+ this->operands[3] = NULL;
+
+ assert(op > ir_last_unop);
+
+ switch (this->operation) {
+ case ir_binop_all_equal:
+ case ir_binop_any_nequal:
+ this->type = glsl_type::bool_type;
+ break;
+
+ case ir_binop_add:
+ case ir_binop_sub:
+ case ir_binop_min:
+ case ir_binop_max:
+ case ir_binop_pow:
+ case ir_binop_mul:
+ case ir_binop_div:
+ case ir_binop_mod:
+ if (op0->type->is_scalar()) {
+ this->type = op1->type;
+ } else if (op1->type->is_scalar()) {
+ this->type = op0->type;
+ } else {
+ /* FINISHME: matrix types */
+ assert(!op0->type->is_matrix() && !op1->type->is_matrix());
+ assert(op0->type == op1->type);
+ this->type = op0->type;
+ }
+ break;
+
+ case ir_binop_logic_and:
+ case ir_binop_logic_xor:
+ case ir_binop_logic_or:
+ case ir_binop_bit_and:
+ case ir_binop_bit_xor:
+ case ir_binop_bit_or:
+ if (op0->type->is_scalar()) {
+ this->type = op1->type;
+ } else if (op1->type->is_scalar()) {
+ this->type = op0->type;
+ }
+ break;
+
+ case ir_binop_equal:
+ case ir_binop_nequal:
+ case ir_binop_lequal:
+ case ir_binop_gequal:
+ case ir_binop_less:
+ case ir_binop_greater:
+ assert(op0->type == op1->type);
+ this->type = glsl_type::get_instance(GLSL_TYPE_BOOL,
+ op0->type->vector_elements, 1);
+ break;
+
+ case ir_binop_dot:
+ this->type = glsl_type::float_type;
+ break;
+
+ case ir_binop_lshift:
+ case ir_binop_rshift:
+ this->type = op0->type;
+ break;
+
+ default:
+ assert(!"not reached: missing automatic type setup for ir_expression");
+ this->type = glsl_type::float_type;
+ }
+}
+
+unsigned int
+ir_expression::get_num_operands(ir_expression_operation op)
+{
+ assert(op <= ir_last_opcode);
+
+ if (op <= ir_last_unop)
+ return 1;
+
+ if (op <= ir_last_binop)
+ return 2;
+
+ if (op == ir_quadop_vector)
+ return 4;
+
+ assert(false);
+ return 0;
+}
+
+static const char *const operator_strs[] = {
+ "~",
+ "!",
+ "neg",
+ "abs",
+ "sign",
+ "rcp",
+ "rsq",
+ "sqrt",
+ "exp",
+ "log",
+ "exp2",
+ "log2",
+ "f2i",
+ "i2f",
+ "f2b",
+ "b2f",
+ "i2b",
+ "b2i",
+ "u2f",
+ "any",
+ "trunc",
+ "ceil",
+ "floor",
+ "fract",
+ "round_even",
+ "sin",
+ "cos",
+ "sin_reduced",
+ "cos_reduced",
+ "dFdx",
+ "dFdy",
+ "noise",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "<",
+ ">",
+ "<=",
+ ">=",
+ "==",
+ "!=",
+ "all_equal",
+ "any_nequal",
+ "<<",
+ ">>",
+ "&",
+ "^",
+ "|",
+ "&&",
+ "^^",
+ "||",
+ "dot",
+ "min",
+ "max",
+ "pow",
+ "vector",
+};
+
+const char *ir_expression::operator_string(ir_expression_operation op)
+{
+ assert((unsigned int) op < Elements(operator_strs));
+ assert(Elements(operator_strs) == (ir_quadop_vector + 1));
+ return operator_strs[op];
+}
+
+const char *ir_expression::operator_string()
+{
+ return operator_string(this->operation);
+}
+
+const char*
+depth_layout_string(ir_depth_layout layout)
+{
+ switch(layout) {
+ case ir_depth_layout_none: return "";
+ case ir_depth_layout_any: return "depth_any";
+ case ir_depth_layout_greater: return "depth_greater";
+ case ir_depth_layout_less: return "depth_less";
+ case ir_depth_layout_unchanged: return "depth_unchanged";
+
+ default:
+ assert(0);
+ return "";
+ }
+}
+
+ir_expression_operation
+ir_expression::get_operator(const char *str)
+{
+ const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]);
+ for (int op = 0; op < operator_count; op++) {
+ if (strcmp(str, operator_strs[op]) == 0)
+ return (ir_expression_operation) op;
+ }
+ return (ir_expression_operation) -1;
+}
+
+ir_constant::ir_constant()
+{
+ this->ir_type = ir_type_constant;
+}
+
+ir_constant::ir_constant(const struct glsl_type *type,
+ const ir_constant_data *data)
+{
+ assert((type->base_type >= GLSL_TYPE_UINT)
+ && (type->base_type <= GLSL_TYPE_BOOL));
+
+ this->ir_type = ir_type_constant;
+ this->type = type;
+ memcpy(& this->value, data, sizeof(this->value));
+}
+
+ir_constant::ir_constant(float f)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::float_type;
+ this->value.f[0] = f;
+ for (int i = 1; i < 16; i++) {
+ this->value.f[i] = 0;
+ }
+}
+
+ir_constant::ir_constant(unsigned int u)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::uint_type;
+ this->value.u[0] = u;
+ for (int i = 1; i < 16; i++) {
+ this->value.u[i] = 0;
+ }
+}
+
+ir_constant::ir_constant(int i)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::int_type;
+ this->value.i[0] = i;
+ for (int i = 1; i < 16; i++) {
+ this->value.i[i] = 0;
+ }
+}
+
+ir_constant::ir_constant(bool b)
+{
+ this->ir_type = ir_type_constant;
+ this->type = glsl_type::bool_type;
+ this->value.b[0] = b;
+ for (int i = 1; i < 16; i++) {
+ this->value.b[i] = false;
+ }
+}
+
+ir_constant::ir_constant(const ir_constant *c, unsigned i)
+{
+ this->ir_type = ir_type_constant;
+ this->type = c->type->get_base_type();
+
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break;
+ case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break;
+ case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
+ case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break;
+ default: assert(!"Should not get here."); break;
+ }
+}
+
+ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
+{
+ this->ir_type = ir_type_constant;
+ this->type = type;
+
+ assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+ || type->is_record() || type->is_array());
+
+ if (type->is_array()) {
+ this->array_elements = talloc_array(this, ir_constant *, type->length);
+ unsigned i = 0;
+ foreach_list(node, value_list) {
+ ir_constant *value = (ir_constant *) node;
+ assert(value->as_constant() != NULL);
+
+ this->array_elements[i++] = value;
+ }
+ return;
+ }
+
+ /* If the constant is a record, the types of each of the entries in
+ * value_list must be a 1-for-1 match with the structure components. Each
+ * entry must also be a constant. Just move the nodes from the value_list
+ * to the list in the ir_constant.
+ */
+ /* FINISHME: Should there be some type checking and / or assertions here? */
+ /* FINISHME: Should the new constant take ownership of the nodes from
+ * FINISHME: value_list, or should it make copies?
+ */
+ if (type->is_record()) {
+ value_list->move_nodes_to(& this->components);
+ return;
+ }
+
+ for (unsigned i = 0; i < 16; i++) {
+ this->value.u[i] = 0;
+ }
+
+ ir_constant *value = (ir_constant *) (value_list->head);
+
+ /* Constructors with exactly one scalar argument are special for vectors
+ * and matrices. For vectors, the scalar value is replicated to fill all
+ * the components. For matrices, the scalar fills the components of the
+ * diagonal while the rest is filled with 0.
+ */
+ if (value->type->is_scalar() && value->next->is_tail_sentinel()) {
+ if (type->is_matrix()) {
+ /* Matrix - fill diagonal (rest is already set to 0) */
+ assert(type->base_type == GLSL_TYPE_FLOAT);
+ for (unsigned i = 0; i < type->matrix_columns; i++)
+ this->value.f[i * type->vector_elements + i] = value->value.f[0];
+ } else {
+ /* Vector or scalar - fill all components */
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ for (unsigned i = 0; i < type->components(); i++)
+ this->value.u[i] = value->value.u[0];
+ break;
+ case GLSL_TYPE_FLOAT:
+ for (unsigned i = 0; i < type->components(); i++)
+ this->value.f[i] = value->value.f[0];
+ break;
+ case GLSL_TYPE_BOOL:
+ for (unsigned i = 0; i < type->components(); i++)
+ this->value.b[i] = value->value.b[0];
+ break;
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ }
+ return;
+ }
+
+ if (type->is_matrix() && value->type->is_matrix()) {
+ assert(value->next->is_tail_sentinel());
+
+ /* From section 5.4.2 of the GLSL 1.20 spec:
+ * "If a matrix is constructed from a matrix, then each component
+ * (column i, row j) in the result that has a corresponding component
+ * (column i, row j) in the argument will be initialized from there."
+ */
+ unsigned cols = MIN2(type->matrix_columns, value->type->matrix_columns);
+ unsigned rows = MIN2(type->vector_elements, value->type->vector_elements);
+ for (unsigned i = 0; i < cols; i++) {
+ for (unsigned j = 0; j < rows; j++) {
+ const unsigned src = i * value->type->vector_elements + j;
+ const unsigned dst = i * type->vector_elements + j;
+ this->value.f[dst] = value->value.f[src];
+ }
+ }
+
+ /* "All other components will be initialized to the identity matrix." */
+ for (unsigned i = cols; i < type->matrix_columns; i++)
+ this->value.f[i * type->vector_elements + i] = 1.0;
+
+ return;
+ }
+
+ /* Use each component from each entry in the value_list to initialize one
+ * component of the constant being constructed.
+ */
+ for (unsigned i = 0; i < type->components(); /* empty */) {
+ assert(value->as_constant() != NULL);
+ assert(!value->is_tail_sentinel());
+
+ for (unsigned j = 0; j < value->type->components(); j++) {
+ switch (type->base_type) {
+ case GLSL_TYPE_UINT:
+ this->value.u[i] = value->get_uint_component(j);
+ break;
+ case GLSL_TYPE_INT:
+ this->value.i[i] = value->get_int_component(j);
+ break;
+ case GLSL_TYPE_FLOAT:
+ this->value.f[i] = value->get_float_component(j);
+ break;
+ case GLSL_TYPE_BOOL:
+ this->value.b[i] = value->get_bool_component(j);
+ break;
+ default:
+ /* FINISHME: What to do? Exceptions are not the answer.
+ */
+ break;
+ }
+
+ i++;
+ if (i >= type->components())
+ break;
+ }
+
+ value = (ir_constant *) value->next;
+ }
+}
+
+ir_constant *
+ir_constant::zero(void *mem_ctx, const glsl_type *type)
+{
+ assert(type->is_numeric() || type->is_boolean());
+
+ ir_constant *c = new(mem_ctx) ir_constant;
+ c->type = type;
+ memset(&c->value, 0, sizeof(c->value));
+
+ return c;
+}
+
+bool
+ir_constant::get_bool_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i] != 0;
+ case GLSL_TYPE_INT: return this->value.i[i] != 0;
+ case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
+ case GLSL_TYPE_BOOL: return this->value.b[i];
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return false;
+}
+
+float
+ir_constant::get_float_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return (float) this->value.u[i];
+ case GLSL_TYPE_INT: return (float) this->value.i[i];
+ case GLSL_TYPE_FLOAT: return this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0.0;
+}
+
+int
+ir_constant::get_int_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
+
+unsigned
+ir_constant::get_uint_component(unsigned i) const
+{
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT: return this->value.u[i];
+ case GLSL_TYPE_INT: return this->value.i[i];
+ case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
+ case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0;
+ default: assert(!"Should not get here."); break;
+ }
+
+ /* Must return something to make the compiler happy. This is clearly an
+ * error case.
+ */
+ return 0;
+}
+
+ir_constant *
+ir_constant::get_array_element(unsigned i) const
+{
+ assert(this->type->is_array());
+
+ /* From page 35 (page 41 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "Behavior is undefined if a shader subscripts an array with an index
+ * less than 0 or greater than or equal to the size the array was
+ * declared with."
+ *
+ * Most out-of-bounds accesses are removed before things could get this far.
+ * There are cases where non-constant array index values can get constant
+ * folded.
+ */
+ if (int(i) < 0)
+ i = 0;
+ else if (i >= this->type->length)
+ i = this->type->length - 1;
+
+ return array_elements[i];
+}
+
+ir_constant *
+ir_constant::get_record_field(const char *name)
+{
+ int idx = this->type->field_index(name);
+
+ if (idx < 0)
+ return NULL;
+
+ if (this->components.is_empty())
+ return NULL;
+
+ exec_node *node = this->components.head;
+ for (int i = 0; i < idx; i++) {
+ node = node->next;
+
+ /* If the end of the list is encountered before the element matching the
+ * requested field is found, return NULL.
+ */
+ if (node->is_tail_sentinel())
+ return NULL;
+ }
+
+ return (ir_constant *) node;
+}
+
+
+bool
+ir_constant::has_value(const ir_constant *c) const
+{
+ if (this->type != c->type)
+ return false;
+
+ if (this->type->is_array()) {
+ for (unsigned i = 0; i < this->type->length; i++) {
+ if (!this->array_elements[i]->has_value(c->array_elements[i]))
+ return false;
+ }
+ return true;
+ }
+
+ if (this->type->base_type == GLSL_TYPE_STRUCT) {
+ const exec_node *a_node = this->components.head;
+ const exec_node *b_node = c->components.head;
+
+ while (!a_node->is_tail_sentinel()) {
+ assert(!b_node->is_tail_sentinel());
+
+ const ir_constant *const a_field = (ir_constant *) a_node;
+ const ir_constant *const b_field = (ir_constant *) b_node;
+
+ if (!a_field->has_value(b_field))
+ return false;
+
+ a_node = a_node->next;
+ b_node = b_node->next;
+ }
+
+ return true;
+ }
+
+ for (unsigned i = 0; i < this->type->components(); i++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_UINT:
+ if (this->value.u[i] != c->value.u[i])
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (this->value.i[i] != c->value.i[i])
+ return false;
+ break;
+ case GLSL_TYPE_FLOAT:
+ if (this->value.f[i] != c->value.f[i])
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (this->value.b[i] != c->value.b[i])
+ return false;
+ break;
+ default:
+ assert(!"Should not get here.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+ir_constant::is_zero() const
+{
+ if (!this->type->is_scalar() && !this->type->is_vector())
+ return false;
+
+ for (unsigned c = 0; c < this->type->vector_elements; c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ if (this->value.f[c] != 0.0)
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (this->value.i[c] != 0)
+ return false;
+ break;
+ case GLSL_TYPE_UINT:
+ if (this->value.u[c] != 0)
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (this->value.b[c] != false)
+ return false;
+ break;
+ default:
+ /* The only other base types are structures, arrays, and samplers.
+ * Samplers cannot be constants, and the others should have been
+ * filtered out above.
+ */
+ assert(!"Should not get here.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+ir_constant::is_one() const
+{
+ if (!this->type->is_scalar() && !this->type->is_vector())
+ return false;
+
+ for (unsigned c = 0; c < this->type->vector_elements; c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ if (this->value.f[c] != 1.0)
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (this->value.i[c] != 1)
+ return false;
+ break;
+ case GLSL_TYPE_UINT:
+ if (this->value.u[c] != 1)
+ return false;
+ break;
+ case GLSL_TYPE_BOOL:
+ if (this->value.b[c] != true)
+ return false;
+ break;
+ default:
+ /* The only other base types are structures, arrays, and samplers.
+ * Samplers cannot be constants, and the others should have been
+ * filtered out above.
+ */
+ assert(!"Should not get here.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+ir_constant::is_negative_one() const
+{
+ if (!this->type->is_scalar() && !this->type->is_vector())
+ return false;
+
+ if (this->type->is_boolean())
+ return false;
+
+ for (unsigned c = 0; c < this->type->vector_elements; c++) {
+ switch (this->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ if (this->value.f[c] != -1.0)
+ return false;
+ break;
+ case GLSL_TYPE_INT:
+ if (this->value.i[c] != -1)
+ return false;
+ break;
+ case GLSL_TYPE_UINT:
+ if (int(this->value.u[c]) != -1)
+ return false;
+ break;
+ default:
+ /* The only other base types are structures, arrays, samplers, and
+ * booleans. Samplers cannot be constants, and the others should
+ * have been filtered out above.
+ */
+ assert(!"Should not get here.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+ir_loop::ir_loop()
+{
+ this->ir_type = ir_type_loop;
+ this->cmp = ir_unop_neg;
+ this->from = NULL;
+ this->to = NULL;
+ this->increment = NULL;
+ this->counter = NULL;
+}
+
+
+ir_dereference_variable::ir_dereference_variable(ir_variable *var)
+{
+ this->ir_type = ir_type_dereference_variable;
+ this->var = var;
+ this->type = (var != NULL) ? var->type : glsl_type::error_type;
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_rvalue *value,
+ ir_rvalue *array_index)
+{
+ this->ir_type = ir_type_dereference_array;
+ this->array_index = array_index;
+ this->set_array(value);
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_variable *var,
+ ir_rvalue *array_index)
+{
+ void *ctx = talloc_parent(var);
+
+ this->ir_type = ir_type_dereference_array;
+ this->array_index = array_index;
+ this->set_array(new(ctx) ir_dereference_variable(var));
+}
+
+
+void
+ir_dereference_array::set_array(ir_rvalue *value)
+{
+ this->array = value;
+ this->type = glsl_type::error_type;
+
+ if (this->array != NULL) {
+ const glsl_type *const vt = this->array->type;
+
+ if (vt->is_array()) {
+ type = vt->element_type();
+ } else if (vt->is_matrix()) {
+ type = vt->column_type();
+ } else if (vt->is_vector()) {
+ type = vt->get_base_type();
+ }
+ }
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_rvalue *value,
+ const char *field)
+{
+ this->ir_type = ir_type_dereference_record;
+ this->record = value;
+ this->field = talloc_strdup(this, field);
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_variable *var,
+ const char *field)
+{
+ void *ctx = talloc_parent(var);
+
+ this->ir_type = ir_type_dereference_record;
+ this->record = new(ctx) ir_dereference_variable(var);
+ this->field = talloc_strdup(this, field);
+ this->type = (this->record != NULL)
+ ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+bool type_contains_sampler(const glsl_type *type)
+{
+ if (type->is_array()) {
+ return type_contains_sampler(type->fields.array);
+ } else if (type->is_record()) {
+ for (unsigned int i = 0; i < type->length; i++) {
+ if (type_contains_sampler(type->fields.structure[i].type))
+ return true;
+ }
+ return false;
+ } else {
+ return type->is_sampler();
+ }
+}
+
+bool
+ir_dereference::is_lvalue()
+{
+ ir_variable *var = this->variable_referenced();
+
+ /* Every l-value derference chain eventually ends in a variable.
+ */
+ if ((var == NULL) || var->read_only)
+ return false;
+
+ if (this->type->is_array() && !var->array_lvalue)
+ return false;
+
+ /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
+ *
+ * "Samplers cannot be treated as l-values; hence cannot be used
+ * as out or inout function parameters, nor can they be
+ * assigned into."
+ */
+ if (type_contains_sampler(this->type))
+ return false;
+
+ return true;
+}
+
+
+const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" };
+
+const char *ir_texture::opcode_string()
+{
+ assert((unsigned int) op <=
+ sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]));
+ return tex_opcode_strs[op];
+}
+
+ir_texture_opcode
+ir_texture::get_opcode(const char *str)
+{
+ const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]);
+ for (int op = 0; op < count; op++) {
+ if (strcmp(str, tex_opcode_strs[op]) == 0)
+ return (ir_texture_opcode) op;
+ }
+ return (ir_texture_opcode) -1;
+}
+
+
+void
+ir_texture::set_sampler(ir_dereference *sampler)
+{
+ assert(sampler != NULL);
+ this->sampler = sampler;
+
+ switch (sampler->type->sampler_type) {
+ case GLSL_TYPE_FLOAT:
+ this->type = glsl_type::vec4_type;
+ break;
+ case GLSL_TYPE_INT:
+ this->type = glsl_type::ivec4_type;
+ break;
+ case GLSL_TYPE_UINT:
+ this->type = glsl_type::uvec4_type;
+ break;
+ }
+}
+
+
+void
+ir_swizzle::init_mask(const unsigned *comp, unsigned count)
+{
+ assert((count >= 1) && (count <= 4));
+
+ memset(&this->mask, 0, sizeof(this->mask));
+ this->mask.num_components = count;
+
+ unsigned dup_mask = 0;
+ switch (count) {
+ case 4:
+ assert(comp[3] <= 3);
+ dup_mask |= (1U << comp[3])
+ & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2]));
+ this->mask.w = comp[3];
+
+ case 3:
+ assert(comp[2] <= 3);
+ dup_mask |= (1U << comp[2])
+ & ((1U << comp[0]) | (1U << comp[1]));
+ this->mask.z = comp[2];
+
+ case 2:
+ assert(comp[1] <= 3);
+ dup_mask |= (1U << comp[1])
+ & ((1U << comp[0]));
+ this->mask.y = comp[1];
+
+ case 1:
+ assert(comp[0] <= 3);
+ this->mask.x = comp[0];
+ }
+
+ this->mask.has_duplicates = dup_mask != 0;
+
+ /* Based on the number of elements in the swizzle and the base type
+ * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
+ * generate the type of the resulting value.
+ */
+ type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
+ unsigned w, unsigned count)
+ : val(val)
+{
+ const unsigned components[4] = { x, y, z, w };
+ this->ir_type = ir_type_swizzle;
+ this->init_mask(components, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
+ unsigned count)
+ : val(val)
+{
+ this->ir_type = ir_type_swizzle;
+ this->init_mask(comp, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
+{
+ this->ir_type = ir_type_swizzle;
+ this->val = val;
+ this->mask = mask;
+ this->type = glsl_type::get_instance(val->type->base_type,
+ mask.num_components, 1);
+}
+
+#define X 1
+#define R 5
+#define S 9
+#define I 13
+
+ir_swizzle *
+ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
+{
+ void *ctx = talloc_parent(val);
+
+ /* For each possible swizzle character, this table encodes the value in
+ * \c idx_map that represents the 0th element of the vector. For invalid
+ * swizzle characters (e.g., 'k'), a special value is used that will allow
+ * detection of errors.
+ */
+ static const unsigned char base_idx[26] = {
+ /* a b c d e f g h i j k l m */
+ R, R, I, I, I, I, R, I, I, I, I, I, I,
+ /* n o p q r s t u v w x y z */
+ I, I, S, S, R, S, S, I, I, X, X, X, X
+ };
+
+ /* Each valid swizzle character has an entry in the previous table. This
+ * table encodes the base index encoded in the previous table plus the actual
+ * index of the swizzle character. When processing swizzles, the first
+ * character in the string is indexed in the previous table. Each character
+ * in the string is indexed in this table, and the value found there has the
+ * value form the first table subtracted. The result must be on the range
+ * [0,3].
+ *
+ * For example, the string "wzyx" will get X from the first table. Each of
+ * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
+ * subtraction, the swizzle values are { 3, 2, 1, 0 }.
+ *
+ * The string "wzrg" will get X from the first table. Each of the characters
+ * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
+ * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
+ * [0,3], the error is detected.
+ */
+ static const unsigned char idx_map[26] = {
+ /* a b c d e f g h i j k l m */
+ R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
+ /* n o p q r s t u v w x y z */
+ 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
+ };
+
+ int swiz_idx[4] = { 0, 0, 0, 0 };
+ unsigned i;
+
+
+ /* Validate the first character in the swizzle string and look up the base
+ * index value as described above.
+ */
+ if ((str[0] < 'a') || (str[0] > 'z'))
+ return NULL;
+
+ const unsigned base = base_idx[str[0] - 'a'];
+
+
+ for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
+ /* Validate the next character, and, as described above, convert it to a
+ * swizzle index.
+ */
+ if ((str[i] < 'a') || (str[i] > 'z'))
+ return NULL;
+
+ swiz_idx[i] = idx_map[str[i] - 'a'] - base;
+ if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
+ return NULL;
+ }
+
+ if (str[i] != '\0')
+ return NULL;
+
+ return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
+ swiz_idx[3], i);
+}
+
+#undef X
+#undef R
+#undef S
+#undef I
+
+ir_variable *
+ir_swizzle::variable_referenced()
+{
+ return this->val->variable_referenced();
+}
+
+
+ir_variable::ir_variable(const struct glsl_type *type, const char *name,
+ ir_variable_mode mode)
+ : max_array_access(0), read_only(false), centroid(false), invariant(false),
+ mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
+{
+ this->ir_type = ir_type_variable;
+ this->type = type;
+ this->name = talloc_strdup(this, name);
+ this->explicit_location = false;
+ this->location = -1;
+ this->warn_extension = NULL;
+ this->constant_value = NULL;
+ this->origin_upper_left = false;
+ this->pixel_center_integer = false;
+ this->depth_layout = ir_depth_layout_none;
+ this->used = false;
+
+ if (type && type->base_type == GLSL_TYPE_SAMPLER)
+ this->read_only = true;
+}
+
+
+const char *
+ir_variable::interpolation_string() const
+{
+ switch (this->interpolation) {
+ case ir_var_smooth: return "smooth";
+ case ir_var_flat: return "flat";
+ case ir_var_noperspective: return "noperspective";
+ }
+
+ assert(!"Should not get here.");
+ return "";
+}
+
+
+unsigned
+ir_variable::component_slots() const
+{
+ /* FINISHME: Sparsely accessed arrays require fewer slots. */
+ return this->type->component_slots();
+}
+
+
+ir_function_signature::ir_function_signature(const glsl_type *return_type)
+ : return_type(return_type), is_defined(false), _function(NULL)
+{
+ this->ir_type = ir_type_function_signature;
+ this->is_builtin = false;
+}
+
+
+const char *
+ir_function_signature::qualifiers_match(exec_list *params)
+{
+ exec_list_iterator iter_a = parameters.iterator();
+ exec_list_iterator iter_b = params->iterator();
+
+ /* check that the qualifiers match. */
+ while (iter_a.has_next()) {
+ ir_variable *a = (ir_variable *)iter_a.get();
+ ir_variable *b = (ir_variable *)iter_b.get();
+
+ if (a->read_only != b->read_only ||
+ a->mode != b->mode ||
+ a->interpolation != b->interpolation ||
+ a->centroid != b->centroid) {
+
+ /* parameter a's qualifiers don't match */
+ return a->name;
+ }
+
+ iter_a.next();
+ iter_b.next();
+ }
+ return NULL;
+}
+
+
+void
+ir_function_signature::replace_parameters(exec_list *new_params)
+{
+ /* Destroy all of the previous parameter information. If the previous
+ * parameter information comes from the function prototype, it may either
+ * specify incorrect parameter names or not have names at all.
+ */
+ foreach_iter(exec_list_iterator, iter, parameters) {
+ assert(((ir_instruction *) iter.get())->as_variable() != NULL);
+
+ iter.remove();
+ }
+
+ new_params->move_nodes_to(&parameters);
+}
+
+
+ir_function::ir_function(const char *name)
+{
+ this->ir_type = ir_type_function;
+ this->name = talloc_strdup(this, name);
+}
+
+
+bool
+ir_function::has_user_signature()
+{
+ foreach_list(n, &this->signatures) {
+ ir_function_signature *const sig = (ir_function_signature *) n;
+ if (!sig->is_builtin)
+ return true;
+ }
+ return false;
+}
+
+
+ir_call *
+ir_call::get_error_instruction(void *ctx)
+{
+ ir_call *call = new(ctx) ir_call;
+
+ call->type = glsl_type::error_type;
+ return call;
+}
+
+void
+ir_call::set_callee(ir_function_signature *sig)
+{
+ assert((this->type == NULL) || (this->type == sig->return_type));
+
+ this->callee = sig;
+}
+
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor)
+{
+ foreach_iter(exec_list_iterator, iter, *list) {
+ ((ir_instruction *)iter.get())->accept(visitor);
+ }
+}
+
+
+static void
+steal_memory(ir_instruction *ir, void *new_ctx)
+{
+ ir_variable *var = ir->as_variable();
+ ir_constant *constant = ir->as_constant();
+ if (var != NULL && var->constant_value != NULL)
+ steal_memory(var->constant_value, ir);
+
+ /* The components of aggregate constants are not visited by the normal
+ * visitor, so steal their values by hand.
+ */
+ if (constant != NULL) {
+ if (constant->type->is_record()) {
+ foreach_iter(exec_list_iterator, iter, constant->components) {
+ ir_constant *field = (ir_constant *)iter.get();
+ steal_memory(field, ir);
+ }
+ } else if (constant->type->is_array()) {
+ for (unsigned int i = 0; i < constant->type->length; i++) {
+ steal_memory(constant->array_elements[i], ir);
+ }
+ }
+ }
+
+ talloc_steal(new_ctx, ir);
+}
+
+
+void
+reparent_ir(exec_list *list, void *mem_ctx)
+{
+ foreach_list(node, list) {
+ visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
+ }
+}
+
+
+static ir_rvalue *
+try_min_one(ir_rvalue *ir)
+{
+ ir_expression *expr = ir->as_expression();
+
+ if (!expr || expr->operation != ir_binop_min)
+ return NULL;
+
+ if (expr->operands[0]->is_one())
+ return expr->operands[1];
+
+ if (expr->operands[1]->is_one())
+ return expr->operands[0];
+
+ return NULL;
+}
+
+static ir_rvalue *
+try_max_zero(ir_rvalue *ir)
+{
+ ir_expression *expr = ir->as_expression();
+
+ if (!expr || expr->operation != ir_binop_max)
+ return NULL;
+
+ if (expr->operands[0]->is_zero())
+ return expr->operands[1];
+
+ if (expr->operands[1]->is_zero())
+ return expr->operands[0];
+
+ return NULL;
+}
+
+ir_rvalue *
+ir_rvalue::as_rvalue_to_saturate()
+{
+ ir_expression *expr = this->as_expression();
+
+ if (!expr)
+ return NULL;
+
+ ir_rvalue *max_zero = try_max_zero(expr);
+ if (max_zero) {
+ return try_min_one(max_zero);
+ } else {
+ ir_rvalue *min_one = try_min_one(expr);
+ if (min_one) {
+ return try_max_zero(min_one);
+ }
+ }
+
+ return NULL;
+}
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 643fbf7c5..8d5056aa1 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -1,1615 +1,1642 @@
-/* -*- c++ -*- */
-/*
- * Copyright © 2010 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#pragma once
-#ifndef IR_H
-#define IR_H
-
-#include <cstdio>
-#include <cstdlib>
-
-extern "C" {
-#include <talloc.h>
-}
-
-#include "glsl_types.h"
-#include "list.h"
-#include "ir_visitor.h"
-#include "ir_hierarchical_visitor.h"
-
-/**
- * \defgroup IR Intermediate representation nodes
- *
- * @{
- */
-
-/**
- * Class tags
- *
- * Each concrete class derived from \c ir_instruction has a value in this
- * enumerant. The value for the type is stored in \c ir_instruction::ir_type
- * by the constructor. While using type tags is not very C++, it is extremely
- * convenient. For example, during debugging you can simply inspect
- * \c ir_instruction::ir_type to find out the actual type of the object.
- *
- * In addition, it is possible to use a switch-statement based on \c
- * \c ir_instruction::ir_type to select different behavior for different object
- * types. For functions that have only slight differences for several object
- * types, this allows writing very straightforward, readable code.
- */
-enum ir_node_type {
- /**
- * Zero is unused so that the IR validator can detect cases where
- * \c ir_instruction::ir_type has not been initialized.
- */
- ir_type_unset,
- ir_type_variable,
- ir_type_assignment,
- ir_type_call,
- ir_type_constant,
- ir_type_dereference_array,
- ir_type_dereference_record,
- ir_type_dereference_variable,
- ir_type_discard,
- ir_type_expression,
- ir_type_function,
- ir_type_function_signature,
- ir_type_if,
- ir_type_loop,
- ir_type_loop_jump,
- ir_type_return,
- ir_type_swizzle,
- ir_type_texture,
- ir_type_max /**< maximum ir_type enum number, for validation */
-};
-
-/**
- * Base class of all IR instructions
- */
-class ir_instruction : public exec_node {
-public:
- enum ir_node_type ir_type;
- const struct glsl_type *type;
-
- /** ir_print_visitor helper for debugging. */
- void print(void) const;
-
- virtual void accept(ir_visitor *) = 0;
- virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
- virtual ir_instruction *clone(void *mem_ctx,
- struct hash_table *ht) const = 0;
-
- /**
- * \name IR instruction downcast functions
- *
- * These functions either cast the object to a derived class or return
- * \c NULL if the object's type does not match the specified derived class.
- * Additional downcast functions will be added as needed.
- */
- /*@{*/
- virtual class ir_variable * as_variable() { return NULL; }
- virtual class ir_function * as_function() { return NULL; }
- virtual class ir_dereference * as_dereference() { return NULL; }
- virtual class ir_dereference_array * as_dereference_array() { return NULL; }
- virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
- virtual class ir_expression * as_expression() { return NULL; }
- virtual class ir_rvalue * as_rvalue() { return NULL; }
- virtual class ir_loop * as_loop() { return NULL; }
- virtual class ir_assignment * as_assignment() { return NULL; }
- virtual class ir_call * as_call() { return NULL; }
- virtual class ir_return * as_return() { return NULL; }
- virtual class ir_if * as_if() { return NULL; }
- virtual class ir_swizzle * as_swizzle() { return NULL; }
- virtual class ir_constant * as_constant() { return NULL; }
- virtual class ir_discard * as_discard() { return NULL; }
- /*@}*/
-
-protected:
- ir_instruction()
- {
- ir_type = ir_type_unset;
- type = NULL;
- }
-};
-
-
-class ir_rvalue : public ir_instruction {
-public:
- virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
-
- virtual ir_constant *constant_expression_value() = 0;
-
- virtual ir_rvalue * as_rvalue()
- {
- return this;
- }
-
- ir_rvalue *as_rvalue_to_saturate();
-
- virtual bool is_lvalue()
- {
- return false;
- }
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced()
- {
- return NULL;
- }
-
-
- /**
- * If an r-value is a reference to a whole variable, get that variable
- *
- * \return
- * Pointer to a variable that is completely dereferenced by the r-value. If
- * the r-value is not a dereference or the dereference does not access the
- * entire variable (i.e., it's just one array element, struct field), \c NULL
- * is returned.
- */
- virtual ir_variable *whole_variable_referenced()
- {
- return NULL;
- }
-
- /**
- * Determine if an r-value has the value zero
- *
- * The base implementation of this function always returns \c false. The
- * \c ir_constant class over-rides this function to return \c true \b only
- * for vector and scalar types that have all elements set to the value
- * zero (or \c false for booleans).
- *
- * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one
- */
- virtual bool is_zero() const;
-
- /**
- * Determine if an r-value has the value one
- *
- * The base implementation of this function always returns \c false. The
- * \c ir_constant class over-rides this function to return \c true \b only
- * for vector and scalar types that have all elements set to the value
- * one (or \c true for booleans).
- *
- * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one
- */
- virtual bool is_one() const;
-
- /**
- * Determine if an r-value has the value negative one
- *
- * The base implementation of this function always returns \c false. The
- * \c ir_constant class over-rides this function to return \c true \b only
- * for vector and scalar types that have all elements set to the value
- * negative one. For boolean times, the result is always \c false.
- *
- * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
- */
- virtual bool is_negative_one() const;
-
-protected:
- ir_rvalue();
-};
-
-
-/**
- * Variable storage classes
- */
-enum ir_variable_mode {
- ir_var_auto = 0, /**< Function local variables and globals. */
- ir_var_uniform, /**< Variable declared as a uniform. */
- ir_var_in,
- ir_var_out,
- ir_var_inout,
- ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
- ir_var_temporary /**< Temporary variable generated during compilation. */
-};
-
-enum ir_variable_interpolation {
- ir_var_smooth = 0,
- ir_var_flat,
- ir_var_noperspective
-};
-
-
-class ir_variable : public ir_instruction {
-public:
- ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
-
- virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual ir_variable *as_variable()
- {
- return this;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
-
- /**
- * Get the string value for the interpolation qualifier
- *
- * \return The string that would be used in a shader to specify \c
- * mode will be returned.
- *
- * This function should only be used on a shader input or output variable.
- */
- const char *interpolation_string() const;
-
- /**
- * Calculate the number of slots required to hold this variable
- *
- * This is used to determine how many uniform or varying locations a variable
- * occupies. The count is in units of floating point components.
- */
- unsigned component_slots() const;
-
- /**
- * Delcared name of the variable
- */
- const char *name;
-
- /**
- * Highest element accessed with a constant expression array index
- *
- * Not used for non-array variables.
- */
- unsigned max_array_access;
-
- /**
- * Is the variable read-only?
- *
- * This is set for variables declared as \c const, shader inputs,
- * and uniforms.
- */
- unsigned read_only:1;
- unsigned centroid:1;
- unsigned invariant:1;
-
- /**
- * Has this variable been used for reading or writing?
- *
- * Several GLSL semantic checks require knowledge of whether or not a
- * variable has been used. For example, it is an error to redeclare a
- * variable as invariant after it has been used.
- */
- unsigned used:1;
-
- /**
- * Storage class of the variable.
- *
- * \sa ir_variable_mode
- */
- unsigned mode:3;
-
- /**
- * Interpolation mode for shader inputs / outputs
- *
- * \sa ir_variable_interpolation
- */
- unsigned interpolation:2;
-
- /**
- * Flag that the whole array is assignable
- *
- * In GLSL 1.20 and later whole arrays are assignable (and comparable for
- * equality). This flag enables this behavior.
- */
- unsigned array_lvalue:1;
-
- /**
- * \name ARB_fragment_coord_conventions
- * @{
- */
- unsigned origin_upper_left:1;
- unsigned pixel_center_integer:1;
- /*@}*/
-
- /**
- * Was the location explicitly set in the shader?
- *
- * If the location is explicitly set in the shader, it \b cannot be changed
- * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
- * no effect).
- */
- unsigned explicit_location:1;
-
- /**
- * Storage location of the base of this variable
- *
- * The precise meaning of this field depends on the nature of the variable.
- *
- * - Vertex shader input: one of the values from \c gl_vert_attrib.
- * - Vertex shader output: one of the values from \c gl_vert_result.
- * - Fragment shader input: one of the values from \c gl_frag_attrib.
- * - Fragment shader output: one of the values from \c gl_frag_result.
- * - Uniforms: Per-stage uniform slot number.
- * - Other: This field is not currently used.
- *
- * If the variable is a uniform, shader input, or shader output, and the
- * slot has not been assigned, the value will be -1.
- */
- int location;
-
- /**
- * Emit a warning if this variable is accessed.
- */
- const char *warn_extension;
-
- /**
- * Value assigned in the initializer of a variable declared "const"
- */
- ir_constant *constant_value;
-};
-
-
-/*@{*/
-/**
- * The representation of a function instance; may be the full definition or
- * simply a prototype.
- */
-class ir_function_signature : public ir_instruction {
- /* An ir_function_signature will be part of the list of signatures in
- * an ir_function.
- */
-public:
- ir_function_signature(const glsl_type *return_type);
-
- virtual ir_function_signature *clone(void *mem_ctx,
- struct hash_table *ht) const;
- ir_function_signature *clone_prototype(void *mem_ctx,
- struct hash_table *ht) const;
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- /**
- * Get the name of the function for which this is a signature
- */
- const char *function_name() const;
-
- /**
- * Get a handle to the function for which this is a signature
- *
- * There is no setter function, this function returns a \c const pointer,
- * and \c ir_function_signature::_function is private for a reason. The
- * only way to make a connection between a function and function signature
- * is via \c ir_function::add_signature. This helps ensure that certain
- * invariants (i.e., a function signature is in the list of signatures for
- * its \c _function) are met.
- *
- * \sa ir_function::add_signature
- */
- inline const class ir_function *function() const
- {
- return this->_function;
- }
-
- /**
- * Check whether the qualifiers match between this signature's parameters
- * and the supplied parameter list. If not, returns the name of the first
- * parameter with mismatched qualifiers (for use in error messages).
- */
- const char *qualifiers_match(exec_list *params);
-
- /**
- * Replace the current parameter list with the given one. This is useful
- * if the current information came from a prototype, and either has invalid
- * or missing parameter names.
- */
- void replace_parameters(exec_list *new_params);
-
- /**
- * Function return type.
- *
- * \note This discards the optional precision qualifier.
- */
- const struct glsl_type *return_type;
-
- /**
- * List of ir_variable of function parameters.
- *
- * This represents the storage. The paramaters passed in a particular
- * call will be in ir_call::actual_paramaters.
- */
- struct exec_list parameters;
-
- /** Whether or not this function has a body (which may be empty). */
- unsigned is_defined:1;
-
- /** Whether or not this function signature is a built-in. */
- unsigned is_builtin:1;
-
- /** Body of instructions in the function. */
- struct exec_list body;
-
-private:
- /** Function of which this signature is one overload. */
- class ir_function *_function;
-
- friend class ir_function;
-};
-
-
-/**
- * Header for tracking multiple overloaded functions with the same name.
- * Contains a list of ir_function_signatures representing each of the
- * actual functions.
- */
-class ir_function : public ir_instruction {
-public:
- ir_function(const char *name);
-
- virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual ir_function *as_function()
- {
- return this;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- void add_signature(ir_function_signature *sig)
- {
- sig->_function = this;
- this->signatures.push_tail(sig);
- }
-
- /**
- * Get an iterator for the set of function signatures
- */
- exec_list_iterator iterator()
- {
- return signatures.iterator();
- }
-
- /**
- * Find a signature that matches a set of actual parameters, taking implicit
- * conversions into account.
- */
- ir_function_signature *matching_signature(const exec_list *actual_param);
-
- /**
- * Find a signature that exactly matches a set of actual parameters without
- * any implicit type conversions.
- */
- ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
-
- /**
- * Name of the function.
- */
- const char *name;
-
- /** Whether or not this function has a signature that isn't a built-in. */
- bool has_user_signature();
-
- /**
- * List of ir_function_signature for each overloaded function with this name.
- */
- struct exec_list signatures;
-};
-
-inline const char *ir_function_signature::function_name() const
-{
- return this->_function->name;
-}
-/*@}*/
-
-
-/**
- * IR instruction representing high-level if-statements
- */
-class ir_if : public ir_instruction {
-public:
- ir_if(ir_rvalue *condition)
- : condition(condition)
- {
- ir_type = ir_type_if;
- }
-
- virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual ir_if *as_if()
- {
- return this;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- ir_rvalue *condition;
- /** List of ir_instruction for the body of the then branch */
- exec_list then_instructions;
- /** List of ir_instruction for the body of the else branch */
- exec_list else_instructions;
-};
-
-
-/**
- * IR instruction representing a high-level loop structure.
- */
-class ir_loop : public ir_instruction {
-public:
- ir_loop();
-
- virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- virtual ir_loop *as_loop()
- {
- return this;
- }
-
- /**
- * Get an iterator for the instructions of the loop body
- */
- exec_list_iterator iterator()
- {
- return body_instructions.iterator();
- }
-
- /** List of ir_instruction that make up the body of the loop. */
- exec_list body_instructions;
-
- /**
- * \name Loop counter and controls
- *
- * Represents a loop like a FORTRAN \c do-loop.
- *
- * \note
- * If \c from and \c to are the same value, the loop will execute once.
- */
- /*@{*/
- ir_rvalue *from; /** Value of the loop counter on the first
- * iteration of the loop.
- */
- ir_rvalue *to; /** Value of the loop counter on the last
- * iteration of the loop.
- */
- ir_rvalue *increment;
- ir_variable *counter;
-
- /**
- * Comparison operation in the loop terminator.
- *
- * If any of the loop control fields are non-\c NULL, this field must be
- * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal,
- * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal.
- */
- int cmp;
- /*@}*/
-};
-
-
-class ir_assignment : public ir_instruction {
-public:
- ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
-
- /**
- * Construct an assignment with an explicit write mask
- *
- * \note
- * Since a write mask is supplied, the LHS must already be a bare
- * \c ir_dereference. The cannot be any swizzles in the LHS.
- */
- ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
- unsigned write_mask);
-
- virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- virtual ir_assignment * as_assignment()
- {
- return this;
- }
-
- /**
- * Get a whole variable written by an assignment
- *
- * If the LHS of the assignment writes a whole variable, the variable is
- * returned. Otherwise \c NULL is returned. Examples of whole-variable
- * assignment are:
- *
- * - Assigning to a scalar
- * - Assigning to all components of a vector
- * - Whole array (or matrix) assignment
- * - Whole structure assignment
- */
- ir_variable *whole_variable_written();
-
- /**
- * Set the LHS of an assignment
- */
- void set_lhs(ir_rvalue *lhs);
-
- /**
- * Left-hand side of the assignment.
- *
- * This should be treated as read only. If you need to set the LHS of an
- * assignment, use \c ir_assignment::set_lhs.
- */
- ir_dereference *lhs;
-
- /**
- * Value being assigned
- */
- ir_rvalue *rhs;
-
- /**
- * Optional condition for the assignment.
- */
- ir_rvalue *condition;
-
-
- /**
- * Component mask written
- *
- * For non-vector types in the LHS, this field will be zero. For vector
- * types, a bit will be set for each component that is written. Note that
- * for \c vec2 and \c vec3 types only the lower bits will ever be set.
- *
- * A partially-set write mask means that each enabled channel gets
- * the value from a consecutive channel of the rhs. For example,
- * to write just .xyw of gl_FrontColor with color:
- *
- * (assign (constant bool (1)) (xyw)
- * (var_ref gl_FragColor)
- * (swiz xyw (var_ref color)))
- */
- unsigned write_mask:4;
-};
-
-/* Update ir_expression::num_operands() and operator_strs when
- * updating this list.
- */
-enum ir_expression_operation {
- ir_unop_bit_not,
- ir_unop_logic_not,
- ir_unop_neg,
- ir_unop_abs,
- ir_unop_sign,
- ir_unop_rcp,
- ir_unop_rsq,
- ir_unop_sqrt,
- ir_unop_exp, /**< Log base e on gentype */
- ir_unop_log, /**< Natural log on gentype */
- ir_unop_exp2,
- ir_unop_log2,
- ir_unop_f2i, /**< Float-to-integer conversion. */
- ir_unop_i2f, /**< Integer-to-float conversion. */
- ir_unop_f2b, /**< Float-to-boolean conversion */
- ir_unop_b2f, /**< Boolean-to-float conversion */
- ir_unop_i2b, /**< int-to-boolean conversion */
- ir_unop_b2i, /**< Boolean-to-int conversion */
- ir_unop_u2f, /**< Unsigned-to-float conversion. */
- ir_unop_any,
-
- /**
- * \name Unary floating-point rounding operations.
- */
- /*@{*/
- ir_unop_trunc,
- ir_unop_ceil,
- ir_unop_floor,
- ir_unop_fract,
- ir_unop_round_even,
- /*@}*/
-
- /**
- * \name Trigonometric operations.
- */
- /*@{*/
- ir_unop_sin,
- ir_unop_cos,
- ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */
- ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */
- /*@}*/
-
- /**
- * \name Partial derivatives.
- */
- /*@{*/
- ir_unop_dFdx,
- ir_unop_dFdy,
- /*@}*/
-
- ir_unop_noise,
-
- /**
- * A sentinel marking the last of the unary operations.
- */
- ir_last_unop = ir_unop_noise,
-
- ir_binop_add,
- ir_binop_sub,
- ir_binop_mul,
- ir_binop_div,
-
- /**
- * Takes one of two combinations of arguments:
- *
- * - mod(vecN, vecN)
- * - mod(vecN, float)
- *
- * Does not take integer types.
- */
- ir_binop_mod,
-
- /**
- * \name Binary comparison operators which return a boolean vector.
- * The type of both operands must be equal.
- */
- /*@{*/
- ir_binop_less,
- ir_binop_greater,
- ir_binop_lequal,
- ir_binop_gequal,
- ir_binop_equal,
- ir_binop_nequal,
- /**
- * Returns single boolean for whether all components of operands[0]
- * equal the components of operands[1].
- */
- ir_binop_all_equal,
- /**
- * Returns single boolean for whether any component of operands[0]
- * is not equal to the corresponding component of operands[1].
- */
- ir_binop_any_nequal,
- /*@}*/
-
- /**
- * \name Bit-wise binary operations.
- */
- /*@{*/
- ir_binop_lshift,
- ir_binop_rshift,
- ir_binop_bit_and,
- ir_binop_bit_xor,
- ir_binop_bit_or,
- /*@}*/
-
- ir_binop_logic_and,
- ir_binop_logic_xor,
- ir_binop_logic_or,
-
- ir_binop_dot,
- ir_binop_min,
- ir_binop_max,
-
- ir_binop_pow,
-
- /**
- * A sentinel marking the last of the binary operations.
- */
- ir_last_binop = ir_binop_pow,
-
- ir_quadop_vector,
-
- /**
- * A sentinel marking the last of all operations.
- */
- ir_last_opcode = ir_last_binop
-};
-
-class ir_expression : public ir_rvalue {
-public:
- /**
- * Constructor for unary operation expressions
- */
- ir_expression(int op, const struct glsl_type *type, ir_rvalue *);
- ir_expression(int op, ir_rvalue *);
-
- /**
- * Constructor for binary operation expressions
- */
- ir_expression(int op, const struct glsl_type *type,
- ir_rvalue *, ir_rvalue *);
- ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
-
- /**
- * Constructor for quad operator expressions
- */
- ir_expression(int op, const struct glsl_type *type,
- ir_rvalue *, ir_rvalue *, ir_rvalue *, ir_rvalue *);
-
- virtual ir_expression *as_expression()
- {
- return this;
- }
-
- virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
-
- /**
- * Attempt to constant-fold the expression
- *
- * If the expression cannot be constant folded, this method will return
- * \c NULL.
- */
- virtual ir_constant *constant_expression_value();
-
- /**
- * Determine the number of operands used by an expression
- */
- static unsigned int get_num_operands(ir_expression_operation);
-
- /**
- * Determine the number of operands used by an expression
- */
- unsigned int get_num_operands() const
- {
- return (this->operation == ir_quadop_vector)
- ? this->type->vector_elements : get_num_operands(operation);
- }
-
- /**
- * Return a string representing this expression's operator.
- */
- const char *operator_string();
-
- /**
- * Return a string representing this expression's operator.
- */
- static const char *operator_string(ir_expression_operation);
-
-
- /**
- * Do a reverse-lookup to translate the given string into an operator.
- */
- static ir_expression_operation get_operator(const char *);
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- ir_expression_operation operation;
- ir_rvalue *operands[4];
-};
-
-
-/**
- * IR instruction representing a function call
- */
-class ir_call : public ir_rvalue {
-public:
- ir_call(ir_function_signature *callee, exec_list *actual_parameters)
- : callee(callee)
- {
- ir_type = ir_type_call;
- assert(callee->return_type != NULL);
- type = callee->return_type;
- actual_parameters->move_nodes_to(& this->actual_parameters);
- }
-
- virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual ir_call *as_call()
- {
- return this;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- /**
- * Get a generic ir_call object when an error occurs
- *
- * Any allocation will be performed with 'ctx' as talloc owner.
- */
- static ir_call *get_error_instruction(void *ctx);
-
- /**
- * Get an iterator for the set of acutal parameters
- */
- exec_list_iterator iterator()
- {
- return actual_parameters.iterator();
- }
-
- /**
- * Get the name of the function being called.
- */
- const char *callee_name() const
- {
- return callee->function_name();
- }
-
- /**
- * Get the function signature bound to this function call
- */
- ir_function_signature *get_callee()
- {
- return callee;
- }
-
- /**
- * Set the function call target
- */
- void set_callee(ir_function_signature *sig);
-
- /**
- * Generates an inline version of the function before @ir,
- * returning the return value of the function.
- */
- ir_rvalue *generate_inline(ir_instruction *ir);
-
- /* List of ir_rvalue of paramaters passed in this call. */
- exec_list actual_parameters;
-
-private:
- ir_call()
- : callee(NULL)
- {
- this->ir_type = ir_type_call;
- }
-
- ir_function_signature *callee;
-};
-
-
-/**
- * \name Jump-like IR instructions.
- *
- * These include \c break, \c continue, \c return, and \c discard.
- */
-/*@{*/
-class ir_jump : public ir_instruction {
-protected:
- ir_jump()
- {
- ir_type = ir_type_unset;
- }
-};
-
-class ir_return : public ir_jump {
-public:
- ir_return()
- : value(NULL)
- {
- this->ir_type = ir_type_return;
- }
-
- ir_return(ir_rvalue *value)
- : value(value)
- {
- this->ir_type = ir_type_return;
- }
-
- virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
-
- virtual ir_return *as_return()
- {
- return this;
- }
-
- ir_rvalue *get_value() const
- {
- return value;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- ir_rvalue *value;
-};
-
-
-/**
- * Jump instructions used inside loops
- *
- * These include \c break and \c continue. The \c break within a loop is
- * different from the \c break within a switch-statement.
- *
- * \sa ir_switch_jump
- */
-class ir_loop_jump : public ir_jump {
-public:
- enum jump_mode {
- jump_break,
- jump_continue
- };
-
- ir_loop_jump(jump_mode mode)
- {
- this->ir_type = ir_type_loop_jump;
- this->mode = mode;
- this->loop = loop;
- }
-
- virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- bool is_break() const
- {
- return mode == jump_break;
- }
-
- bool is_continue() const
- {
- return mode == jump_continue;
- }
-
- /** Mode selector for the jump instruction. */
- enum jump_mode mode;
-private:
- /** Loop containing this break instruction. */
- ir_loop *loop;
-};
-
-/**
- * IR instruction representing discard statements.
- */
-class ir_discard : public ir_jump {
-public:
- ir_discard()
- {
- this->ir_type = ir_type_discard;
- this->condition = NULL;
- }
-
- ir_discard(ir_rvalue *cond)
- {
- this->ir_type = ir_type_discard;
- this->condition = cond;
- }
-
- virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- virtual ir_discard *as_discard()
- {
- return this;
- }
-
- ir_rvalue *condition;
-};
-/*@}*/
-
-
-/**
- * Texture sampling opcodes used in ir_texture
- */
-enum ir_texture_opcode {
- ir_tex, /**< Regular texture look-up */
- ir_txb, /**< Texture look-up with LOD bias */
- ir_txl, /**< Texture look-up with explicit LOD */
- ir_txd, /**< Texture look-up with partial derivatvies */
- ir_txf /**< Texel fetch with explicit LOD */
-};
-
-
-/**
- * IR instruction to sample a texture
- *
- * The specific form of the IR instruction depends on the \c mode value
- * selected from \c ir_texture_opcodes. In the printed IR, these will
- * appear as:
- *
- * Texel offset
- * | Projection divisor
- * | | Shadow comparitor
- * | | |
- * v v v
- * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
- * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
- * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
- * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
- * (txf (sampler) (coordinate) (0 0 0) (lod))
- */
-class ir_texture : public ir_rvalue {
-public:
- ir_texture(enum ir_texture_opcode op)
- : op(op), projector(NULL), shadow_comparitor(NULL)
- {
- this->ir_type = ir_type_texture;
- }
-
- virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- /**
- * Return a string representing the ir_texture_opcode.
- */
- const char *opcode_string();
-
- /** Set the sampler and infer the type. */
- void set_sampler(ir_dereference *sampler);
-
- /**
- * Do a reverse-lookup to translate a string into an ir_texture_opcode.
- */
- static ir_texture_opcode get_opcode(const char *);
-
- enum ir_texture_opcode op;
-
- /** Sampler to use for the texture access. */
- ir_dereference *sampler;
-
- /** Texture coordinate to sample */
- ir_rvalue *coordinate;
-
- /**
- * Value used for projective divide.
- *
- * If there is no projective divide (the common case), this will be
- * \c NULL. Optimization passes should check for this to point to a constant
- * of 1.0 and replace that with \c NULL.
- */
- ir_rvalue *projector;
-
- /**
- * Coordinate used for comparison on shadow look-ups.
- *
- * If there is no shadow comparison, this will be \c NULL. For the
- * \c ir_txf opcode, this *must* be \c NULL.
- */
- ir_rvalue *shadow_comparitor;
-
- /** Explicit texel offsets. */
- signed char offsets[3];
-
- union {
- ir_rvalue *lod; /**< Floating point LOD */
- ir_rvalue *bias; /**< Floating point LOD bias */
- struct {
- ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */
- ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */
- } grad;
- } lod_info;
-};
-
-
-struct ir_swizzle_mask {
- unsigned x:2;
- unsigned y:2;
- unsigned z:2;
- unsigned w:2;
-
- /**
- * Number of components in the swizzle.
- */
- unsigned num_components:3;
-
- /**
- * Does the swizzle contain duplicate components?
- *
- * L-value swizzles cannot contain duplicate components.
- */
- unsigned has_duplicates:1;
-};
-
-
-class ir_swizzle : public ir_rvalue {
-public:
- ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
- unsigned count);
-
- ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count);
-
- ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
-
- virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual ir_swizzle *as_swizzle()
- {
- return this;
- }
-
- /**
- * Construct an ir_swizzle from the textual representation. Can fail.
- */
- static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- bool is_lvalue()
- {
- return val->is_lvalue() && !mask.has_duplicates;
- }
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced();
-
- ir_rvalue *val;
- ir_swizzle_mask mask;
-
-private:
- /**
- * Initialize the mask component of a swizzle
- *
- * This is used by the \c ir_swizzle constructors.
- */
- void init_mask(const unsigned *components, unsigned count);
-};
-
-
-class ir_dereference : public ir_rvalue {
-public:
- virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
-
- virtual ir_dereference *as_dereference()
- {
- return this;
- }
-
- bool is_lvalue();
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced() = 0;
-};
-
-
-class ir_dereference_variable : public ir_dereference {
-public:
- ir_dereference_variable(ir_variable *var);
-
- virtual ir_dereference_variable *clone(void *mem_ctx,
- struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual ir_dereference_variable *as_dereference_variable()
- {
- return this;
- }
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced()
- {
- return this->var;
- }
-
- virtual ir_variable *whole_variable_referenced()
- {
- /* ir_dereference_variable objects always dereference the entire
- * variable. However, if this dereference is dereferenced by anything
- * else, the complete deferefernce chain is not a whole-variable
- * dereference. This method should only be called on the top most
- * ir_rvalue in a dereference chain.
- */
- return this->var;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- /**
- * Object being dereferenced.
- */
- ir_variable *var;
-};
-
-
-class ir_dereference_array : public ir_dereference {
-public:
- ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
-
- ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
-
- virtual ir_dereference_array *clone(void *mem_ctx,
- struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual ir_dereference_array *as_dereference_array()
- {
- return this;
- }
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced()
- {
- return this->array->variable_referenced();
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- ir_rvalue *array;
- ir_rvalue *array_index;
-
-private:
- void set_array(ir_rvalue *value);
-};
-
-
-class ir_dereference_record : public ir_dereference {
-public:
- ir_dereference_record(ir_rvalue *value, const char *field);
-
- ir_dereference_record(ir_variable *var, const char *field);
-
- virtual ir_dereference_record *clone(void *mem_ctx,
- struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- /**
- * Get the variable that is ultimately referenced by an r-value
- */
- virtual ir_variable *variable_referenced()
- {
- return this->record->variable_referenced();
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- ir_rvalue *record;
- const char *field;
-};
-
-
-/**
- * Data stored in an ir_constant
- */
-union ir_constant_data {
- unsigned u[16];
- int i[16];
- float f[16];
- bool b[16];
-};
-
-
-class ir_constant : public ir_rvalue {
-public:
- ir_constant(const struct glsl_type *type, const ir_constant_data *data);
- ir_constant(bool b);
- ir_constant(unsigned int u);
- ir_constant(int i);
- ir_constant(float f);
-
- /**
- * Construct an ir_constant from a list of ir_constant values
- */
- ir_constant(const struct glsl_type *type, exec_list *values);
-
- /**
- * Construct an ir_constant from a scalar component of another ir_constant
- *
- * The new \c ir_constant inherits the type of the component from the
- * source constant.
- *
- * \note
- * In the case of a matrix constant, the new constant is a scalar, \b not
- * a vector.
- */
- ir_constant(const ir_constant *c, unsigned i);
-
- /**
- * Return a new ir_constant of the specified type containing all zeros.
- */
- static ir_constant *zero(void *mem_ctx, const glsl_type *type);
-
- virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
-
- virtual ir_constant *constant_expression_value();
-
- virtual ir_constant *as_constant()
- {
- return this;
- }
-
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
- virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-
- /**
- * Get a particular component of a constant as a specific type
- *
- * This is useful, for example, to get a value from an integer constant
- * as a float or bool. This appears frequently when constructors are
- * called with all constant parameters.
- */
- /*@{*/
- bool get_bool_component(unsigned i) const;
- float get_float_component(unsigned i) const;
- int get_int_component(unsigned i) const;
- unsigned get_uint_component(unsigned i) const;
- /*@}*/
-
- ir_constant *get_array_element(unsigned i) const;
-
- ir_constant *get_record_field(const char *name);
-
- /**
- * Determine whether a constant has the same value as another constant
- *
- * \sa ir_constant::is_zero, ir_constant::is_one,
- * ir_constant::is_negative_one
- */
- bool has_value(const ir_constant *) const;
-
- virtual bool is_zero() const;
- virtual bool is_one() const;
- virtual bool is_negative_one() const;
-
- /**
- * Value of the constant.
- *
- * The field used to back the values supplied by the constant is determined
- * by the type associated with the \c ir_instruction. Constants may be
- * scalars, vectors, or matrices.
- */
- union ir_constant_data value;
-
- /* Array elements */
- ir_constant **array_elements;
-
- /* Structure fields */
- exec_list components;
-
-private:
- /**
- * Parameterless constructor only used by the clone method
- */
- ir_constant(void);
-};
-
-/*@}*/
-
-/**
- * Apply a visitor to each IR node in a list
- */
-void
-visit_exec_list(exec_list *list, ir_visitor *visitor);
-
-/**
- * Validate invariants on each IR node in a list
- */
-void validate_ir_tree(exec_list *instructions);
-
-/**
- * Make a clone of each IR instruction in a list
- *
- * \param in List of IR instructions that are to be cloned
- * \param out List to hold the cloned instructions
- */
-void
-clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
-
-extern void
-_mesa_glsl_initialize_variables(exec_list *instructions,
- struct _mesa_glsl_parse_state *state);
-
-extern void
-_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
-
-extern void
-_mesa_glsl_release_functions(void);
-
-extern void
-reparent_ir(exec_list *list, void *mem_ctx);
-
-struct glsl_symbol_table;
-
-extern void
-import_prototypes(const exec_list *source, exec_list *dest,
- struct glsl_symbol_table *symbols, void *mem_ctx);
-
-extern bool
-ir_has_call(ir_instruction *ir);
-
-extern void
-do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
-
-#endif /* IR_H */
+/* -*- c++ -*- */
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#pragma once
+#ifndef IR_H
+#define IR_H
+
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "glsl_types.h"
+#include "list.h"
+#include "ir_visitor.h"
+#include "ir_hierarchical_visitor.h"
+
+/**
+ * \defgroup IR Intermediate representation nodes
+ *
+ * @{
+ */
+
+/**
+ * Class tags
+ *
+ * Each concrete class derived from \c ir_instruction has a value in this
+ * enumerant. The value for the type is stored in \c ir_instruction::ir_type
+ * by the constructor. While using type tags is not very C++, it is extremely
+ * convenient. For example, during debugging you can simply inspect
+ * \c ir_instruction::ir_type to find out the actual type of the object.
+ *
+ * In addition, it is possible to use a switch-statement based on \c
+ * \c ir_instruction::ir_type to select different behavior for different object
+ * types. For functions that have only slight differences for several object
+ * types, this allows writing very straightforward, readable code.
+ */
+enum ir_node_type {
+ /**
+ * Zero is unused so that the IR validator can detect cases where
+ * \c ir_instruction::ir_type has not been initialized.
+ */
+ ir_type_unset,
+ ir_type_variable,
+ ir_type_assignment,
+ ir_type_call,
+ ir_type_constant,
+ ir_type_dereference_array,
+ ir_type_dereference_record,
+ ir_type_dereference_variable,
+ ir_type_discard,
+ ir_type_expression,
+ ir_type_function,
+ ir_type_function_signature,
+ ir_type_if,
+ ir_type_loop,
+ ir_type_loop_jump,
+ ir_type_return,
+ ir_type_swizzle,
+ ir_type_texture,
+ ir_type_max /**< maximum ir_type enum number, for validation */
+};
+
+/**
+ * Base class of all IR instructions
+ */
+class ir_instruction : public exec_node {
+public:
+ enum ir_node_type ir_type;
+ const struct glsl_type *type;
+
+ /** ir_print_visitor helper for debugging. */
+ void print(void) const;
+
+ virtual void accept(ir_visitor *) = 0;
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
+ virtual ir_instruction *clone(void *mem_ctx,
+ struct hash_table *ht) const = 0;
+
+ /**
+ * \name IR instruction downcast functions
+ *
+ * These functions either cast the object to a derived class or return
+ * \c NULL if the object's type does not match the specified derived class.
+ * Additional downcast functions will be added as needed.
+ */
+ /*@{*/
+ virtual class ir_variable * as_variable() { return NULL; }
+ virtual class ir_function * as_function() { return NULL; }
+ virtual class ir_dereference * as_dereference() { return NULL; }
+ virtual class ir_dereference_array * as_dereference_array() { return NULL; }
+ virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
+ virtual class ir_expression * as_expression() { return NULL; }
+ virtual class ir_rvalue * as_rvalue() { return NULL; }
+ virtual class ir_loop * as_loop() { return NULL; }
+ virtual class ir_assignment * as_assignment() { return NULL; }
+ virtual class ir_call * as_call() { return NULL; }
+ virtual class ir_return * as_return() { return NULL; }
+ virtual class ir_if * as_if() { return NULL; }
+ virtual class ir_swizzle * as_swizzle() { return NULL; }
+ virtual class ir_constant * as_constant() { return NULL; }
+ virtual class ir_discard * as_discard() { return NULL; }
+ /*@}*/
+
+protected:
+ ir_instruction()
+ {
+ ir_type = ir_type_unset;
+ type = NULL;
+ }
+};
+
+
+class ir_rvalue : public ir_instruction {
+public:
+ virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+ virtual ir_constant *constant_expression_value() = 0;
+
+ virtual ir_rvalue * as_rvalue()
+ {
+ return this;
+ }
+
+ ir_rvalue *as_rvalue_to_saturate();
+
+ virtual bool is_lvalue()
+ {
+ return false;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return NULL;
+ }
+
+
+ /**
+ * If an r-value is a reference to a whole variable, get that variable
+ *
+ * \return
+ * Pointer to a variable that is completely dereferenced by the r-value. If
+ * the r-value is not a dereference or the dereference does not access the
+ * entire variable (i.e., it's just one array element, struct field), \c NULL
+ * is returned.
+ */
+ virtual ir_variable *whole_variable_referenced()
+ {
+ return NULL;
+ }
+
+ /**
+ * Determine if an r-value has the value zero
+ *
+ * The base implementation of this function always returns \c false. The
+ * \c ir_constant class over-rides this function to return \c true \b only
+ * for vector and scalar types that have all elements set to the value
+ * zero (or \c false for booleans).
+ *
+ * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one
+ */
+ virtual bool is_zero() const;
+
+ /**
+ * Determine if an r-value has the value one
+ *
+ * The base implementation of this function always returns \c false. The
+ * \c ir_constant class over-rides this function to return \c true \b only
+ * for vector and scalar types that have all elements set to the value
+ * one (or \c true for booleans).
+ *
+ * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one
+ */
+ virtual bool is_one() const;
+
+ /**
+ * Determine if an r-value has the value negative one
+ *
+ * The base implementation of this function always returns \c false. The
+ * \c ir_constant class over-rides this function to return \c true \b only
+ * for vector and scalar types that have all elements set to the value
+ * negative one. For boolean times, the result is always \c false.
+ *
+ * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
+ */
+ virtual bool is_negative_one() const;
+
+protected:
+ ir_rvalue();
+};
+
+
+/**
+ * Variable storage classes
+ */
+enum ir_variable_mode {
+ ir_var_auto = 0, /**< Function local variables and globals. */
+ ir_var_uniform, /**< Variable declared as a uniform. */
+ ir_var_in,
+ ir_var_out,
+ ir_var_inout,
+ ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
+ ir_var_temporary /**< Temporary variable generated during compilation. */
+};
+
+enum ir_variable_interpolation {
+ ir_var_smooth = 0,
+ ir_var_flat,
+ ir_var_noperspective
+};
+
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * The AMD_conservative_depth extension allows gl_FragDepth to be redeclared
+ * with a layout qualifier.
+ */
+enum ir_depth_layout {
+ ir_depth_layout_none, /**< No depth layout is specified. */
+ ir_depth_layout_any,
+ ir_depth_layout_greater,
+ ir_depth_layout_less,
+ ir_depth_layout_unchanged
+};
+
+/**
+ * \brief Convert depth layout qualifier to string.
+ */
+const char*
+depth_layout_string(ir_depth_layout layout);
+
+class ir_variable : public ir_instruction {
+public:
+ ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
+
+ virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_variable *as_variable()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+
+ /**
+ * Get the string value for the interpolation qualifier
+ *
+ * \return The string that would be used in a shader to specify \c
+ * mode will be returned.
+ *
+ * This function should only be used on a shader input or output variable.
+ */
+ const char *interpolation_string() const;
+
+ /**
+ * Calculate the number of slots required to hold this variable
+ *
+ * This is used to determine how many uniform or varying locations a variable
+ * occupies. The count is in units of floating point components.
+ */
+ unsigned component_slots() const;
+
+ /**
+ * Delcared name of the variable
+ */
+ const char *name;
+
+ /**
+ * Highest element accessed with a constant expression array index
+ *
+ * Not used for non-array variables.
+ */
+ unsigned max_array_access;
+
+ /**
+ * Is the variable read-only?
+ *
+ * This is set for variables declared as \c const, shader inputs,
+ * and uniforms.
+ */
+ unsigned read_only:1;
+ unsigned centroid:1;
+ unsigned invariant:1;
+
+ /**
+ * Has this variable been used for reading or writing?
+ *
+ * Several GLSL semantic checks require knowledge of whether or not a
+ * variable has been used. For example, it is an error to redeclare a
+ * variable as invariant after it has been used.
+ */
+ unsigned used:1;
+
+ /**
+ * Storage class of the variable.
+ *
+ * \sa ir_variable_mode
+ */
+ unsigned mode:3;
+
+ /**
+ * Interpolation mode for shader inputs / outputs
+ *
+ * \sa ir_variable_interpolation
+ */
+ unsigned interpolation:2;
+
+ /**
+ * Flag that the whole array is assignable
+ *
+ * In GLSL 1.20 and later whole arrays are assignable (and comparable for
+ * equality). This flag enables this behavior.
+ */
+ unsigned array_lvalue:1;
+
+ /**
+ * \name ARB_fragment_coord_conventions
+ * @{
+ */
+ unsigned origin_upper_left:1;
+ unsigned pixel_center_integer:1;
+ /*@}*/
+
+ /**
+ * \brief Layout qualifier for gl_FragDepth.
+ *
+ * This is not equal to \c ir_depth_layout_none if and only if this
+ * variable is \c gl_FragDepth and a layout qualifier is specified.
+ */
+ ir_depth_layout depth_layout;
+
+ /**
+ * Was the location explicitly set in the shader?
+ *
+ * If the location is explicitly set in the shader, it \b cannot be changed
+ * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
+ * no effect).
+ */
+ unsigned explicit_location:1;
+
+ /**
+ * Storage location of the base of this variable
+ *
+ * The precise meaning of this field depends on the nature of the variable.
+ *
+ * - Vertex shader input: one of the values from \c gl_vert_attrib.
+ * - Vertex shader output: one of the values from \c gl_vert_result.
+ * - Fragment shader input: one of the values from \c gl_frag_attrib.
+ * - Fragment shader output: one of the values from \c gl_frag_result.
+ * - Uniforms: Per-stage uniform slot number.
+ * - Other: This field is not currently used.
+ *
+ * If the variable is a uniform, shader input, or shader output, and the
+ * slot has not been assigned, the value will be -1.
+ */
+ int location;
+
+ /**
+ * Emit a warning if this variable is accessed.
+ */
+ const char *warn_extension;
+
+ /**
+ * Value assigned in the initializer of a variable declared "const"
+ */
+ ir_constant *constant_value;
+};
+
+
+/*@{*/
+/**
+ * The representation of a function instance; may be the full definition or
+ * simply a prototype.
+ */
+class ir_function_signature : public ir_instruction {
+ /* An ir_function_signature will be part of the list of signatures in
+ * an ir_function.
+ */
+public:
+ ir_function_signature(const glsl_type *return_type);
+
+ virtual ir_function_signature *clone(void *mem_ctx,
+ struct hash_table *ht) const;
+ ir_function_signature *clone_prototype(void *mem_ctx,
+ struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get the name of the function for which this is a signature
+ */
+ const char *function_name() const;
+
+ /**
+ * Get a handle to the function for which this is a signature
+ *
+ * There is no setter function, this function returns a \c const pointer,
+ * and \c ir_function_signature::_function is private for a reason. The
+ * only way to make a connection between a function and function signature
+ * is via \c ir_function::add_signature. This helps ensure that certain
+ * invariants (i.e., a function signature is in the list of signatures for
+ * its \c _function) are met.
+ *
+ * \sa ir_function::add_signature
+ */
+ inline const class ir_function *function() const
+ {
+ return this->_function;
+ }
+
+ /**
+ * Check whether the qualifiers match between this signature's parameters
+ * and the supplied parameter list. If not, returns the name of the first
+ * parameter with mismatched qualifiers (for use in error messages).
+ */
+ const char *qualifiers_match(exec_list *params);
+
+ /**
+ * Replace the current parameter list with the given one. This is useful
+ * if the current information came from a prototype, and either has invalid
+ * or missing parameter names.
+ */
+ void replace_parameters(exec_list *new_params);
+
+ /**
+ * Function return type.
+ *
+ * \note This discards the optional precision qualifier.
+ */
+ const struct glsl_type *return_type;
+
+ /**
+ * List of ir_variable of function parameters.
+ *
+ * This represents the storage. The paramaters passed in a particular
+ * call will be in ir_call::actual_paramaters.
+ */
+ struct exec_list parameters;
+
+ /** Whether or not this function has a body (which may be empty). */
+ unsigned is_defined:1;
+
+ /** Whether or not this function signature is a built-in. */
+ unsigned is_builtin:1;
+
+ /** Body of instructions in the function. */
+ struct exec_list body;
+
+private:
+ /** Function of which this signature is one overload. */
+ class ir_function *_function;
+
+ friend class ir_function;
+};
+
+
+/**
+ * Header for tracking multiple overloaded functions with the same name.
+ * Contains a list of ir_function_signatures representing each of the
+ * actual functions.
+ */
+class ir_function : public ir_instruction {
+public:
+ ir_function(const char *name);
+
+ virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_function *as_function()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ void add_signature(ir_function_signature *sig)
+ {
+ sig->_function = this;
+ this->signatures.push_tail(sig);
+ }
+
+ /**
+ * Get an iterator for the set of function signatures
+ */
+ exec_list_iterator iterator()
+ {
+ return signatures.iterator();
+ }
+
+ /**
+ * Find a signature that matches a set of actual parameters, taking implicit
+ * conversions into account.
+ */
+ ir_function_signature *matching_signature(const exec_list *actual_param);
+
+ /**
+ * Find a signature that exactly matches a set of actual parameters without
+ * any implicit type conversions.
+ */
+ ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
+
+ /**
+ * Name of the function.
+ */
+ const char *name;
+
+ /** Whether or not this function has a signature that isn't a built-in. */
+ bool has_user_signature();
+
+ /**
+ * List of ir_function_signature for each overloaded function with this name.
+ */
+ struct exec_list signatures;
+};
+
+inline const char *ir_function_signature::function_name() const
+{
+ return this->_function->name;
+}
+/*@}*/
+
+
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+ ir_if(ir_rvalue *condition)
+ : condition(condition)
+ {
+ ir_type = ir_type_if;
+ }
+
+ virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_if *as_if()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *condition;
+ /** List of ir_instruction for the body of the then branch */
+ exec_list then_instructions;
+ /** List of ir_instruction for the body of the else branch */
+ exec_list else_instructions;
+};
+
+
+/**
+ * IR instruction representing a high-level loop structure.
+ */
+class ir_loop : public ir_instruction {
+public:
+ ir_loop();
+
+ virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_loop *as_loop()
+ {
+ return this;
+ }
+
+ /**
+ * Get an iterator for the instructions of the loop body
+ */
+ exec_list_iterator iterator()
+ {
+ return body_instructions.iterator();
+ }
+
+ /** List of ir_instruction that make up the body of the loop. */
+ exec_list body_instructions;
+
+ /**
+ * \name Loop counter and controls
+ *
+ * Represents a loop like a FORTRAN \c do-loop.
+ *
+ * \note
+ * If \c from and \c to are the same value, the loop will execute once.
+ */
+ /*@{*/
+ ir_rvalue *from; /** Value of the loop counter on the first
+ * iteration of the loop.
+ */
+ ir_rvalue *to; /** Value of the loop counter on the last
+ * iteration of the loop.
+ */
+ ir_rvalue *increment;
+ ir_variable *counter;
+
+ /**
+ * Comparison operation in the loop terminator.
+ *
+ * If any of the loop control fields are non-\c NULL, this field must be
+ * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal,
+ * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal.
+ */
+ int cmp;
+ /*@}*/
+};
+
+
+class ir_assignment : public ir_instruction {
+public:
+ ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+
+ /**
+ * Construct an assignment with an explicit write mask
+ *
+ * \note
+ * Since a write mask is supplied, the LHS must already be a bare
+ * \c ir_dereference. The cannot be any swizzles in the LHS.
+ */
+ ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
+ unsigned write_mask);
+
+ virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_assignment * as_assignment()
+ {
+ return this;
+ }
+
+ /**
+ * Get a whole variable written by an assignment
+ *
+ * If the LHS of the assignment writes a whole variable, the variable is
+ * returned. Otherwise \c NULL is returned. Examples of whole-variable
+ * assignment are:
+ *
+ * - Assigning to a scalar
+ * - Assigning to all components of a vector
+ * - Whole array (or matrix) assignment
+ * - Whole structure assignment
+ */
+ ir_variable *whole_variable_written();
+
+ /**
+ * Set the LHS of an assignment
+ */
+ void set_lhs(ir_rvalue *lhs);
+
+ /**
+ * Left-hand side of the assignment.
+ *
+ * This should be treated as read only. If you need to set the LHS of an
+ * assignment, use \c ir_assignment::set_lhs.
+ */
+ ir_dereference *lhs;
+
+ /**
+ * Value being assigned
+ */
+ ir_rvalue *rhs;
+
+ /**
+ * Optional condition for the assignment.
+ */
+ ir_rvalue *condition;
+
+
+ /**
+ * Component mask written
+ *
+ * For non-vector types in the LHS, this field will be zero. For vector
+ * types, a bit will be set for each component that is written. Note that
+ * for \c vec2 and \c vec3 types only the lower bits will ever be set.
+ *
+ * A partially-set write mask means that each enabled channel gets
+ * the value from a consecutive channel of the rhs. For example,
+ * to write just .xyw of gl_FrontColor with color:
+ *
+ * (assign (constant bool (1)) (xyw)
+ * (var_ref gl_FragColor)
+ * (swiz xyw (var_ref color)))
+ */
+ unsigned write_mask:4;
+};
+
+/* Update ir_expression::num_operands() and operator_strs when
+ * updating this list.
+ */
+enum ir_expression_operation {
+ ir_unop_bit_not,
+ ir_unop_logic_not,
+ ir_unop_neg,
+ ir_unop_abs,
+ ir_unop_sign,
+ ir_unop_rcp,
+ ir_unop_rsq,
+ ir_unop_sqrt,
+ ir_unop_exp, /**< Log base e on gentype */
+ ir_unop_log, /**< Natural log on gentype */
+ ir_unop_exp2,
+ ir_unop_log2,
+ ir_unop_f2i, /**< Float-to-integer conversion. */
+ ir_unop_i2f, /**< Integer-to-float conversion. */
+ ir_unop_f2b, /**< Float-to-boolean conversion */
+ ir_unop_b2f, /**< Boolean-to-float conversion */
+ ir_unop_i2b, /**< int-to-boolean conversion */
+ ir_unop_b2i, /**< Boolean-to-int conversion */
+ ir_unop_u2f, /**< Unsigned-to-float conversion. */
+ ir_unop_any,
+
+ /**
+ * \name Unary floating-point rounding operations.
+ */
+ /*@{*/
+ ir_unop_trunc,
+ ir_unop_ceil,
+ ir_unop_floor,
+ ir_unop_fract,
+ ir_unop_round_even,
+ /*@}*/
+
+ /**
+ * \name Trigonometric operations.
+ */
+ /*@{*/
+ ir_unop_sin,
+ ir_unop_cos,
+ ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */
+ ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */
+ /*@}*/
+
+ /**
+ * \name Partial derivatives.
+ */
+ /*@{*/
+ ir_unop_dFdx,
+ ir_unop_dFdy,
+ /*@}*/
+
+ ir_unop_noise,
+
+ /**
+ * A sentinel marking the last of the unary operations.
+ */
+ ir_last_unop = ir_unop_noise,
+
+ ir_binop_add,
+ ir_binop_sub,
+ ir_binop_mul,
+ ir_binop_div,
+
+ /**
+ * Takes one of two combinations of arguments:
+ *
+ * - mod(vecN, vecN)
+ * - mod(vecN, float)
+ *
+ * Does not take integer types.
+ */
+ ir_binop_mod,
+
+ /**
+ * \name Binary comparison operators which return a boolean vector.
+ * The type of both operands must be equal.
+ */
+ /*@{*/
+ ir_binop_less,
+ ir_binop_greater,
+ ir_binop_lequal,
+ ir_binop_gequal,
+ ir_binop_equal,
+ ir_binop_nequal,
+ /**
+ * Returns single boolean for whether all components of operands[0]
+ * equal the components of operands[1].
+ */
+ ir_binop_all_equal,
+ /**
+ * Returns single boolean for whether any component of operands[0]
+ * is not equal to the corresponding component of operands[1].
+ */
+ ir_binop_any_nequal,
+ /*@}*/
+
+ /**
+ * \name Bit-wise binary operations.
+ */
+ /*@{*/
+ ir_binop_lshift,
+ ir_binop_rshift,
+ ir_binop_bit_and,
+ ir_binop_bit_xor,
+ ir_binop_bit_or,
+ /*@}*/
+
+ ir_binop_logic_and,
+ ir_binop_logic_xor,
+ ir_binop_logic_or,
+
+ ir_binop_dot,
+ ir_binop_min,
+ ir_binop_max,
+
+ ir_binop_pow,
+
+ /**
+ * A sentinel marking the last of the binary operations.
+ */
+ ir_last_binop = ir_binop_pow,
+
+ ir_quadop_vector,
+
+ /**
+ * A sentinel marking the last of all operations.
+ */
+ ir_last_opcode = ir_last_binop
+};
+
+class ir_expression : public ir_rvalue {
+public:
+ /**
+ * Constructor for unary operation expressions
+ */
+ ir_expression(int op, const struct glsl_type *type, ir_rvalue *);
+ ir_expression(int op, ir_rvalue *);
+
+ /**
+ * Constructor for binary operation expressions
+ */
+ ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *, ir_rvalue *);
+ ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
+
+ /**
+ * Constructor for quad operator expressions
+ */
+ ir_expression(int op, const struct glsl_type *type,
+ ir_rvalue *, ir_rvalue *, ir_rvalue *, ir_rvalue *);
+
+ virtual ir_expression *as_expression()
+ {
+ return this;
+ }
+
+ virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ /**
+ * Attempt to constant-fold the expression
+ *
+ * If the expression cannot be constant folded, this method will return
+ * \c NULL.
+ */
+ virtual ir_constant *constant_expression_value();
+
+ /**
+ * Determine the number of operands used by an expression
+ */
+ static unsigned int get_num_operands(ir_expression_operation);
+
+ /**
+ * Determine the number of operands used by an expression
+ */
+ unsigned int get_num_operands() const
+ {
+ return (this->operation == ir_quadop_vector)
+ ? this->type->vector_elements : get_num_operands(operation);
+ }
+
+ /**
+ * Return a string representing this expression's operator.
+ */
+ const char *operator_string();
+
+ /**
+ * Return a string representing this expression's operator.
+ */
+ static const char *operator_string(ir_expression_operation);
+
+
+ /**
+ * Do a reverse-lookup to translate the given string into an operator.
+ */
+ static ir_expression_operation get_operator(const char *);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_expression_operation operation;
+ ir_rvalue *operands[4];
+};
+
+
+/**
+ * IR instruction representing a function call
+ */
+class ir_call : public ir_rvalue {
+public:
+ ir_call(ir_function_signature *callee, exec_list *actual_parameters)
+ : callee(callee)
+ {
+ ir_type = ir_type_call;
+ assert(callee->return_type != NULL);
+ type = callee->return_type;
+ actual_parameters->move_nodes_to(& this->actual_parameters);
+ }
+
+ virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_call *as_call()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get a generic ir_call object when an error occurs
+ *
+ * Any allocation will be performed with 'ctx' as talloc owner.
+ */
+ static ir_call *get_error_instruction(void *ctx);
+
+ /**
+ * Get an iterator for the set of acutal parameters
+ */
+ exec_list_iterator iterator()
+ {
+ return actual_parameters.iterator();
+ }
+
+ /**
+ * Get the name of the function being called.
+ */
+ const char *callee_name() const
+ {
+ return callee->function_name();
+ }
+
+ /**
+ * Get the function signature bound to this function call
+ */
+ ir_function_signature *get_callee()
+ {
+ return callee;
+ }
+
+ /**
+ * Set the function call target
+ */
+ void set_callee(ir_function_signature *sig);
+
+ /**
+ * Generates an inline version of the function before @ir,
+ * returning the return value of the function.
+ */
+ ir_rvalue *generate_inline(ir_instruction *ir);
+
+ /* List of ir_rvalue of paramaters passed in this call. */
+ exec_list actual_parameters;
+
+private:
+ ir_call()
+ : callee(NULL)
+ {
+ this->ir_type = ir_type_call;
+ }
+
+ ir_function_signature *callee;
+};
+
+
+/**
+ * \name Jump-like IR instructions.
+ *
+ * These include \c break, \c continue, \c return, and \c discard.
+ */
+/*@{*/
+class ir_jump : public ir_instruction {
+protected:
+ ir_jump()
+ {
+ ir_type = ir_type_unset;
+ }
+};
+
+class ir_return : public ir_jump {
+public:
+ ir_return()
+ : value(NULL)
+ {
+ this->ir_type = ir_type_return;
+ }
+
+ ir_return(ir_rvalue *value)
+ : value(value)
+ {
+ this->ir_type = ir_type_return;
+ }
+
+ virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_return *as_return()
+ {
+ return this;
+ }
+
+ ir_rvalue *get_value() const
+ {
+ return value;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *value;
+};
+
+
+/**
+ * Jump instructions used inside loops
+ *
+ * These include \c break and \c continue. The \c break within a loop is
+ * different from the \c break within a switch-statement.
+ *
+ * \sa ir_switch_jump
+ */
+class ir_loop_jump : public ir_jump {
+public:
+ enum jump_mode {
+ jump_break,
+ jump_continue
+ };
+
+ ir_loop_jump(jump_mode mode)
+ {
+ this->ir_type = ir_type_loop_jump;
+ this->mode = mode;
+ this->loop = loop;
+ }
+
+ virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ bool is_break() const
+ {
+ return mode == jump_break;
+ }
+
+ bool is_continue() const
+ {
+ return mode == jump_continue;
+ }
+
+ /** Mode selector for the jump instruction. */
+ enum jump_mode mode;
+private:
+ /** Loop containing this break instruction. */
+ ir_loop *loop;
+};
+
+/**
+ * IR instruction representing discard statements.
+ */
+class ir_discard : public ir_jump {
+public:
+ ir_discard()
+ {
+ this->ir_type = ir_type_discard;
+ this->condition = NULL;
+ }
+
+ ir_discard(ir_rvalue *cond)
+ {
+ this->ir_type = ir_type_discard;
+ this->condition = cond;
+ }
+
+ virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ virtual ir_discard *as_discard()
+ {
+ return this;
+ }
+
+ ir_rvalue *condition;
+};
+/*@}*/
+
+
+/**
+ * Texture sampling opcodes used in ir_texture
+ */
+enum ir_texture_opcode {
+ ir_tex, /**< Regular texture look-up */
+ ir_txb, /**< Texture look-up with LOD bias */
+ ir_txl, /**< Texture look-up with explicit LOD */
+ ir_txd, /**< Texture look-up with partial derivatvies */
+ ir_txf /**< Texel fetch with explicit LOD */
+};
+
+
+/**
+ * IR instruction to sample a texture
+ *
+ * The specific form of the IR instruction depends on the \c mode value
+ * selected from \c ir_texture_opcodes. In the printed IR, these will
+ * appear as:
+ *
+ * Texel offset
+ * | Projection divisor
+ * | | Shadow comparitor
+ * | | |
+ * v v v
+ * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
+ * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
+ * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
+ * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
+ * (txf (sampler) (coordinate) (0 0 0) (lod))
+ */
+class ir_texture : public ir_rvalue {
+public:
+ ir_texture(enum ir_texture_opcode op)
+ : op(op), projector(NULL), shadow_comparitor(NULL)
+ {
+ this->ir_type = ir_type_texture;
+ }
+
+ virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Return a string representing the ir_texture_opcode.
+ */
+ const char *opcode_string();
+
+ /** Set the sampler and infer the type. */
+ void set_sampler(ir_dereference *sampler);
+
+ /**
+ * Do a reverse-lookup to translate a string into an ir_texture_opcode.
+ */
+ static ir_texture_opcode get_opcode(const char *);
+
+ enum ir_texture_opcode op;
+
+ /** Sampler to use for the texture access. */
+ ir_dereference *sampler;
+
+ /** Texture coordinate to sample */
+ ir_rvalue *coordinate;
+
+ /**
+ * Value used for projective divide.
+ *
+ * If there is no projective divide (the common case), this will be
+ * \c NULL. Optimization passes should check for this to point to a constant
+ * of 1.0 and replace that with \c NULL.
+ */
+ ir_rvalue *projector;
+
+ /**
+ * Coordinate used for comparison on shadow look-ups.
+ *
+ * If there is no shadow comparison, this will be \c NULL. For the
+ * \c ir_txf opcode, this *must* be \c NULL.
+ */
+ ir_rvalue *shadow_comparitor;
+
+ /** Explicit texel offsets. */
+ signed char offsets[3];
+
+ union {
+ ir_rvalue *lod; /**< Floating point LOD */
+ ir_rvalue *bias; /**< Floating point LOD bias */
+ struct {
+ ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */
+ ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */
+ } grad;
+ } lod_info;
+};
+
+
+struct ir_swizzle_mask {
+ unsigned x:2;
+ unsigned y:2;
+ unsigned z:2;
+ unsigned w:2;
+
+ /**
+ * Number of components in the swizzle.
+ */
+ unsigned num_components:3;
+
+ /**
+ * Does the swizzle contain duplicate components?
+ *
+ * L-value swizzles cannot contain duplicate components.
+ */
+ unsigned has_duplicates:1;
+};
+
+
+class ir_swizzle : public ir_rvalue {
+public:
+ ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+ unsigned count);
+
+ ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count);
+
+ ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
+
+ virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_swizzle *as_swizzle()
+ {
+ return this;
+ }
+
+ /**
+ * Construct an ir_swizzle from the textual representation. Can fail.
+ */
+ static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ bool is_lvalue()
+ {
+ return val->is_lvalue() && !mask.has_duplicates;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced();
+
+ ir_rvalue *val;
+ ir_swizzle_mask mask;
+
+private:
+ /**
+ * Initialize the mask component of a swizzle
+ *
+ * This is used by the \c ir_swizzle constructors.
+ */
+ void init_mask(const unsigned *components, unsigned count);
+};
+
+
+class ir_dereference : public ir_rvalue {
+public:
+ virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+ virtual ir_dereference *as_dereference()
+ {
+ return this;
+ }
+
+ bool is_lvalue();
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced() = 0;
+};
+
+
+class ir_dereference_variable : public ir_dereference {
+public:
+ ir_dereference_variable(ir_variable *var);
+
+ virtual ir_dereference_variable *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_dereference_variable *as_dereference_variable()
+ {
+ return this;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->var;
+ }
+
+ virtual ir_variable *whole_variable_referenced()
+ {
+ /* ir_dereference_variable objects always dereference the entire
+ * variable. However, if this dereference is dereferenced by anything
+ * else, the complete deferefernce chain is not a whole-variable
+ * dereference. This method should only be called on the top most
+ * ir_rvalue in a dereference chain.
+ */
+ return this->var;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Object being dereferenced.
+ */
+ ir_variable *var;
+};
+
+
+class ir_dereference_array : public ir_dereference {
+public:
+ ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
+
+ ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+
+ virtual ir_dereference_array *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_dereference_array *as_dereference_array()
+ {
+ return this;
+ }
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->array->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *array;
+ ir_rvalue *array_index;
+
+private:
+ void set_array(ir_rvalue *value);
+};
+
+
+class ir_dereference_record : public ir_dereference {
+public:
+ ir_dereference_record(ir_rvalue *value, const char *field);
+
+ ir_dereference_record(ir_variable *var, const char *field);
+
+ virtual ir_dereference_record *clone(void *mem_ctx,
+ struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ /**
+ * Get the variable that is ultimately referenced by an r-value
+ */
+ virtual ir_variable *variable_referenced()
+ {
+ return this->record->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *record;
+ const char *field;
+};
+
+
+/**
+ * Data stored in an ir_constant
+ */
+union ir_constant_data {
+ unsigned u[16];
+ int i[16];
+ float f[16];
+ bool b[16];
+};
+
+
+class ir_constant : public ir_rvalue {
+public:
+ ir_constant(const struct glsl_type *type, const ir_constant_data *data);
+ ir_constant(bool b);
+ ir_constant(unsigned int u);
+ ir_constant(int i);
+ ir_constant(float f);
+
+ /**
+ * Construct an ir_constant from a list of ir_constant values
+ */
+ ir_constant(const struct glsl_type *type, exec_list *values);
+
+ /**
+ * Construct an ir_constant from a scalar component of another ir_constant
+ *
+ * The new \c ir_constant inherits the type of the component from the
+ * source constant.
+ *
+ * \note
+ * In the case of a matrix constant, the new constant is a scalar, \b not
+ * a vector.
+ */
+ ir_constant(const ir_constant *c, unsigned i);
+
+ /**
+ * Return a new ir_constant of the specified type containing all zeros.
+ */
+ static ir_constant *zero(void *mem_ctx, const glsl_type *type);
+
+ virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value();
+
+ virtual ir_constant *as_constant()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Get a particular component of a constant as a specific type
+ *
+ * This is useful, for example, to get a value from an integer constant
+ * as a float or bool. This appears frequently when constructors are
+ * called with all constant parameters.
+ */
+ /*@{*/
+ bool get_bool_component(unsigned i) const;
+ float get_float_component(unsigned i) const;
+ int get_int_component(unsigned i) const;
+ unsigned get_uint_component(unsigned i) const;
+ /*@}*/
+
+ ir_constant *get_array_element(unsigned i) const;
+
+ ir_constant *get_record_field(const char *name);
+
+ /**
+ * Determine whether a constant has the same value as another constant
+ *
+ * \sa ir_constant::is_zero, ir_constant::is_one,
+ * ir_constant::is_negative_one
+ */
+ bool has_value(const ir_constant *) const;
+
+ virtual bool is_zero() const;
+ virtual bool is_one() const;
+ virtual bool is_negative_one() const;
+
+ /**
+ * Value of the constant.
+ *
+ * The field used to back the values supplied by the constant is determined
+ * by the type associated with the \c ir_instruction. Constants may be
+ * scalars, vectors, or matrices.
+ */
+ union ir_constant_data value;
+
+ /* Array elements */
+ ir_constant **array_elements;
+
+ /* Structure fields */
+ exec_list components;
+
+private:
+ /**
+ * Parameterless constructor only used by the clone method
+ */
+ ir_constant(void);
+};
+
+/*@}*/
+
+/**
+ * Apply a visitor to each IR node in a list
+ */
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor);
+
+/**
+ * Validate invariants on each IR node in a list
+ */
+void validate_ir_tree(exec_list *instructions);
+
+/**
+ * Make a clone of each IR instruction in a list
+ *
+ * \param in List of IR instructions that are to be cloned
+ * \param out List to hold the cloned instructions
+ */
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
+
+extern void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_release_functions(void);
+
+extern void
+reparent_ir(exec_list *list, void *mem_ctx);
+
+struct glsl_symbol_table;
+
+extern void
+import_prototypes(const exec_list *source, exec_list *dest,
+ struct glsl_symbol_table *symbols, void *mem_ctx);
+
+extern bool
+ir_has_call(ir_instruction *ir);
+
+extern void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
+
+#endif /* IR_H */
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index bf7a56353..4332338df 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -382,6 +382,32 @@ cross_validate_globals(struct gl_shader_program *prog,
existing->explicit_location = true;
}
+ /* Validate layout qualifiers for gl_FragDepth.
+ *
+ * From the AMD_conservative_depth spec:
+ * "If gl_FragDepth is redeclared in any fragment shader in
+ * a program, it must be redeclared in all fragment shaders in that
+ * program that have static assignments to gl_FragDepth. All
+ * redeclarations of gl_FragDepth in all fragment shaders in
+ * a single program must have the same set of qualifiers."
+ */
+ if (strcmp(var->name, "gl_FragDepth") == 0) {
+ bool layout_declared = var->depth_layout != ir_depth_layout_none;
+ bool layout_differs = var->depth_layout != existing->depth_layout;
+ if (layout_declared && layout_differs) {
+ linker_error_printf(prog,
+ "All redeclarations of gl_FragDepth in all fragment shaders "
+ "in a single program must have the same set of qualifiers.");
+ }
+ if (var->used && layout_differs) {
+ linker_error_printf(prog,
+ "If gl_FragDepth is redeclared with a layout qualifier in"
+ "any fragment shader, it must be redeclared with the same"
+ "layout qualifier in all fragment shaders that have"
+ "assignments to gl_FragDepth");
+ }
+ }
+
/* FINISHME: Handle non-constant initializers.
*/
if (var->constant_value != NULL) {
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 7d15e3a50..aaef337ac 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -250,6 +250,7 @@ static const struct extension extension_table[] = {
/* Vendor extensions */
{ "GL_3DFX_texture_compression_FXT1", o(TDFX_texture_compression_FXT1), GL },
+ { "GL_AMD_conservative_depth", o(AMD_conservative_depth), GL | ES2 },
{ "GL_APPLE_client_storage", o(APPLE_client_storage), GL },
{ "GL_APPLE_object_purgeable", o(APPLE_object_purgeable), GL },
{ "GL_APPLE_packed_pixels", o(APPLE_packed_pixels), GL },
@@ -730,78 +731,67 @@ _mesa_extension_is_enabled( struct gl_context *ctx, const char *name )
/**
- * Append string 'b' onto string 'a'. Free 'a' and return new string.
- */
-static char *
-append(const char *a, const char *b)
-{
- const GLuint aLen = a ? strlen(a) : 0;
- const GLuint bLen = b ? strlen(b) : 0;
- char *s = calloc(1, aLen + bLen + 1);
- if (s) {
- if (a)
- memcpy(s, a, aLen);
- if (b)
- memcpy(s + aLen, b, bLen);
- s[aLen + bLen] = '\0';
- }
- if (a)
- free((void *) a);
- return s;
-}
-
-
-/**
- * Check the MESA_EXTENSION_OVERRIDE env var.
- * For extension names that are recognized, turn them on. For extension
- * names that are recognized and prefixed with '-', turn them off.
- * Return a string of the unknown/leftover names.
+ * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable.
+ *
+ * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to
+ * enable or disable. The list is processed thus:
+ * - Enable recognized extension names that are prefixed with '+'.
+ * - Disable recognized extension names that are prefixed with '-'.
+ * - Enable recognized extension names that are not prefixed.
+ * - Collect unrecognized extension names in a new string.
*
- * Returnd string needs to be freed.
+ * \return Space-separated list of unrecognized extension names (which must
+ * be freed). Does not return \c NULL.
*/
static char *
get_extension_override( struct gl_context *ctx )
{
- const char *envExt = _mesa_getenv("MESA_EXTENSION_OVERRIDE");
- char *extraExt = NULL;
- char ext[1000];
- GLuint extLen = 0;
- GLuint i;
- GLboolean disableExt = GL_FALSE;
-
- if (!envExt)
- return NULL;
+ const char *env_const= _mesa_getenv("MESA_EXTENSION_OVERRIDE");
+ char *env;
+ char *ext;
+ char *extra_exts;
+ int len;
+
+ if (env_const == NULL) {
+ /* Return the empty string rather than NULL. This simplifies the logic
+ * of client functions. */
+ return calloc(1, sizeof(char));
+ }
- for (i = 0; ; i++) {
- if (envExt[i] == '\0' || envExt[i] == ' ') {
- /* terminate/process 'ext' if extLen > 0 */
- if (extLen > 0) {
- assert(extLen < sizeof(ext));
- /* enable extension named by 'ext' */
- ext[extLen] = 0;
- if (!set_extension(ctx, ext, !disableExt)) {
- /* unknown extension name, append it to extraExt */
- if (extraExt) {
- extraExt = append(extraExt, " ");
- }
- extraExt = append(extraExt, ext);
- }
- extLen = 0;
- disableExt = GL_FALSE;
- }
- if (envExt[i] == '\0')
- break;
- }
- else if (envExt[i] == '-') {
- disableExt = GL_TRUE;
+ /* extra_exts: List of unrecognized extensions. */
+ extra_exts = calloc(strlen(env_const), sizeof(char));
+
+ /* Copy env_const because strtok() is destructive. */
+ env = strdup(env_const);
+ for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
+ int enable;
+ int recognized;
+ switch (ext[0]) {
+ case '+':
+ enable = 1;
+ ++ext;
+ break;
+ case '-':
+ enable = 0;
+ ++ext;
+ break;
+ default:
+ enable = 1;
+ break;
}
- else {
- /* accumulate this non-space character */
- ext[extLen++] = envExt[i];
+ recognized = set_extension(ctx, ext, enable);
+ if (!recognized) {
+ strcat(extra_exts, ext);
+ strcat(extra_exts, " ");
}
}
- return extraExt;
+ /* Remove trailing space. */
+ len = strlen(extra_exts);
+ if (extra_exts[len - 1] == ' ')
+ extra_exts[len - 1] = '\0';
+
+ return extra_exts;
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 4a039338d..37f39ceef 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -867,6 +867,23 @@ struct gl_fog_attrib
};
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
+ * a layout qualifier.
+ *
+ * \see enum ir_depth_layout
+ */
+enum gl_frag_depth_layout {
+ FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */
+ FRAG_DEPTH_LAYOUT_ANY,
+ FRAG_DEPTH_LAYOUT_GREATER,
+ FRAG_DEPTH_LAYOUT_LESS,
+ FRAG_DEPTH_LAYOUT_UNCHANGED
+};
+
+
/**
* Hint attribute group (GL_HINT_BIT).
*
@@ -1889,6 +1906,7 @@ struct gl_fragment_program
GLboolean UsesKill; /**< shader uses KIL instruction */
GLboolean OriginUpperLeft;
GLboolean PixelCenterInteger;
+ enum gl_frag_depth_layout FragDepthLayout;
};
@@ -2824,6 +2842,7 @@ struct gl_extensions
GLboolean EXT_vertex_array_set;
GLboolean OES_standard_derivatives;
/* vendor extensions */
+ GLboolean AMD_conservative_depth;
GLboolean APPLE_client_storage;
GLboolean APPLE_packed_pixels;
GLboolean APPLE_vertex_array_object;
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c
index 325fb9ebc..2542cea85 100644
--- a/mesalib/src/mesa/main/texformat.c
+++ b/mesalib/src/mesa/main/texformat.c
@@ -1,597 +1,608 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.7
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (c) 2008-2009 VMware, Inc.
- *
- * 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 texformat.c
- * Texture formats.
- *
- * \author Gareth Hughes
- * \author Brian Paul
- */
-
-
-#include "context.h"
-#include "mfeatures.h"
-#include "mtypes.h"
-#include "texcompress.h"
-#include "texformat.h"
-
-#define RETURN_IF_SUPPORTED(f) do { \
- if (ctx->TextureFormatSupported[f]) \
- return f; \
-} while (0)
-
-/**
- * Choose an appropriate texture format given the format, type and
- * internalFormat parameters passed to glTexImage().
- *
- * \param ctx the GL context.
- * \param internalFormat user's prefered internal texture format.
- * \param format incoming image pixel format.
- * \param type incoming image data type.
- *
- * \return a pointer to a gl_texture_format object which describes the
- * choosen texture format, or NULL on failure.
- *
- * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers
- * will typically override this function with a specialized version.
- */
-gl_format
-_mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
- GLenum format, GLenum type )
-{
- (void) format;
- (void) type;
-
- switch (internalFormat) {
- /* shallow RGBA formats */
- case 4:
- case GL_RGBA:
- if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
- } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555);
- }
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
-
- case GL_RGBA8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- case GL_RGB5_A1:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555);
- break;
- case GL_RGBA2:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444_REV); /* just to test another format*/
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
- break;
- case GL_RGBA4:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
- break;
-
- /* deep RGBA formats */
- case GL_RGB10_A2:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- case GL_RGBA12:
- case GL_RGBA16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
-
- /* shallow RGB formats */
- case 3:
- case GL_RGB:
- case GL_RGB8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- case GL_R3_G3_B2:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332);
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- case GL_RGB4:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); /* just to test another format */
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565);
- break;
- case GL_RGB5:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565);
- break;
-
- /* deep RGB formats */
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
-
- /* Alpha formats */
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
- break;
-
- case GL_ALPHA12:
- case GL_ALPHA16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_A16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
- break;
-
- /* Luminance formats */
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
- break;
-
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_L16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
- break;
-
- /* Luminance/Alpha formats */
- case GL_LUMINANCE4_ALPHA4:
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL44);
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
- break;
-
- case 2:
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE6_ALPHA2:
- case GL_LUMINANCE8_ALPHA8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
- break;
-
- case GL_LUMINANCE12_ALPHA4:
- case GL_LUMINANCE12_ALPHA12:
- case GL_LUMINANCE16_ALPHA16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL1616);
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
- break;
-
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
- break;
-
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_I16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
- break;
-
- case GL_COLOR_INDEX:
- case GL_COLOR_INDEX1_EXT:
- case GL_COLOR_INDEX2_EXT:
- case GL_COLOR_INDEX4_EXT:
- case GL_COLOR_INDEX12_EXT:
- case GL_COLOR_INDEX16_EXT:
- case GL_COLOR_INDEX8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_CI8);
- break;
-
- default:
- ; /* fallthrough */
- }
-
- if (ctx->Extensions.ARB_depth_texture) {
- switch (internalFormat) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- RETURN_IF_SUPPORTED(MESA_FORMAT_Z32);
- RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
- break;
- case GL_DEPTH_COMPONENT16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_Z16);
- RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
- default:
- ; /* fallthrough */
- }
- }
-
- switch (internalFormat) {
- case GL_COMPRESSED_ALPHA_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
- break;
- case GL_COMPRESSED_LUMINANCE_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
- break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
- break;
- case GL_COMPRESSED_INTENSITY_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
- break;
- case GL_COMPRESSED_RGB_ARB:
- if (ctx->Extensions.EXT_texture_compression_s3tc ||
- ctx->Extensions.S3_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1);
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- case GL_COMPRESSED_RGBA_ARB:
- if (ctx->Extensions.EXT_texture_compression_s3tc ||
- ctx->Extensions.S3_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1);
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
- break;
- default:
- ; /* fallthrough */
- }
-
- if (ctx->Extensions.MESA_ycbcr_texture) {
- if (internalFormat == GL_YCBCR_MESA) {
- if (type == GL_UNSIGNED_SHORT_8_8_MESA)
- RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR);
- else
- RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV);
- }
- }
-
-#if FEATURE_texture_fxt1
- if (ctx->Extensions.TDFX_texture_compression_FXT1) {
- switch (internalFormat) {
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1);
- break;
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1);
- break;
- default:
- ; /* fallthrough */
- }
- }
-#endif
-
-#if FEATURE_texture_s3tc
- if (ctx->Extensions.EXT_texture_compression_s3tc) {
- switch (internalFormat) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT1);
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3);
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT5);
- break;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.S3_s3tc) {
- switch (internalFormat) {
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
- break;
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3);
- break;
- default:
- ; /* fallthrough */
- }
- }
-#endif
-
- if (ctx->Extensions.ARB_texture_float) {
- switch (internalFormat) {
- case GL_ALPHA16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16);
- break;
- case GL_ALPHA32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32);
- break;
- case GL_LUMINANCE16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16);
- break;
- case GL_LUMINANCE32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32);
- break;
- case GL_LUMINANCE_ALPHA16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16);
- break;
- case GL_LUMINANCE_ALPHA32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32);
- break;
- case GL_INTENSITY16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16);
- break;
- case GL_INTENSITY32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32);
- break;
- case GL_RGB16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16);
- break;
- case GL_RGB32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32);
- break;
- case GL_RGBA16F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
- break;
- case GL_RGBA32F_ARB:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
- break;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.EXT_packed_depth_stencil) {
- switch (internalFormat) {
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_S8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
- break;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.ATI_envmap_bumpmap) {
- switch (internalFormat) {
- case GL_DUDV_ATI:
- case GL_DU8DV8_ATI:
- RETURN_IF_SUPPORTED(MESA_FORMAT_DUDV8);
- break;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->Extensions.MESA_texture_signed_rgba) {
- switch (internalFormat) {
- case GL_RGBA_SNORM:
- case GL_RGBA8_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV);
- break;
- default:
- ; /* fallthrough */
- }
- }
-
- if (ctx->VersionMajor * 10 + ctx->VersionMinor >= 31) {
- switch (internalFormat) {
- case GL_RED_SNORM:
- case GL_R8_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R8);
- break;
- case GL_RG_SNORM:
- case GL_RG8_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG88);
- break;
- case GL_RGB_SNORM:
- case GL_RGB8_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888);
- break;
- case GL_RGBA_SNORM:
- case GL_RGBA8_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888);
- break;
- case GL_R16_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R_16);
- break;
- case GL_RG16_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG_16);
- break;
- case GL_RGB16_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16);
- break;
- case GL_RGBA16_SNORM:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16);
- break;
- default:
- ; /* fall-through */
- }
- }
-
-#if FEATURE_EXT_texture_sRGB
- if (ctx->Extensions.EXT_texture_sRGB) {
- switch (internalFormat) {
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SL8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SLUMINANCE_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SL8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SRGB_EXT:
-#if FEATURE_texture_s3tc
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1);
-#endif
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
-#if FEATURE_texture_s3tc
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */
-#endif
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
-#if FEATURE_texture_s3tc
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT1);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- if (ctx->Extensions.EXT_texture_compression_s3tc)
- RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT5);
- RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
- break;
-#endif
- default:
- ; /* fallthrough */
- }
- }
-#endif /* FEATURE_EXT_texture_sRGB */
-
- if (ctx->Extensions.EXT_texture_integer) {
- switch (internalFormat) {
- case GL_RGBA32UI_EXT:
- case GL_RGB32UI_EXT:
- case GL_ALPHA32UI_EXT:
- case GL_INTENSITY32UI_EXT:
- case GL_LUMINANCE32UI_EXT:
- case GL_LUMINANCE_ALPHA32UI_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
- break;
- case GL_RGBA16UI_EXT:
- case GL_RGB16UI_EXT:
- case GL_ALPHA16UI_EXT:
- case GL_INTENSITY16UI_EXT:
- case GL_LUMINANCE16UI_EXT:
- case GL_LUMINANCE_ALPHA16UI_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
- break;
- case GL_RGBA8UI_EXT:
- case GL_RGB8UI_EXT:
- case GL_ALPHA8UI_EXT:
- case GL_INTENSITY8UI_EXT:
- case GL_LUMINANCE8UI_EXT:
- case GL_LUMINANCE_ALPHA8UI_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
- break;
- case GL_RGBA32I_EXT:
- case GL_RGB32I_EXT:
- case GL_ALPHA32I_EXT:
- case GL_INTENSITY32I_EXT:
- case GL_LUMINANCE32I_EXT:
- case GL_LUMINANCE_ALPHA32I_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32);
- break;
- case GL_RGBA16I_EXT:
- case GL_RGB16I_EXT:
- case GL_ALPHA16I_EXT:
- case GL_INTENSITY16I_EXT:
- case GL_LUMINANCE16I_EXT:
- case GL_LUMINANCE_ALPHA16I_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16);
- break;
- case GL_RGBA8I_EXT:
- case GL_RGB8I_EXT:
- case GL_ALPHA8I_EXT:
- case GL_INTENSITY8I_EXT:
- case GL_LUMINANCE8I_EXT:
- case GL_LUMINANCE_ALPHA8I_EXT:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8);
- break;
- }
- }
-
- if (ctx->Extensions.ARB_texture_rg) {
- switch (internalFormat) {
- case GL_R8:
- case GL_RED:
- case GL_COMPRESSED_RED:
- RETURN_IF_SUPPORTED(MESA_FORMAT_R8);
- break;
-
- case GL_R16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_R16);
- break;
-
- case GL_RG:
- case GL_RG8:
- case GL_COMPRESSED_RG:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RG88);
- break;
-
- case GL_RG16:
- RETURN_IF_SUPPORTED(MESA_FORMAT_RG1616);
- break;
-
- default:
- ; /* fallthrough */
- }
- }
-
- _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()");
- return MESA_FORMAT_NONE;
-}
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.7
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008-2009 VMware, Inc.
+ *
+ * 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 texformat.c
+ * Texture formats.
+ *
+ * \author Gareth Hughes
+ * \author Brian Paul
+ */
+
+
+#include "context.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "texcompress.h"
+#include "texformat.h"
+
+#define RETURN_IF_SUPPORTED(f) do { \
+ if (ctx->TextureFormatSupported[f]) \
+ return f; \
+} while (0)
+
+/**
+ * Choose an appropriate texture format given the format, type and
+ * internalFormat parameters passed to glTexImage().
+ *
+ * \param ctx the GL context.
+ * \param internalFormat user's prefered internal texture format.
+ * \param format incoming image pixel format.
+ * \param type incoming image data type.
+ *
+ * \return a pointer to a gl_texture_format object which describes the
+ * choosen texture format, or NULL on failure.
+ *
+ * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers
+ * will typically override this function with a specialized version.
+ */
+gl_format
+_mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ (void) format;
+ (void) type;
+
+ switch (internalFormat) {
+ /* shallow RGBA formats */
+ case 4:
+ case GL_RGBA:
+ if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
+ } else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555);
+ }
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+
+ case GL_RGBA8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ case GL_RGB5_A1:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB1555);
+ break;
+ case GL_RGBA2:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444_REV); /* just to test another format*/
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
+ break;
+ case GL_RGBA4:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB4444);
+ break;
+
+ /* deep RGBA formats */
+ case GL_RGB10_A2:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB2101010);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ case GL_RGBA12:
+ case GL_RGBA16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+
+ /* shallow RGB formats */
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ case GL_R3_G3_B2:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB332);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ case GL_RGB4:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565_REV); /* just to test another format */
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565);
+ break;
+ case GL_RGB5:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB565);
+ break;
+
+ /* deep RGB formats */
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+
+ /* Alpha formats */
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
+ break;
+
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_A16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
+ break;
+
+ /* Luminance formats */
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
+ break;
+
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_L16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
+ break;
+
+ /* Luminance/Alpha formats */
+ case GL_LUMINANCE4_ALPHA4:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL44);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
+ break;
+
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
+ break;
+
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL1616);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
+ break;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
+ break;
+
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_I16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
+ break;
+
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_CI8);
+ break;
+
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.ARB_depth_texture) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_Z32);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
+ break;
+ case GL_DEPTH_COMPONENT16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_Z16);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_A8);
+ break;
+ case GL_COMPRESSED_LUMINANCE_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_L8);
+ break;
+ case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_AL88);
+ break;
+ case GL_COMPRESSED_INTENSITY_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_I8);
+ break;
+ case GL_COMPRESSED_RGB_ARB:
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_XRGB8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ case GL_COMPRESSED_RGBA_ARB:
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.MESA_ycbcr_texture) {
+ if (internalFormat == GL_YCBCR_MESA) {
+ if (type == GL_UNSIGNED_SHORT_8_8_MESA)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR);
+ else
+ RETURN_IF_SUPPORTED(MESA_FORMAT_YCBCR_REV);
+ }
+ }
+
+#if FEATURE_texture_fxt1
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1);
+ break;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif
+
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT1);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT5);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.S3_s3tc) {
+ switch (internalFormat) {
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1);
+ break;
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif
+
+ if (ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_ALPHA16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT16);
+ break;
+ case GL_ALPHA32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ALPHA_FLOAT32);
+ break;
+ case GL_LUMINANCE16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT16);
+ break;
+ case GL_LUMINANCE32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_FLOAT32);
+ break;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16);
+ break;
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32);
+ break;
+ case GL_INTENSITY16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT16);
+ break;
+ case GL_INTENSITY32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_INTENSITY_FLOAT32);
+ break;
+ case GL_RGB16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT16);
+ break;
+ case GL_RGB32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FLOAT32);
+ break;
+ case GL_RGBA16F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT16);
+ break;
+ case GL_RGBA32F_ARB:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FLOAT32);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ switch (internalFormat) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_S8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_S8_Z24);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_DUDV8);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888_REV);
+ break;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->VersionMajor * 10 + ctx->VersionMinor >= 31) {
+ switch (internalFormat) {
+ case GL_RED_SNORM:
+ case GL_R8_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R8);
+ break;
+ case GL_RG_SNORM:
+ case GL_RG8_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG88);
+ break;
+ case GL_RGB_SNORM:
+ case GL_RGB8_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBX8888);
+ break;
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA8888);
+ break;
+ case GL_R16_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_R_16);
+ break;
+ case GL_RG16_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RG_16);
+ break;
+ case GL_RGB16_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGB_16);
+ break;
+ case GL_RGBA16_SNORM:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_RGBA_16);
+ break;
+ default:
+ ; /* fall-through */
+ }
+ }
+
+#if FEATURE_EXT_texture_sRGB
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ switch (internalFormat) {
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SL8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SL8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SLA8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SRGB_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1);
+#endif
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */
+#endif
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA8);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+#if FEATURE_texture_s3tc
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT1);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT5);
+ RETURN_IF_SUPPORTED(MESA_FORMAT_SARGB8);
+ break;
+#endif
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+
+ if (ctx->Extensions.EXT_texture_integer) {
+ switch (internalFormat) {
+ case GL_RGBA32UI_EXT:
+ case GL_RGB32UI_EXT:
+ case GL_ALPHA32UI_EXT:
+ case GL_INTENSITY32UI_EXT:
+ case GL_LUMINANCE32UI_EXT:
+ case GL_LUMINANCE_ALPHA32UI_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT32);
+ break;
+ case GL_RGBA16UI_EXT:
+ case GL_RGB16UI_EXT:
+ case GL_ALPHA16UI_EXT:
+ case GL_INTENSITY16UI_EXT:
+ case GL_LUMINANCE16UI_EXT:
+ case GL_LUMINANCE_ALPHA16UI_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT16);
+ break;
+ case GL_RGBA8UI_EXT:
+ case GL_RGB8UI_EXT:
+ case GL_ALPHA8UI_EXT:
+ case GL_INTENSITY8UI_EXT:
+ case GL_LUMINANCE8UI_EXT:
+ case GL_LUMINANCE_ALPHA8UI_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_UINT8);
+ break;
+ case GL_RGBA32I_EXT:
+ case GL_RGB32I_EXT:
+ case GL_ALPHA32I_EXT:
+ case GL_INTENSITY32I_EXT:
+ case GL_LUMINANCE32I_EXT:
+ case GL_LUMINANCE_ALPHA32I_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT32);
+ break;
+ case GL_RGBA16I_EXT:
+ case GL_RGB16I_EXT:
+ case GL_ALPHA16I_EXT:
+ case GL_INTENSITY16I_EXT:
+ case GL_LUMINANCE16I_EXT:
+ case GL_LUMINANCE_ALPHA16I_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT16);
+ break;
+ case GL_RGBA8I_EXT:
+ case GL_RGB8I_EXT:
+ case GL_ALPHA8I_EXT:
+ case GL_INTENSITY8I_EXT:
+ case GL_LUMINANCE8I_EXT:
+ case GL_LUMINANCE_ALPHA8I_EXT:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_INT8);
+ break;
+ }
+ }
+
+ if (ctx->Extensions.ARB_texture_rg) {
+ switch (internalFormat) {
+ case GL_R8:
+ case GL_RED:
+ case GL_COMPRESSED_RED:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_R8);
+ break;
+
+ case GL_R16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_R16);
+ break;
+
+ case GL_RG:
+ case GL_RG8:
+ case GL_COMPRESSED_RG:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RG88);
+ break;
+
+ case GL_RG16:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_RG1616);
+ break;
+
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_texture_format_BGRA8888) {
+ switch (internalFormat) {
+ case GL_BGRA:
+ RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+ break;
+
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()");
+ return MESA_FORMAT_NONE;
+}
+
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index ee3eae6cf..404b6c646 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -727,6 +727,29 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
fp->OriginUpperLeft = ir->origin_upper_left;
fp->PixelCenterInteger = ir->pixel_center_integer;
+
+ } else if (strcmp(ir->name, "gl_FragDepth") == 0) {
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+ switch (ir->depth_layout) {
+ case ir_depth_layout_none:
+ fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE;
+ break;
+ case ir_depth_layout_any:
+ fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY;
+ break;
+ case ir_depth_layout_greater:
+ fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER;
+ break;
+ case ir_depth_layout_less:
+ fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS;
+ break;
+ case ir_depth_layout_unchanged:
+ fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED;
+ break;
+ default:
+ assert(0);
+ break;
+ }
}
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
@@ -1452,18 +1475,17 @@ void
ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
{
variable_storage *entry = find_variable_storage(ir->var);
+ ir_variable *var = ir->var;
if (!entry) {
- switch (ir->var->mode) {
+ switch (var->mode) {
case ir_var_uniform:
- entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
- ir->var->location);
+ entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
+ var->location);
this->variables.push_tail(entry);
break;
case ir_var_in:
- case ir_var_out:
case ir_var_inout:
- case ir_var_system_value:
/* The linker assigns locations for varyings and attributes,
* including deprecated builtins (like gl_Color), user-assign
* generic attributes (glBindVertexLocation), and
@@ -1471,49 +1493,47 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
*
* FINISHME: We would hit this path for function arguments. Fix!
*/
- assert(ir->var->location != -1);
- if (ir->var->mode == ir_var_in ||
- ir->var->mode == ir_var_inout) {
- entry = new(mem_ctx) variable_storage(ir->var,
- PROGRAM_INPUT,
- ir->var->location);
-
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
- ir->var->location >= VERT_ATTRIB_GENERIC0) {
- _mesa_add_attribute(prog->Attributes,
- ir->var->name,
- _mesa_sizeof_glsl_type(ir->var->type->gl_type),
- ir->var->type->gl_type,
- ir->var->location - VERT_ATTRIB_GENERIC0);
- }
- } else if (ir->var->mode == ir_var_system_value) {
- entry = new(mem_ctx) variable_storage(ir->var,
- PROGRAM_SYSTEM_VALUE,
- ir->var->location);
- } else {
- entry = new(mem_ctx) variable_storage(ir->var,
- PROGRAM_OUTPUT,
- ir->var->location);
- }
-
+ assert(var->location != -1);
+ entry = new(mem_ctx) variable_storage(var,
+ PROGRAM_INPUT,
+ var->location);
+ if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
+ var->location >= VERT_ATTRIB_GENERIC0) {
+ _mesa_add_attribute(this->prog->Attributes,
+ var->name,
+ _mesa_sizeof_glsl_type(var->type->gl_type),
+ var->type->gl_type,
+ var->location - VERT_ATTRIB_GENERIC0);
+ }
+ break;
+ case ir_var_out:
+ assert(var->location != -1);
+ entry = new(mem_ctx) variable_storage(var,
+ PROGRAM_OUTPUT,
+ var->location);
break;
+ case ir_var_system_value:
+ entry = new(mem_ctx) variable_storage(var,
+ PROGRAM_SYSTEM_VALUE,
+ var->location);
+ break;
case ir_var_auto:
case ir_var_temporary:
- entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY,
+ entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
this->next_temp);
this->variables.push_tail(entry);
- next_temp += type_size(ir->var->type);
+ next_temp += type_size(var->type);
break;
}
if (!entry) {
- printf("Failed to make storage for %s\n", ir->var->name);
+ printf("Failed to make storage for %s\n", var->name);
exit(1);
}
}
- this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type);
+ this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type);
}
void
diff --git a/pixman/configure.ac b/pixman/configure.ac
index e2f73dc06..ab2ecde1b 100644
--- a/pixman/configure.ac
+++ b/pixman/configure.ac
@@ -795,3 +795,26 @@ AC_OUTPUT([pixman-1.pc
pixman/Makefile
pixman/pixman-version.h
test/Makefile])
+
+m4_if(m4_eval(pixman_minor % 2), [1], [
+ echo
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo
+ echo " Thanks for testing this development snapshot of pixman. Please"
+ echo " report any problems you find, either by sending email to "
+ echo
+ echo " pixman@lists.freedesktop.org"
+ echo
+ echo " or by filing a bug at "
+ echo
+ echo " https://bugs.freedesktop.org/enter_bug.cgi?product=pixman "
+ echo
+ echo " If you are looking for a stable release of pixman, please note "
+ echo " that stable releases have _even_ minor version numbers. Ie., "
+ echo " pixman-0.]m4_eval(pixman_minor & ~1)[.x are stable releases, whereas pixman-$PIXMAN_VERSION_MAJOR.$PIXMAN_VERSION_MINOR.$PIXMAN_VERSION_MICRO is a "
+ echo " development snapshot that may contain bugs and experimental "
+ echo " features. "
+ echo
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo
+])
diff --git a/pixman/pixman/pixman-arm-neon.c b/pixman/pixman/pixman-arm-neon.c
index e89cc3215..7d6c83775 100644
--- a/pixman/pixman/pixman-arm-neon.c
+++ b/pixman/pixman/pixman-arm-neon.c
@@ -1,435 +1,430 @@
-/*
- * Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of ARM Ltd not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. ARM Ltd makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Ian Rickards (ian.rickards@arm.com)
- * Author: Jonathan Morton (jonathan.morton@movial.com)
- * Author: Markku Vire (markku.vire@movial.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include "pixman-private.h"
-#include "pixman-arm-common.h"
-
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_x888_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_0565,
- uint16_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0888,
- uint8_t, 3, uint8_t, 3)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_0565,
- uint32_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_8888,
- uint16_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_8888_rev,
- uint8_t, 3, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0565_rev,
- uint8_t, 3, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_pixbuf_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_rpixbuf_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8_8,
- uint8_t, 1, uint8_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8888_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_0565,
- uint32_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_0565,
- uint8_t, 1, uint16_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_0565,
- uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_8888,
- uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_reverse_n_8888,
- uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, neon, in_n_8,
- uint8_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_0565,
- uint8_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8888,
- uint8_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_8888_ca,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8,
- uint8_t, 1, uint8_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8,
- uint8_t, 1, uint8_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8888,
- uint8_t, 1, uint32_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_8888,
- uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_0565,
- uint32_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_0565_n_0565,
- uint16_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, add_8888_n_8888,
- uint32_t, 1, uint32_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8_8_8,
- uint8_t, 1, uint8_t, 1, uint8_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_0565_8_0565,
- uint16_t, 1, uint8_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8_8888,
- uint32_t, 1, uint8_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8888_8888,
- uint32_t, 1, uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_8888,
- uint32_t, 1, uint8_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8888_8888,
- uint32_t, 1, uint32_t, 1, uint32_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_0565,
- uint32_t, 1, uint8_t, 1, uint16_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_0565_8_0565,
- uint16_t, 1, uint8_t, 1, uint16_t, 1)
-
-PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_8888, OVER,
- uint32_t, uint32_t)
-PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, OVER,
- uint32_t, uint16_t)
-PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, SRC,
- uint32_t, uint16_t)
-PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 0565_8888, SRC,
- uint16_t, uint32_t)
-
-void
-pixman_composite_src_n_8_asm_neon (int32_t w,
- int32_t h,
- uint8_t *dst,
- int32_t dst_stride,
- uint8_t src);
-
-void
-pixman_composite_src_n_0565_asm_neon (int32_t w,
- int32_t h,
- uint16_t *dst,
- int32_t dst_stride,
- uint16_t src);
-
-void
-pixman_composite_src_n_8888_asm_neon (int32_t w,
- int32_t h,
- uint32_t *dst,
- int32_t dst_stride,
- uint32_t src);
-
-static pixman_bool_t
-pixman_fill_neon (uint32_t *bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t _xor)
-{
- /* stride is always multiple of 32bit units in pixman */
- uint32_t byte_stride = stride * sizeof(uint32_t);
-
- switch (bpp)
- {
- case 8:
- pixman_composite_src_n_8_asm_neon (
- width,
- height,
- (uint8_t *)(((char *) bits) + y * byte_stride + x),
- byte_stride,
- _xor & 0xff);
- return TRUE;
- case 16:
- pixman_composite_src_n_0565_asm_neon (
- width,
- height,
- (uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
- byte_stride / 2,
- _xor & 0xffff);
- return TRUE;
- case 32:
- pixman_composite_src_n_8888_asm_neon (
- width,
- height,
- (uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
- byte_stride / 4,
- _xor);
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static pixman_bool_t
-pixman_blt_neon (uint32_t *src_bits,
- uint32_t *dst_bits,
- int src_stride,
- int dst_stride,
- int src_bpp,
- int dst_bpp,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- if (src_bpp != dst_bpp)
- return FALSE;
-
- switch (src_bpp)
- {
- case 16:
- pixman_composite_src_0565_0565_asm_neon (
- width, height,
- (uint16_t *)(((char *) dst_bits) +
- dst_y * dst_stride * 4 + dst_x * 2), dst_stride * 2,
- (uint16_t *)(((char *) src_bits) +
- src_y * src_stride * 4 + src_x * 2), src_stride * 2);
- return TRUE;
- case 32:
- pixman_composite_src_8888_8888_asm_neon (
- width, height,
- (uint32_t *)(((char *) dst_bits) +
- dst_y * dst_stride * 4 + dst_x * 4), dst_stride,
- (uint32_t *)(((char *) src_bits) +
- src_y * src_stride * 4 + src_x * 4), src_stride);
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static const pixman_fast_path_t arm_neon_fast_paths[] =
-{
- PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
- PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, neon_composite_src_0565_0565),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
- PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, neon_composite_src_0565_8888),
- PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, neon_composite_src_0565_8888),
- PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, neon_composite_src_0565_8888),
- PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, neon_composite_src_0565_8888),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, neon_composite_src_8888_8888),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, neon_composite_src_0888_0888),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, neon_composite_src_0888_8888_rev),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, neon_composite_src_0888_0565_rev),
- PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, neon_composite_src_pixbuf_8888),
- PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, neon_composite_src_rpixbuf_8888),
- PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, neon_composite_src_rpixbuf_8888),
- PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, neon_composite_src_pixbuf_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, neon_composite_over_n_8_8),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, neon_composite_over_n_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, neon_composite_over_n_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, neon_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, neon_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, neon_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, neon_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, neon_composite_over_n_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, neon_composite_over_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, neon_composite_over_n_8888),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, neon_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, neon_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, neon_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, neon_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, neon_composite_over_8888_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, neon_composite_over_8888_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, neon_composite_over_8888_n_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, neon_composite_over_8888_n_0565),
- PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, neon_composite_over_0565_n_0565),
- PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, neon_composite_over_0565_n_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, neon_composite_over_8888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, neon_composite_over_8888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, neon_composite_over_8888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, neon_composite_over_8888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, neon_composite_over_8888_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, neon_composite_over_8888_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, neon_composite_over_0565_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, neon_composite_over_0565_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_over_8888_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, neon_composite_over_8888_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, neon_composite_over_8888_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, neon_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, neon_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, neon_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, neon_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, neon_composite_add_n_8_8),
- PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, neon_composite_add_n_8_8888),
- PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, neon_composite_add_n_8_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8),
- PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, neon_composite_add_0565_8_0565),
- PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, neon_composite_add_0565_8_0565),
- PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, neon_composite_add_8888_8_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, neon_composite_add_8888_8_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add_8888_8888_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, neon_composite_add_8888_n_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, neon_composite_add_8888_n_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8_8),
- PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add_8888_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add_8888_8888),
- PIXMAN_STD_FAST_PATH (IN, solid, null, a8, neon_composite_in_n_8),
- PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, neon_composite_over_reverse_n_8888),
- PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, neon_composite_over_reverse_n_8888),
- PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, neon_composite_out_reverse_8_0565),
- PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, neon_composite_out_reverse_8_0565),
-
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
-
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
-
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
-
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
- /* Note: NONE repeat is not supported yet */
- SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
- SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
- SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
- SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
-
- { PIXMAN_OP_NONE },
-};
-
-static pixman_bool_t
-arm_neon_blt (pixman_implementation_t *imp,
- uint32_t * src_bits,
- uint32_t * dst_bits,
- int src_stride,
- int dst_stride,
- int src_bpp,
- int dst_bpp,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- if (!pixman_blt_neon (
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dst_x, dst_y, width, height))
-
- {
- return _pixman_implementation_blt (
- imp->delegate,
- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
- src_x, src_y, dst_x, dst_y, width, height);
- }
-
- return TRUE;
-}
-
-static pixman_bool_t
-arm_neon_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- if (pixman_fill_neon (bits, stride, bpp, x, y, width, height, xor))
- return TRUE;
-
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
-
-#define BIND_COMBINE_U(name) \
-void \
-pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \
- const uint32_t *dst, \
- const uint32_t *src, \
- const uint32_t *mask); \
- \
-void \
-pixman_composite_scanline_##name##_asm_neon (int32_t w, \
- const uint32_t *dst, \
- const uint32_t *src); \
- \
-static void \
-neon_combine_##name##_u (pixman_implementation_t *imp, \
- pixman_op_t op, \
- uint32_t * dest, \
- const uint32_t * src, \
- const uint32_t * mask, \
- int width) \
-{ \
- if (mask) \
- pixman_composite_scanline_##name##_mask_asm_neon (width, dest, \
- src, mask); \
- else \
- pixman_composite_scanline_##name##_asm_neon (width, dest, src); \
-}
-
-BIND_COMBINE_U (over)
-BIND_COMBINE_U (add)
-BIND_COMBINE_U (out_reverse)
-
-pixman_implementation_t *
-_pixman_implementation_create_arm_neon (void)
-{
-#ifdef USE_ARM_SIMD
- pixman_implementation_t *fallback = _pixman_implementation_create_arm_simd ();
-#else
- pixman_implementation_t *fallback = _pixman_implementation_create_fast_path ();
-#endif
- pixman_implementation_t *imp =
- _pixman_implementation_create (fallback, arm_neon_fast_paths);
-
- imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
- imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
- imp->combine_32[PIXMAN_OP_OUT_REVERSE] = neon_combine_out_reverse_u;
-
- imp->blt = arm_neon_blt;
- imp->fill = arm_neon_fill;
-
- return imp;
-}
+/*
+ * Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of ARM Ltd not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. ARM Ltd makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author: Ian Rickards (ian.rickards@arm.com)
+ * Author: Jonathan Morton (jonathan.morton@movial.com)
+ * Author: Markku Vire (markku.vire@movial.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "pixman-private.h"
+#include "pixman-arm-common.h"
+
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_x888_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_0565,
+ uint16_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0888,
+ uint8_t, 3, uint8_t, 3)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_0565,
+ uint32_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_8888,
+ uint16_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_8888_rev,
+ uint8_t, 3, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0565_rev,
+ uint8_t, 3, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_pixbuf_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_rpixbuf_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8_8,
+ uint8_t, 1, uint8_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8888_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_0565,
+ uint32_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_0565,
+ uint8_t, 1, uint16_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_0565,
+ uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_8888,
+ uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_reverse_n_8888,
+ uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, neon, in_n_8,
+ uint8_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_0565,
+ uint8_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8888,
+ uint8_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_8888_ca,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8,
+ uint8_t, 1, uint8_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8,
+ uint8_t, 1, uint8_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8888,
+ uint8_t, 1, uint32_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_8888,
+ uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_0565,
+ uint32_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_0565_n_0565,
+ uint16_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, add_8888_n_8888,
+ uint32_t, 1, uint32_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8_8_8,
+ uint8_t, 1, uint8_t, 1, uint8_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_0565_8_0565,
+ uint16_t, 1, uint8_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8_8888,
+ uint32_t, 1, uint8_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8888_8888,
+ uint32_t, 1, uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_8888,
+ uint32_t, 1, uint8_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8888_8888,
+ uint32_t, 1, uint32_t, 1, uint32_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_0565,
+ uint32_t, 1, uint8_t, 1, uint16_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_0565_8_0565,
+ uint16_t, 1, uint8_t, 1, uint16_t, 1)
+
+PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_8888, OVER,
+ uint32_t, uint32_t)
+PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, OVER,
+ uint32_t, uint16_t)
+PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, SRC,
+ uint32_t, uint16_t)
+PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 0565_8888, SRC,
+ uint16_t, uint32_t)
+
+void
+pixman_composite_src_n_8_asm_neon (int32_t w,
+ int32_t h,
+ uint8_t *dst,
+ int32_t dst_stride,
+ uint8_t src);
+
+void
+pixman_composite_src_n_0565_asm_neon (int32_t w,
+ int32_t h,
+ uint16_t *dst,
+ int32_t dst_stride,
+ uint16_t src);
+
+void
+pixman_composite_src_n_8888_asm_neon (int32_t w,
+ int32_t h,
+ uint32_t *dst,
+ int32_t dst_stride,
+ uint32_t src);
+
+static pixman_bool_t
+pixman_fill_neon (uint32_t *bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t _xor)
+{
+ /* stride is always multiple of 32bit units in pixman */
+ uint32_t byte_stride = stride * sizeof(uint32_t);
+
+ switch (bpp)
+ {
+ case 8:
+ pixman_composite_src_n_8_asm_neon (
+ width,
+ height,
+ (uint8_t *)(((char *) bits) + y * byte_stride + x),
+ byte_stride,
+ _xor & 0xff);
+ return TRUE;
+ case 16:
+ pixman_composite_src_n_0565_asm_neon (
+ width,
+ height,
+ (uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
+ byte_stride / 2,
+ _xor & 0xffff);
+ return TRUE;
+ case 32:
+ pixman_composite_src_n_8888_asm_neon (
+ width,
+ height,
+ (uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
+ byte_stride / 4,
+ _xor);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static pixman_bool_t
+pixman_blt_neon (uint32_t *src_bits,
+ uint32_t *dst_bits,
+ int src_stride,
+ int dst_stride,
+ int src_bpp,
+ int dst_bpp,
+ int src_x,
+ int src_y,
+ int dst_x,
+ int dst_y,
+ int width,
+ int height)
+{
+ if (src_bpp != dst_bpp)
+ return FALSE;
+
+ switch (src_bpp)
+ {
+ case 16:
+ pixman_composite_src_0565_0565_asm_neon (
+ width, height,
+ (uint16_t *)(((char *) dst_bits) +
+ dst_y * dst_stride * 4 + dst_x * 2), dst_stride * 2,
+ (uint16_t *)(((char *) src_bits) +
+ src_y * src_stride * 4 + src_x * 2), src_stride * 2);
+ return TRUE;
+ case 32:
+ pixman_composite_src_8888_8888_asm_neon (
+ width, height,
+ (uint32_t *)(((char *) dst_bits) +
+ dst_y * dst_stride * 4 + dst_x * 4), dst_stride,
+ (uint32_t *)(((char *) src_bits) +
+ src_y * src_stride * 4 + src_x * 4), src_stride);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static const pixman_fast_path_t arm_neon_fast_paths[] =
+{
+ PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
+ PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, neon_composite_src_0565_0565),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, neon_composite_src_0565_8888),
+ PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, neon_composite_src_0565_8888),
+ PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, neon_composite_src_0565_8888),
+ PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, neon_composite_src_0565_8888),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, neon_composite_src_8888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, neon_composite_src_0888_0888),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, neon_composite_src_0888_8888_rev),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, neon_composite_src_0888_0565_rev),
+ PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, neon_composite_src_pixbuf_8888),
+ PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, neon_composite_src_rpixbuf_8888),
+ PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, neon_composite_src_rpixbuf_8888),
+ PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, neon_composite_src_pixbuf_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, neon_composite_over_n_8_8),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, neon_composite_over_n_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, neon_composite_over_n_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, neon_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, neon_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, neon_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, neon_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, neon_composite_over_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, neon_composite_over_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, neon_composite_over_n_8888),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, neon_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, neon_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, neon_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, neon_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, neon_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, neon_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, neon_composite_over_8888_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, neon_composite_over_8888_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, neon_composite_over_0565_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, neon_composite_over_0565_n_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, neon_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, neon_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, neon_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, neon_composite_over_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, neon_composite_over_8888_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, neon_composite_over_8888_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, neon_composite_over_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, neon_composite_over_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_over_8888_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, neon_composite_over_8888_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, neon_composite_over_8888_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, neon_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, neon_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, neon_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, neon_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, neon_composite_add_n_8_8),
+ PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, neon_composite_add_n_8_8888),
+ PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, neon_composite_add_n_8_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8),
+ PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, neon_composite_add_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, neon_composite_add_0565_8_0565),
+ PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, neon_composite_add_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, neon_composite_add_8888_8_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add_8888_8888_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, neon_composite_add_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, neon_composite_add_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8_8),
+ PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add_8888_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add_8888_8888),
+ PIXMAN_STD_FAST_PATH (IN, solid, null, a8, neon_composite_in_n_8),
+ PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, neon_composite_over_reverse_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, neon_composite_over_reverse_n_8888),
+ PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, neon_composite_out_reverse_8_0565),
+ PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, neon_composite_out_reverse_8_0565),
+
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
+
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
+
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
+
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
+ /* Note: NONE repeat is not supported yet */
+ SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
+ SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
+ SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
+ SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
+
+ { PIXMAN_OP_NONE },
+};
+
+static pixman_bool_t
+arm_neon_blt (pixman_implementation_t *imp,
+ uint32_t * src_bits,
+ uint32_t * dst_bits,
+ int src_stride,
+ int dst_stride,
+ int src_bpp,
+ int dst_bpp,
+ int src_x,
+ int src_y,
+ int dst_x,
+ int dst_y,
+ int width,
+ int height)
+{
+ if (!pixman_blt_neon (
+ src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
+ src_x, src_y, dst_x, dst_y, width, height))
+
+ {
+ return _pixman_implementation_blt (
+ imp->delegate,
+ src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
+ src_x, src_y, dst_x, dst_y, width, height);
+ }
+
+ return TRUE;
+}
+
+static pixman_bool_t
+arm_neon_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ if (pixman_fill_neon (bits, stride, bpp, x, y, width, height, xor))
+ return TRUE;
+
+ return _pixman_implementation_fill (
+ imp->delegate, bits, stride, bpp, x, y, width, height, xor);
+}
+
+#define BIND_COMBINE_U(name) \
+void \
+pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \
+ const uint32_t *dst, \
+ const uint32_t *src, \
+ const uint32_t *mask); \
+ \
+void \
+pixman_composite_scanline_##name##_asm_neon (int32_t w, \
+ const uint32_t *dst, \
+ const uint32_t *src); \
+ \
+static void \
+neon_combine_##name##_u (pixman_implementation_t *imp, \
+ pixman_op_t op, \
+ uint32_t * dest, \
+ const uint32_t * src, \
+ const uint32_t * mask, \
+ int width) \
+{ \
+ if (mask) \
+ pixman_composite_scanline_##name##_mask_asm_neon (width, dest, \
+ src, mask); \
+ else \
+ pixman_composite_scanline_##name##_asm_neon (width, dest, src); \
+}
+
+BIND_COMBINE_U (over)
+BIND_COMBINE_U (add)
+BIND_COMBINE_U (out_reverse)
+
+pixman_implementation_t *
+_pixman_implementation_create_arm_neon (pixman_implementation_t *fallback)
+{
+ pixman_implementation_t *imp =
+ _pixman_implementation_create (fallback, arm_neon_fast_paths);
+
+ imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
+ imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
+ imp->combine_32[PIXMAN_OP_OUT_REVERSE] = neon_combine_out_reverse_u;
+
+ imp->blt = arm_neon_blt;
+ imp->fill = arm_neon_fill;
+
+ return imp;
+}
diff --git a/pixman/pixman/pixman-arm-simd.c b/pixman/pixman/pixman-arm-simd.c
index e03dfe020..6bbc1094d 100644
--- a/pixman/pixman/pixman-arm-simd.c
+++ b/pixman/pixman/pixman-arm-simd.c
@@ -1,424 +1,423 @@
-/*
- * Copyright © 2008 Mozilla Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Mozilla Corporation not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Mozilla Corporation makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Jeff Muizelaar (jeff@infidigm.net)
- *
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "pixman-private.h"
-#include "pixman-arm-common.h"
-#include "pixman-fast-path.h"
-
-#if 0 /* This code was moved to 'pixman-arm-simd-asm.S' */
-
-void
-pixman_composite_add_8_8_asm_armv6 (int32_t width,
- int32_t height,
- uint8_t *dst_line,
- int32_t dst_stride,
- uint8_t *src_line,
- int32_t src_stride)
-{
- uint8_t *dst, *src;
- int32_t w;
- uint8_t s, d;
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- /* ensure both src and dst are properly aligned before doing 32 bit reads
- * we'll stay in this loop if src and dst have differing alignments
- */
- while (w && (((unsigned long)dst & 3) || ((unsigned long)src & 3)))
- {
- s = *src;
- d = *dst;
- asm ("uqadd8 %0, %1, %2" : "+r" (d) : "r" (s));
- *dst = d;
-
- dst++;
- src++;
- w--;
- }
-
- while (w >= 4)
- {
- asm ("uqadd8 %0, %1, %2"
- : "=r" (*(uint32_t*)dst)
- : "r" (*(uint32_t*)src), "r" (*(uint32_t*)dst));
- dst += 4;
- src += 4;
- w -= 4;
- }
-
- while (w)
- {
- s = *src;
- d = *dst;
- asm ("uqadd8 %0, %1, %2" : "+r" (d) : "r" (s));
- *dst = d;
-
- dst++;
- src++;
- w--;
- }
- }
-
-}
-
-void
-pixman_composite_over_8888_8888_asm_armv6 (int32_t width,
- int32_t height,
- uint32_t *dst_line,
- int32_t dst_stride,
- uint32_t *src_line,
- int32_t src_stride)
-{
- uint32_t *dst;
- uint32_t *src;
- int32_t w;
- uint32_t component_half = 0x800080;
- uint32_t upper_component_mask = 0xff00ff00;
- uint32_t alpha_mask = 0xff;
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
-/* #define inner_branch */
- asm volatile (
- "cmp %[w], #0\n\t"
- "beq 2f\n\t"
- "1:\n\t"
- /* load src */
- "ldr r5, [%[src]], #4\n\t"
-#ifdef inner_branch
- /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
- * The 0x0 case also allows us to avoid doing an unecessary data
- * write which is more valuable so we only check for that
- */
- "cmp r5, #0\n\t"
- "beq 3f\n\t"
-
- /* = 255 - alpha */
- "sub r8, %[alpha_mask], r5, lsr #24\n\t"
-
- "ldr r4, [%[dest]] \n\t"
-
-#else
- "ldr r4, [%[dest]] \n\t"
-
- /* = 255 - alpha */
- "sub r8, %[alpha_mask], r5, lsr #24\n\t"
-#endif
- "uxtb16 r6, r4\n\t"
- "uxtb16 r7, r4, ror #8\n\t"
-
- /* multiply by 257 and divide by 65536 */
- "mla r6, r6, r8, %[component_half]\n\t"
- "mla r7, r7, r8, %[component_half]\n\t"
-
- "uxtab16 r6, r6, r6, ror #8\n\t"
- "uxtab16 r7, r7, r7, ror #8\n\t"
-
- /* recombine the 0xff00ff00 bytes of r6 and r7 */
- "and r7, r7, %[upper_component_mask]\n\t"
- "uxtab16 r6, r7, r6, ror #8\n\t"
-
- "uqadd8 r5, r6, r5\n\t"
-
-#ifdef inner_branch
- "3:\n\t"
-
-#endif
- "str r5, [%[dest]], #4\n\t"
- /* increment counter and jmp to top */
- "subs %[w], %[w], #1\n\t"
- "bne 1b\n\t"
- "2:\n\t"
- : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src)
- : [component_half] "r" (component_half), [upper_component_mask] "r" (upper_component_mask),
- [alpha_mask] "r" (alpha_mask)
- : "r4", "r5", "r6", "r7", "r8", "cc", "memory"
- );
- }
-}
-
-void
-pixman_composite_over_8888_n_8888_asm_armv6 (int32_t width,
- int32_t height,
- uint32_t *dst_line,
- int32_t dst_stride,
- uint32_t *src_line,
- int32_t src_stride,
- uint32_t mask)
-{
- uint32_t *dst;
- uint32_t *src;
- int32_t w;
- uint32_t component_half = 0x800080;
- uint32_t alpha_mask = 0xff;
-
- mask = (mask) >> 24;
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
-/* #define inner_branch */
- asm volatile (
- "cmp %[w], #0\n\t"
- "beq 2f\n\t"
- "1:\n\t"
- /* load src */
- "ldr r5, [%[src]], #4\n\t"
-#ifdef inner_branch
- /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
- * The 0x0 case also allows us to avoid doing an unecessary data
- * write which is more valuable so we only check for that
- */
- "cmp r5, #0\n\t"
- "beq 3f\n\t"
-
-#endif
- "ldr r4, [%[dest]] \n\t"
-
- "uxtb16 r6, r5\n\t"
- "uxtb16 r7, r5, ror #8\n\t"
-
- /* multiply by alpha (r8) then by 257 and divide by 65536 */
- "mla r6, r6, %[mask_alpha], %[component_half]\n\t"
- "mla r7, r7, %[mask_alpha], %[component_half]\n\t"
-
- "uxtab16 r6, r6, r6, ror #8\n\t"
- "uxtab16 r7, r7, r7, ror #8\n\t"
-
- "uxtb16 r6, r6, ror #8\n\t"
- "uxtb16 r7, r7, ror #8\n\t"
-
- /* recombine */
- "orr r5, r6, r7, lsl #8\n\t"
-
- "uxtb16 r6, r4\n\t"
- "uxtb16 r7, r4, ror #8\n\t"
-
- /* 255 - alpha */
- "sub r8, %[alpha_mask], r5, lsr #24\n\t"
-
- /* multiply by alpha (r8) then by 257 and divide by 65536 */
- "mla r6, r6, r8, %[component_half]\n\t"
- "mla r7, r7, r8, %[component_half]\n\t"
-
- "uxtab16 r6, r6, r6, ror #8\n\t"
- "uxtab16 r7, r7, r7, ror #8\n\t"
-
- "uxtb16 r6, r6, ror #8\n\t"
- "uxtb16 r7, r7, ror #8\n\t"
-
- /* recombine */
- "orr r6, r6, r7, lsl #8\n\t"
-
- "uqadd8 r5, r6, r5\n\t"
-
-#ifdef inner_branch
- "3:\n\t"
-
-#endif
- "str r5, [%[dest]], #4\n\t"
- /* increment counter and jmp to top */
- "subs %[w], %[w], #1\n\t"
- "bne 1b\n\t"
- "2:\n\t"
- : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src)
- : [component_half] "r" (component_half), [mask_alpha] "r" (mask),
- [alpha_mask] "r" (alpha_mask)
- : "r4", "r5", "r6", "r7", "r8", "r9", "cc", "memory"
- );
- }
-}
-
-void
-pixman_composite_over_n_8_8888_asm_armv6 (int32_t width,
- int32_t height,
- uint32_t *dst_line,
- int32_t dst_stride,
- uint32_t src,
- int32_t unused,
- uint8_t *mask_line,
- int32_t mask_stride)
-{
- uint32_t srca;
- uint32_t *dst;
- uint8_t *mask;
- int32_t w;
-
- srca = src >> 24;
-
- uint32_t component_mask = 0xff00ff;
- uint32_t component_half = 0x800080;
-
- uint32_t src_hi = (src >> 8) & component_mask;
- uint32_t src_lo = src & component_mask;
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
-/* #define inner_branch */
- asm volatile (
- "cmp %[w], #0\n\t"
- "beq 2f\n\t"
- "1:\n\t"
- /* load mask */
- "ldrb r5, [%[mask]], #1\n\t"
-#ifdef inner_branch
- /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
- * The 0x0 case also allows us to avoid doing an unecessary data
- * write which is more valuable so we only check for that
- */
- "cmp r5, #0\n\t"
- "beq 3f\n\t"
-
-#endif
- "ldr r4, [%[dest]] \n\t"
-
- /* multiply by alpha (r8) then by 257 and divide by 65536 */
- "mla r6, %[src_lo], r5, %[component_half]\n\t"
- "mla r7, %[src_hi], r5, %[component_half]\n\t"
-
- "uxtab16 r6, r6, r6, ror #8\n\t"
- "uxtab16 r7, r7, r7, ror #8\n\t"
-
- "uxtb16 r6, r6, ror #8\n\t"
- "uxtb16 r7, r7, ror #8\n\t"
-
- /* recombine */
- "orr r5, r6, r7, lsl #8\n\t"
-
- "uxtb16 r6, r4\n\t"
- "uxtb16 r7, r4, ror #8\n\t"
-
- /* we could simplify this to use 'sub' if we were
- * willing to give up a register for alpha_mask
- */
- "mvn r8, r5\n\t"
- "mov r8, r8, lsr #24\n\t"
-
- /* multiply by alpha (r8) then by 257 and divide by 65536 */
- "mla r6, r6, r8, %[component_half]\n\t"
- "mla r7, r7, r8, %[component_half]\n\t"
-
- "uxtab16 r6, r6, r6, ror #8\n\t"
- "uxtab16 r7, r7, r7, ror #8\n\t"
-
- "uxtb16 r6, r6, ror #8\n\t"
- "uxtb16 r7, r7, ror #8\n\t"
-
- /* recombine */
- "orr r6, r6, r7, lsl #8\n\t"
-
- "uqadd8 r5, r6, r5\n\t"
-
-#ifdef inner_branch
- "3:\n\t"
-
-#endif
- "str r5, [%[dest]], #4\n\t"
- /* increment counter and jmp to top */
- "subs %[w], %[w], #1\n\t"
- "bne 1b\n\t"
- "2:\n\t"
- : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src), [mask] "+r" (mask)
- : [component_half] "r" (component_half),
- [src_hi] "r" (src_hi), [src_lo] "r" (src_lo)
- : "r4", "r5", "r6", "r7", "r8", "cc", "memory");
- }
-}
-
-#endif
-
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, add_8_8,
- uint8_t, 1, uint8_t, 1)
-PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, over_8888_8888,
- uint32_t, 1, uint32_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
- uint32_t, 1, uint32_t, 1)
-
-PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8_8888,
- uint8_t, 1, uint32_t, 1)
-
-PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 0565_0565, SRC,
- uint16_t, uint16_t)
-
-static const pixman_fast_path_t arm_simd_fast_paths[] =
-{
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, armv6_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, armv6_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, armv6_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, armv6_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, armv6_composite_over_8888_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, armv6_composite_over_8888_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, armv6_composite_over_8888_n_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, armv6_composite_over_8888_n_8888),
-
- PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, armv6_composite_add_8_8),
-
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, armv6_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, armv6_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, armv6_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, armv6_composite_over_n_8_8888),
-
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
- PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
-
- { PIXMAN_OP_NONE },
-};
-
-pixman_implementation_t *
-_pixman_implementation_create_arm_simd (void)
-{
- pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
- pixman_implementation_t *imp = _pixman_implementation_create (general, arm_simd_fast_paths);
-
- return imp;
-}
+/*
+ * Copyright © 2008 Mozilla Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Mozilla Corporation not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Mozilla Corporation makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author: Jeff Muizelaar (jeff@infidigm.net)
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pixman-private.h"
+#include "pixman-arm-common.h"
+#include "pixman-fast-path.h"
+
+#if 0 /* This code was moved to 'pixman-arm-simd-asm.S' */
+
+void
+pixman_composite_add_8_8_asm_armv6 (int32_t width,
+ int32_t height,
+ uint8_t *dst_line,
+ int32_t dst_stride,
+ uint8_t *src_line,
+ int32_t src_stride)
+{
+ uint8_t *dst, *src;
+ int32_t w;
+ uint8_t s, d;
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ /* ensure both src and dst are properly aligned before doing 32 bit reads
+ * we'll stay in this loop if src and dst have differing alignments
+ */
+ while (w && (((unsigned long)dst & 3) || ((unsigned long)src & 3)))
+ {
+ s = *src;
+ d = *dst;
+ asm ("uqadd8 %0, %1, %2" : "+r" (d) : "r" (s));
+ *dst = d;
+
+ dst++;
+ src++;
+ w--;
+ }
+
+ while (w >= 4)
+ {
+ asm ("uqadd8 %0, %1, %2"
+ : "=r" (*(uint32_t*)dst)
+ : "r" (*(uint32_t*)src), "r" (*(uint32_t*)dst));
+ dst += 4;
+ src += 4;
+ w -= 4;
+ }
+
+ while (w)
+ {
+ s = *src;
+ d = *dst;
+ asm ("uqadd8 %0, %1, %2" : "+r" (d) : "r" (s));
+ *dst = d;
+
+ dst++;
+ src++;
+ w--;
+ }
+ }
+
+}
+
+void
+pixman_composite_over_8888_8888_asm_armv6 (int32_t width,
+ int32_t height,
+ uint32_t *dst_line,
+ int32_t dst_stride,
+ uint32_t *src_line,
+ int32_t src_stride)
+{
+ uint32_t *dst;
+ uint32_t *src;
+ int32_t w;
+ uint32_t component_half = 0x800080;
+ uint32_t upper_component_mask = 0xff00ff00;
+ uint32_t alpha_mask = 0xff;
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+/* #define inner_branch */
+ asm volatile (
+ "cmp %[w], #0\n\t"
+ "beq 2f\n\t"
+ "1:\n\t"
+ /* load src */
+ "ldr r5, [%[src]], #4\n\t"
+#ifdef inner_branch
+ /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
+ * The 0x0 case also allows us to avoid doing an unecessary data
+ * write which is more valuable so we only check for that
+ */
+ "cmp r5, #0\n\t"
+ "beq 3f\n\t"
+
+ /* = 255 - alpha */
+ "sub r8, %[alpha_mask], r5, lsr #24\n\t"
+
+ "ldr r4, [%[dest]] \n\t"
+
+#else
+ "ldr r4, [%[dest]] \n\t"
+
+ /* = 255 - alpha */
+ "sub r8, %[alpha_mask], r5, lsr #24\n\t"
+#endif
+ "uxtb16 r6, r4\n\t"
+ "uxtb16 r7, r4, ror #8\n\t"
+
+ /* multiply by 257 and divide by 65536 */
+ "mla r6, r6, r8, %[component_half]\n\t"
+ "mla r7, r7, r8, %[component_half]\n\t"
+
+ "uxtab16 r6, r6, r6, ror #8\n\t"
+ "uxtab16 r7, r7, r7, ror #8\n\t"
+
+ /* recombine the 0xff00ff00 bytes of r6 and r7 */
+ "and r7, r7, %[upper_component_mask]\n\t"
+ "uxtab16 r6, r7, r6, ror #8\n\t"
+
+ "uqadd8 r5, r6, r5\n\t"
+
+#ifdef inner_branch
+ "3:\n\t"
+
+#endif
+ "str r5, [%[dest]], #4\n\t"
+ /* increment counter and jmp to top */
+ "subs %[w], %[w], #1\n\t"
+ "bne 1b\n\t"
+ "2:\n\t"
+ : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src)
+ : [component_half] "r" (component_half), [upper_component_mask] "r" (upper_component_mask),
+ [alpha_mask] "r" (alpha_mask)
+ : "r4", "r5", "r6", "r7", "r8", "cc", "memory"
+ );
+ }
+}
+
+void
+pixman_composite_over_8888_n_8888_asm_armv6 (int32_t width,
+ int32_t height,
+ uint32_t *dst_line,
+ int32_t dst_stride,
+ uint32_t *src_line,
+ int32_t src_stride,
+ uint32_t mask)
+{
+ uint32_t *dst;
+ uint32_t *src;
+ int32_t w;
+ uint32_t component_half = 0x800080;
+ uint32_t alpha_mask = 0xff;
+
+ mask = (mask) >> 24;
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+/* #define inner_branch */
+ asm volatile (
+ "cmp %[w], #0\n\t"
+ "beq 2f\n\t"
+ "1:\n\t"
+ /* load src */
+ "ldr r5, [%[src]], #4\n\t"
+#ifdef inner_branch
+ /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
+ * The 0x0 case also allows us to avoid doing an unecessary data
+ * write which is more valuable so we only check for that
+ */
+ "cmp r5, #0\n\t"
+ "beq 3f\n\t"
+
+#endif
+ "ldr r4, [%[dest]] \n\t"
+
+ "uxtb16 r6, r5\n\t"
+ "uxtb16 r7, r5, ror #8\n\t"
+
+ /* multiply by alpha (r8) then by 257 and divide by 65536 */
+ "mla r6, r6, %[mask_alpha], %[component_half]\n\t"
+ "mla r7, r7, %[mask_alpha], %[component_half]\n\t"
+
+ "uxtab16 r6, r6, r6, ror #8\n\t"
+ "uxtab16 r7, r7, r7, ror #8\n\t"
+
+ "uxtb16 r6, r6, ror #8\n\t"
+ "uxtb16 r7, r7, ror #8\n\t"
+
+ /* recombine */
+ "orr r5, r6, r7, lsl #8\n\t"
+
+ "uxtb16 r6, r4\n\t"
+ "uxtb16 r7, r4, ror #8\n\t"
+
+ /* 255 - alpha */
+ "sub r8, %[alpha_mask], r5, lsr #24\n\t"
+
+ /* multiply by alpha (r8) then by 257 and divide by 65536 */
+ "mla r6, r6, r8, %[component_half]\n\t"
+ "mla r7, r7, r8, %[component_half]\n\t"
+
+ "uxtab16 r6, r6, r6, ror #8\n\t"
+ "uxtab16 r7, r7, r7, ror #8\n\t"
+
+ "uxtb16 r6, r6, ror #8\n\t"
+ "uxtb16 r7, r7, ror #8\n\t"
+
+ /* recombine */
+ "orr r6, r6, r7, lsl #8\n\t"
+
+ "uqadd8 r5, r6, r5\n\t"
+
+#ifdef inner_branch
+ "3:\n\t"
+
+#endif
+ "str r5, [%[dest]], #4\n\t"
+ /* increment counter and jmp to top */
+ "subs %[w], %[w], #1\n\t"
+ "bne 1b\n\t"
+ "2:\n\t"
+ : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src)
+ : [component_half] "r" (component_half), [mask_alpha] "r" (mask),
+ [alpha_mask] "r" (alpha_mask)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "cc", "memory"
+ );
+ }
+}
+
+void
+pixman_composite_over_n_8_8888_asm_armv6 (int32_t width,
+ int32_t height,
+ uint32_t *dst_line,
+ int32_t dst_stride,
+ uint32_t src,
+ int32_t unused,
+ uint8_t *mask_line,
+ int32_t mask_stride)
+{
+ uint32_t srca;
+ uint32_t *dst;
+ uint8_t *mask;
+ int32_t w;
+
+ srca = src >> 24;
+
+ uint32_t component_mask = 0xff00ff;
+ uint32_t component_half = 0x800080;
+
+ uint32_t src_hi = (src >> 8) & component_mask;
+ uint32_t src_lo = src & component_mask;
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+/* #define inner_branch */
+ asm volatile (
+ "cmp %[w], #0\n\t"
+ "beq 2f\n\t"
+ "1:\n\t"
+ /* load mask */
+ "ldrb r5, [%[mask]], #1\n\t"
+#ifdef inner_branch
+ /* We can avoid doing the multiplication in two cases: 0x0 or 0xff.
+ * The 0x0 case also allows us to avoid doing an unecessary data
+ * write which is more valuable so we only check for that
+ */
+ "cmp r5, #0\n\t"
+ "beq 3f\n\t"
+
+#endif
+ "ldr r4, [%[dest]] \n\t"
+
+ /* multiply by alpha (r8) then by 257 and divide by 65536 */
+ "mla r6, %[src_lo], r5, %[component_half]\n\t"
+ "mla r7, %[src_hi], r5, %[component_half]\n\t"
+
+ "uxtab16 r6, r6, r6, ror #8\n\t"
+ "uxtab16 r7, r7, r7, ror #8\n\t"
+
+ "uxtb16 r6, r6, ror #8\n\t"
+ "uxtb16 r7, r7, ror #8\n\t"
+
+ /* recombine */
+ "orr r5, r6, r7, lsl #8\n\t"
+
+ "uxtb16 r6, r4\n\t"
+ "uxtb16 r7, r4, ror #8\n\t"
+
+ /* we could simplify this to use 'sub' if we were
+ * willing to give up a register for alpha_mask
+ */
+ "mvn r8, r5\n\t"
+ "mov r8, r8, lsr #24\n\t"
+
+ /* multiply by alpha (r8) then by 257 and divide by 65536 */
+ "mla r6, r6, r8, %[component_half]\n\t"
+ "mla r7, r7, r8, %[component_half]\n\t"
+
+ "uxtab16 r6, r6, r6, ror #8\n\t"
+ "uxtab16 r7, r7, r7, ror #8\n\t"
+
+ "uxtb16 r6, r6, ror #8\n\t"
+ "uxtb16 r7, r7, ror #8\n\t"
+
+ /* recombine */
+ "orr r6, r6, r7, lsl #8\n\t"
+
+ "uqadd8 r5, r6, r5\n\t"
+
+#ifdef inner_branch
+ "3:\n\t"
+
+#endif
+ "str r5, [%[dest]], #4\n\t"
+ /* increment counter and jmp to top */
+ "subs %[w], %[w], #1\n\t"
+ "bne 1b\n\t"
+ "2:\n\t"
+ : [w] "+r" (w), [dest] "+r" (dst), [src] "+r" (src), [mask] "+r" (mask)
+ : [component_half] "r" (component_half),
+ [src_hi] "r" (src_hi), [src_lo] "r" (src_lo)
+ : "r4", "r5", "r6", "r7", "r8", "cc", "memory");
+ }
+}
+
+#endif
+
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, add_8_8,
+ uint8_t, 1, uint8_t, 1)
+PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, over_8888_8888,
+ uint32_t, 1, uint32_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
+ uint32_t, 1, uint32_t, 1)
+
+PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8_8888,
+ uint8_t, 1, uint32_t, 1)
+
+PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 0565_0565, SRC,
+ uint16_t, uint16_t)
+
+static const pixman_fast_path_t arm_simd_fast_paths[] =
+{
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, armv6_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, armv6_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, armv6_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, armv6_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, armv6_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, armv6_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, armv6_composite_over_8888_n_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, armv6_composite_over_8888_n_8888),
+
+ PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, armv6_composite_add_8_8),
+
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, armv6_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, armv6_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, armv6_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, armv6_composite_over_n_8_8888),
+
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
+ PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
+
+ { PIXMAN_OP_NONE },
+};
+
+pixman_implementation_t *
+_pixman_implementation_create_arm_simd (pixman_implementation_t *fallback)
+{
+ pixman_implementation_t *imp = _pixman_implementation_create (fallback, arm_simd_fast_paths);
+
+ return imp;
+}
diff --git a/pixman/pixman/pixman-cpu.c b/pixman/pixman/pixman-cpu.c
index 70253d1ea..0e14ecb6f 100644
--- a/pixman/pixman/pixman-cpu.c
+++ b/pixman/pixman/pixman-cpu.c
@@ -576,28 +576,36 @@ pixman_have_sse2 (void)
pixman_implementation_t *
_pixman_choose_implementation (void)
{
-#ifdef USE_SSE2
- if (pixman_have_sse2 ())
- return _pixman_implementation_create_sse2 ();
-#endif
+ pixman_implementation_t *imp;
+
+ imp = _pixman_implementation_create_general();
+ imp = _pixman_implementation_create_fast_path (imp);
+
#ifdef USE_MMX
if (pixman_have_mmx ())
- return _pixman_implementation_create_mmx ();
+ imp = _pixman_implementation_create_mmx (imp);
#endif
-#ifdef USE_ARM_NEON
- if (pixman_have_arm_neon ())
- return _pixman_implementation_create_arm_neon ();
+#ifdef USE_SSE2
+ if (pixman_have_sse2 ())
+ imp = _pixman_implementation_create_sse2 (imp);
#endif
+
#ifdef USE_ARM_SIMD
if (pixman_have_arm_simd ())
- return _pixman_implementation_create_arm_simd ();
+ imp = _pixman_implementation_create_arm_simd (imp);
+#endif
+
+#ifdef USE_ARM_NEON
+ if (pixman_have_arm_neon ())
+ imp = _pixman_implementation_create_arm_neon (imp);
#endif
+
#ifdef USE_VMX
if (pixman_have_vmx ())
- return _pixman_implementation_create_vmx ();
+ imp = _pixman_implementation_create_vmx (imp);
#endif
- return _pixman_implementation_create_fast_path ();
+ return imp;
}
diff --git a/pixman/pixman/pixman-fast-path.c b/pixman/pixman/pixman-fast-path.c
index 736e302c6..eb0971586 100644
--- a/pixman/pixman/pixman-fast-path.c
+++ b/pixman/pixman/pixman-fast-path.c
@@ -1,1936 +1,1935 @@
-/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
-/*
- * Copyright © 2000 SuSE, Inc.
- * Copyright © 2007 Red Hat, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include "pixman-private.h"
-#include "pixman-combine32.h"
-#include "pixman-fast-path.h"
-
-static force_inline uint32_t
-fetch_24 (uint8_t *a)
-{
- if (((unsigned long)a) & 1)
- {
-#ifdef WORDS_BIGENDIAN
- return (*a << 16) | (*(uint16_t *)(a + 1));
-#else
- return *a | (*(uint16_t *)(a + 1) << 8);
-#endif
- }
- else
- {
-#ifdef WORDS_BIGENDIAN
- return (*(uint16_t *)a << 8) | *(a + 2);
-#else
- return *(uint16_t *)a | (*(a + 2) << 16);
-#endif
- }
-}
-
-static force_inline void
-store_24 (uint8_t *a,
- uint32_t v)
-{
- if (((unsigned long)a) & 1)
- {
-#ifdef WORDS_BIGENDIAN
- *a = (uint8_t) (v >> 16);
- *(uint16_t *)(a + 1) = (uint16_t) (v);
-#else
- *a = (uint8_t) (v);
- *(uint16_t *)(a + 1) = (uint16_t) (v >> 8);
-#endif
- }
- else
- {
-#ifdef WORDS_BIGENDIAN
- *(uint16_t *)a = (uint16_t)(v >> 8);
- *(a + 2) = (uint8_t)v;
-#else
- *(uint16_t *)a = (uint16_t)v;
- *(a + 2) = (uint8_t)(v >> 16);
-#endif
- }
-}
-
-static force_inline uint32_t
-over (uint32_t src,
- uint32_t dest)
-{
- uint32_t a = ~src >> 24;
-
- UN8x4_MUL_UN8_ADD_UN8x4 (dest, a, src);
-
- return dest;
-}
-
-static uint32_t
-in (uint32_t x,
- uint8_t y)
-{
- uint16_t a = y;
-
- UN8x4_MUL_UN8 (x, a);
-
- return x;
-}
-
-/*
- * Naming convention:
- *
- * op_src_mask_dest
- */
-static void
-fast_composite_over_x888_8_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *src, *src_line;
- uint32_t *dst, *dst_line;
- uint8_t *mask, *mask_line;
- int src_stride, mask_stride, dst_stride;
- uint8_t m;
- uint32_t s, d;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
-
- while (height--)
- {
- src = src_line;
- src_line += src_stride;
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
-
- w = width;
- while (w--)
- {
- m = *mask++;
- if (m)
- {
- s = *src | 0xff000000;
-
- if (m == 0xff)
- {
- *dst = s;
- }
- else
- {
- d = in (s, m);
- *dst = over (d, *dst);
- }
- }
- src++;
- dst++;
- }
- }
-}
-
-static void
-fast_composite_in_n_8_8 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dest_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint8_t *dst_line, *dst;
- uint8_t *mask_line, *mask, m;
- int dst_stride, mask_stride;
- int32_t w;
- uint16_t t;
-
- src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
-
- srca = src >> 24;
-
- PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
-
- if (srca == 0xff)
- {
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
-
- if (m == 0)
- *dst = 0;
- else if (m != 0xff)
- *dst = MUL_UN8 (m, *dst, t);
-
- dst++;
- }
- }
- }
- else
- {
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- m = MUL_UN8 (m, srca, t);
-
- if (m == 0)
- *dst = 0;
- else if (m != 0xff)
- *dst = MUL_UN8 (m, *dst, t);
-
- dst++;
- }
- }
- }
-}
-
-static void
-fast_composite_in_8_8 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dest_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint8_t *dst_line, *dst;
- uint8_t *src_line, *src;
- int dst_stride, src_stride;
- int32_t w;
- uint8_t s;
- uint16_t t;
-
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
-
- if (s == 0)
- *dst = 0;
- else if (s != 0xff)
- *dst = MUL_UN8 (s, *dst, t);
-
- dst++;
- }
- }
-}
-
-static void
-fast_composite_over_n_8_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint32_t *dst_line, *dst, d;
- uint8_t *mask_line, *mask, m;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- *dst = src;
- else
- *dst = over (src, *dst);
- }
- else if (m)
- {
- d = in (src, m);
- *dst = over (d, *dst);
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_add_n_8888_8888_ca (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, s;
- uint32_t *dst_line, *dst, d;
- uint32_t *mask_line, *mask, ma;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- ma = *mask++;
-
- if (ma)
- {
- d = *dst;
- s = src;
-
- UN8x4_MUL_UN8x4_ADD_UN8x4 (s, ma, d);
-
- *dst = s;
- }
-
- dst++;
- }
- }
-}
-
-static void
-fast_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca, s;
- uint32_t *dst_line, *dst, d;
- uint32_t *mask_line, *mask, ma;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- ma = *mask++;
- if (ma == 0xffffffff)
- {
- if (srca == 0xff)
- *dst = src;
- else
- *dst = over (src, *dst);
- }
- else if (ma)
- {
- d = *dst;
- s = src;
-
- UN8x4_MUL_UN8x4 (s, ma);
- UN8x4_MUL_UN8 (ma, srca);
- ma = ~ma;
- UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
-
- *dst = d;
- }
-
- dst++;
- }
- }
-}
-
-static void
-fast_composite_over_n_8_0888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint8_t *dst_line, *dst;
- uint32_t d;
- uint8_t *mask_line, *mask, m;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- {
- d = src;
- }
- else
- {
- d = fetch_24 (dst);
- d = over (src, d);
- }
- store_24 (dst, d);
- }
- else if (m)
- {
- d = over (in (src, m), fetch_24 (dst));
- store_24 (dst, d);
- }
- dst += 3;
- }
- }
-}
-
-static void
-fast_composite_over_n_8_0565 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint16_t *dst_line, *dst;
- uint32_t d;
- uint8_t *mask_line, *mask, m;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- m = *mask++;
- if (m == 0xff)
- {
- if (srca == 0xff)
- {
- d = src;
- }
- else
- {
- d = *dst;
- d = over (src, CONVERT_0565_TO_0888 (d));
- }
- *dst = CONVERT_8888_TO_0565 (d);
- }
- else if (m)
- {
- d = *dst;
- d = over (in (src, m), CONVERT_0565_TO_0888 (d));
- *dst = CONVERT_8888_TO_0565 (d);
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca, s;
- uint16_t src16;
- uint16_t *dst_line, *dst;
- uint32_t d;
- uint32_t *mask_line, *mask, ma;
- int dst_stride, mask_stride;
- int32_t w;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- srca = src >> 24;
- if (src == 0)
- return;
-
- src16 = CONVERT_8888_TO_0565 (src);
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- ma = *mask++;
- if (ma == 0xffffffff)
- {
- if (srca == 0xff)
- {
- *dst = src16;
- }
- else
- {
- d = *dst;
- d = over (src, CONVERT_0565_TO_0888 (d));
- *dst = CONVERT_8888_TO_0565 (d);
- }
- }
- else if (ma)
- {
- d = *dst;
- d = CONVERT_0565_TO_0888 (d);
-
- s = src;
-
- UN8x4_MUL_UN8x4 (s, ma);
- UN8x4_MUL_UN8 (ma, srca);
- ma = ~ma;
- UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
-
- *dst = CONVERT_8888_TO_0565 (d);
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_over_8888_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *dst_line, *dst;
- uint32_t *src_line, *src, s;
- int dst_stride, src_stride;
- uint8_t a;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- a = s >> 24;
- if (a == 0xff)
- *dst = s;
- else if (s)
- *dst = over (s, *dst);
- dst++;
- }
- }
-}
-
-static void
-fast_composite_src_x888_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *dst_line, *dst;
- uint32_t *src_line, *src;
- int dst_stride, src_stride;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- *dst++ = (*src++) | 0xff000000;
- }
-}
-
-#if 0
-static void
-fast_composite_over_8888_0888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint8_t *dst_line, *dst;
- uint32_t d;
- uint32_t *src_line, *src, s;
- uint8_t a;
- int dst_stride, src_stride;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- a = s >> 24;
- if (a)
- {
- if (a == 0xff)
- d = s;
- else
- d = over (s, fetch_24 (dst));
-
- store_24 (dst, d);
- }
- dst += 3;
- }
- }
-}
-#endif
-
-static void
-fast_composite_over_8888_0565 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint16_t *dst_line, *dst;
- uint32_t d;
- uint32_t *src_line, *src, s;
- uint8_t a;
- int dst_stride, src_stride;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- a = s >> 24;
- if (s)
- {
- if (a == 0xff)
- {
- d = s;
- }
- else
- {
- d = *dst;
- d = over (s, CONVERT_0565_TO_0888 (d));
- }
- *dst = CONVERT_8888_TO_0565 (d);
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_src_x888_0565 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint16_t *dst_line, *dst;
- uint32_t *src_line, *src, s;
- int dst_stride, src_stride;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- *dst = CONVERT_8888_TO_0565 (s);
- dst++;
- }
- }
-}
-
-static void
-fast_composite_add_8_8 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint8_t *dst_line, *dst;
- uint8_t *src_line, *src;
- int dst_stride, src_stride;
- int32_t w;
- uint8_t s, d;
- uint16_t t;
-
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- if (s)
- {
- if (s != 0xff)
- {
- d = *dst;
- t = d + s;
- s = t | (0 - (t >> 8));
- }
- *dst = s;
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_add_8888_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *dst_line, *dst;
- uint32_t *src_line, *src;
- int dst_stride, src_stride;
- int32_t w;
- uint32_t s, d;
-
- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- s = *src++;
- if (s)
- {
- if (s != 0xffffffff)
- {
- d = *dst;
- if (d)
- UN8x4_ADD_UN8x4 (s, d);
- }
- *dst = s;
- }
- dst++;
- }
- }
-}
-
-static void
-fast_composite_add_n_8_8 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint8_t *dst_line, *dst;
- uint8_t *mask_line, *mask;
- int dst_stride, mask_stride;
- int32_t w;
- uint32_t src;
- uint8_t sa;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
- sa = (src >> 24);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- while (w--)
- {
- uint16_t tmp;
- uint16_t a;
- uint32_t m, d;
- uint32_t r;
-
- a = *mask++;
- d = *dst;
-
- m = MUL_UN8 (sa, a, tmp);
- r = ADD_UN8 (m, d, tmp);
-
- *dst++ = r;
- }
- }
-}
-
-#ifdef WORDS_BIGENDIAN
-#define CREATE_BITMASK(n) (0x80000000 >> (n))
-#define UPDATE_BITMASK(n) ((n) >> 1)
-#else
-#define CREATE_BITMASK(n) (1 << (n))
-#define UPDATE_BITMASK(n) ((n) << 1)
-#endif
-
-#define TEST_BIT(p, n) \
- (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31))
-#define SET_BIT(p, n) \
- do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0);
-
-static void
-fast_composite_add_1000_1000 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *dst_line, *dst;
- uint32_t *src_line, *src;
- int dst_stride, src_stride;
- int32_t w;
-
- PIXMAN_IMAGE_GET_LINE (src_image, 0, src_y, uint32_t,
- src_stride, src_line, 1);
- PIXMAN_IMAGE_GET_LINE (dst_image, 0, dest_y, uint32_t,
- dst_stride, dst_line, 1);
-
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- src = src_line;
- src_line += src_stride;
- w = width;
-
- while (w--)
- {
- /*
- * TODO: improve performance by processing uint32_t data instead
- * of individual bits
- */
- if (TEST_BIT (src, src_x + w))
- SET_BIT (dst, dest_x + w);
- }
- }
-}
-
-static void
-fast_composite_over_n_1_8888 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint32_t *dst, *dst_line;
- uint32_t *mask, *mask_line;
- int mask_stride, dst_stride;
- uint32_t bitcache, bitmask;
- int32_t w;
-
- if (width <= 0)
- return;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t,
- dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
- mask_stride, mask_line, 1);
- mask_line += mask_x >> 5;
-
- if (srca == 0xff)
- {
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (mask_x & 31);
-
- while (w--)
- {
- if (bitmask == 0)
- {
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (0);
- }
- if (bitcache & bitmask)
- *dst = src;
- bitmask = UPDATE_BITMASK (bitmask);
- dst++;
- }
- }
- }
- else
- {
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (mask_x & 31);
-
- while (w--)
- {
- if (bitmask == 0)
- {
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (0);
- }
- if (bitcache & bitmask)
- *dst = over (src, *dst);
- bitmask = UPDATE_BITMASK (bitmask);
- dst++;
- }
- }
- }
-}
-
-static void
-fast_composite_over_n_1_0565 (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src, srca;
- uint16_t *dst, *dst_line;
- uint32_t *mask, *mask_line;
- int mask_stride, dst_stride;
- uint32_t bitcache, bitmask;
- int32_t w;
- uint32_t d;
- uint16_t src565;
-
- if (width <= 0)
- return;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
- srca = src >> 24;
- if (src == 0)
- return;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t,
- dst_stride, dst_line, 1);
- PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
- mask_stride, mask_line, 1);
- mask_line += mask_x >> 5;
-
- if (srca == 0xff)
- {
- src565 = CONVERT_8888_TO_0565 (src);
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (mask_x & 31);
-
- while (w--)
- {
- if (bitmask == 0)
- {
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (0);
- }
- if (bitcache & bitmask)
- *dst = src565;
- bitmask = UPDATE_BITMASK (bitmask);
- dst++;
- }
- }
- }
- else
- {
- while (height--)
- {
- dst = dst_line;
- dst_line += dst_stride;
- mask = mask_line;
- mask_line += mask_stride;
- w = width;
-
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (mask_x & 31);
-
- while (w--)
- {
- if (bitmask == 0)
- {
- bitcache = *mask++;
- bitmask = CREATE_BITMASK (0);
- }
- if (bitcache & bitmask)
- {
- d = over (src, CONVERT_0565_TO_0888 (*dst));
- *dst = CONVERT_8888_TO_0565 (d);
- }
- bitmask = UPDATE_BITMASK (bitmask);
- dst++;
- }
- }
- }
-}
-
-/*
- * Simple bitblt
- */
-
-static void
-fast_composite_solid_fill (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t src;
-
- src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
-
- if (dst_image->bits.format == PIXMAN_a1)
- {
- src = src >> 31;
- }
- else if (dst_image->bits.format == PIXMAN_a8)
- {
- src = src >> 24;
- }
- else if (dst_image->bits.format == PIXMAN_r5g6b5 ||
- dst_image->bits.format == PIXMAN_b5g6r5)
- {
- src = CONVERT_8888_TO_0565 (src);
- }
-
- pixman_fill (dst_image->bits.bits, dst_image->bits.rowstride,
- PIXMAN_FORMAT_BPP (dst_image->bits.format),
- dest_x, dest_y,
- width, height,
- src);
-}
-
-static void
-fast_composite_src_memcpy (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- int bpp = PIXMAN_FORMAT_BPP (dst_image->bits.format) / 8;
- uint32_t n_bytes = width * bpp;
- int dst_stride, src_stride;
- uint8_t *dst;
- uint8_t *src;
-
- src_stride = src_image->bits.rowstride * 4;
- dst_stride = dst_image->bits.rowstride * 4;
-
- src = (uint8_t *)src_image->bits.bits + src_y * src_stride + src_x * bpp;
- dst = (uint8_t *)dst_image->bits.bits + dest_y * dst_stride + dest_x * bpp;
-
- while (height--)
- {
- memcpy (dst, src, n_bytes);
-
- dst += dst_stride;
- src += src_stride;
- }
-}
-
-FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, SRC, COVER)
-FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, SRC, NONE)
-FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, SRC, PAD)
-FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, SRC, NORMAL)
-FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, OVER, COVER)
-FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, OVER, NONE)
-FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, OVER, PAD)
-FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, OVER, NORMAL)
-FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, SRC, COVER)
-FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, SRC, NONE)
-FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, SRC, PAD)
-FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, SRC, NORMAL)
-FAST_NEAREST (565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL)
-FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, OVER, COVER)
-FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, OVER, NONE)
-FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, OVER, PAD)
-FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, OVER, NORMAL)
-
-/* Use more unrolling for src_0565_0565 because it is typically CPU bound */
-static force_inline void
-scaled_nearest_scanline_565_565_SRC (uint16_t * dst,
- uint16_t * src,
- int32_t w,
- pixman_fixed_t vx,
- pixman_fixed_t unit_x,
- pixman_fixed_t max_vx)
-{
- uint16_t tmp1, tmp2, tmp3, tmp4;
- while ((w -= 4) >= 0)
- {
- tmp1 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- tmp2 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- tmp3 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- tmp4 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- *dst++ = tmp1;
- *dst++ = tmp2;
- *dst++ = tmp3;
- *dst++ = tmp4;
- }
- if (w & 2)
- {
- tmp1 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- tmp2 = src[pixman_fixed_to_int (vx)];
- vx += unit_x;
- *dst++ = tmp1;
- *dst++ = tmp2;
- }
- if (w & 1)
- *dst++ = src[pixman_fixed_to_int (vx)];
-}
-
-FAST_NEAREST_MAINLOOP (565_565_cover_SRC,
- scaled_nearest_scanline_565_565_SRC,
- uint16_t, uint16_t, COVER)
-FAST_NEAREST_MAINLOOP (565_565_none_SRC,
- scaled_nearest_scanline_565_565_SRC,
- uint16_t, uint16_t, NONE)
-FAST_NEAREST_MAINLOOP (565_565_pad_SRC,
- scaled_nearest_scanline_565_565_SRC,
- uint16_t, uint16_t, PAD)
-
-static force_inline uint32_t
-fetch_nearest (pixman_repeat_t src_repeat,
- pixman_format_code_t format,
- uint32_t *src, int x, int src_width)
-{
- if (repeat (src_repeat, &x, src_width))
- {
- if (format == PIXMAN_x8r8g8b8)
- return *(src + x) | 0xff000000;
- else
- return *(src + x);
- }
- else
- {
- return 0;
- }
-}
-
-static force_inline void
-combine_over (uint32_t s, uint32_t *dst)
-{
- if (s)
- {
- uint8_t ia = 0xff - (s >> 24);
-
- if (ia)
- UN8x4_MUL_UN8_ADD_UN8x4 (*dst, ia, s);
- else
- *dst = s;
- }
-}
-
-static force_inline void
-combine_src (uint32_t s, uint32_t *dst)
-{
- *dst = s;
-}
-
-static void
-fast_composite_scaled_nearest (pixman_implementation_t *imp,
- pixman_op_t op,
- pixman_image_t * src_image,
- pixman_image_t * mask_image,
- pixman_image_t * dst_image,
- int32_t src_x,
- int32_t src_y,
- int32_t mask_x,
- int32_t mask_y,
- int32_t dest_x,
- int32_t dest_y,
- int32_t width,
- int32_t height)
-{
- uint32_t *dst_line;
- uint32_t *src_line;
- int dst_stride, src_stride;
- int src_width, src_height;
- pixman_repeat_t src_repeat;
- pixman_fixed_t unit_x, unit_y;
- pixman_format_code_t src_format;
- pixman_vector_t v;
- pixman_fixed_t vy;
-
- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
- /* pass in 0 instead of src_x and src_y because src_x and src_y need to be
- * transformed from destination space to source space
- */
- PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, uint32_t, src_stride, src_line, 1);
-
- /* reference point is the center of the pixel */
- v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2;
- v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2;
- v.vector[2] = pixman_fixed_1;
-
- if (!pixman_transform_point_3d (src_image->common.transform, &v))
- return;
-
- unit_x = src_image->common.transform->matrix[0][0];
- unit_y = src_image->common.transform->matrix[1][1];
-
- /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
- v.vector[0] -= pixman_fixed_e;
- v.vector[1] -= pixman_fixed_e;
-
- src_height = src_image->bits.height;
- src_width = src_image->bits.width;
- src_repeat = src_image->common.repeat;
- src_format = src_image->bits.format;
-
- vy = v.vector[1];
- while (height--)
- {
- pixman_fixed_t vx = v.vector[0];
- int y = pixman_fixed_to_int (vy);
- uint32_t *dst = dst_line;
-
- dst_line += dst_stride;
-
- /* adjust the y location by a unit vector in the y direction
- * this is equivalent to transforming y+1 of the destination point to source space */
- vy += unit_y;
-
- if (!repeat (src_repeat, &y, src_height))
- {
- if (op == PIXMAN_OP_SRC)
- memset (dst, 0, sizeof (*dst) * width);
- }
- else
- {
- int w = width;
-
- uint32_t *src = src_line + y * src_stride;
-
- while (w >= 2)
- {
- uint32_t s1, s2;
- int x1, x2;
-
- x1 = pixman_fixed_to_int (vx);
- vx += unit_x;
-
- x2 = pixman_fixed_to_int (vx);
- vx += unit_x;
-
- w -= 2;
-
- s1 = fetch_nearest (src_repeat, src_format, src, x1, src_width);
- s2 = fetch_nearest (src_repeat, src_format, src, x2, src_width);
-
- if (op == PIXMAN_OP_OVER)
- {
- combine_over (s1, dst++);
- combine_over (s2, dst++);
- }
- else
- {
- combine_src (s1, dst++);
- combine_src (s2, dst++);
- }
- }
-
- while (w--)
- {
- uint32_t s;
- int x;
-
- x = pixman_fixed_to_int (vx);
- vx += unit_x;
-
- s = fetch_nearest (src_repeat, src_format, src, x, src_width);
-
- if (op == PIXMAN_OP_OVER)
- combine_over (s, dst++);
- else
- combine_src (s, dst++);
- }
- }
- }
-}
-
-static const pixman_fast_path_t c_fast_paths[] =
-{
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5, fast_composite_over_n_1_0565),
- PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5, fast_composite_over_n_1_0565),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca),
- PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888),
- PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565),
- PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888),
- PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8_8),
- PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1000_1000),
- PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca),
- PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, a1, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, fast_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, fast_composite_src_x888_8888),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8x8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8a8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8x8, null, b8g8r8x8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, b8g8r8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, fast_composite_src_memcpy),
- PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
- PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
- PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
- PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
- PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8),
- PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8),
-
- SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, 8888_8888),
-
- SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, 8888_8888),
-
- SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, 8888_565),
- SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, 8888_565),
-
- SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, 565_565),
-
- SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, 8888_8888),
- SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, 8888_8888),
-
- SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, 8888_565),
-
-#define NEAREST_FAST_PATH(op,s,d) \
- { PIXMAN_OP_ ## op, \
- PIXMAN_ ## s, SCALED_NEAREST_FLAGS, \
- PIXMAN_null, 0, \
- PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
- fast_composite_scaled_nearest, \
- }
-
- NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8),
- NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8),
- NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8),
- NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8),
-
- NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8),
- NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8),
- NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8),
- NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8),
-
- NEAREST_FAST_PATH (OVER, x8r8g8b8, x8r8g8b8),
- NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8),
- NEAREST_FAST_PATH (OVER, x8b8g8r8, x8b8g8r8),
- NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8),
-
- NEAREST_FAST_PATH (OVER, x8r8g8b8, a8r8g8b8),
- NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8),
- NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8),
- NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8),
-
- { PIXMAN_OP_NONE },
-};
-
-#ifdef WORDS_BIGENDIAN
-#define A1_FILL_MASK(n, offs) (((1 << (n)) - 1) << (32 - (offs) - (n)))
-#else
-#define A1_FILL_MASK(n, offs) (((1 << (n)) - 1) << (offs))
-#endif
-
-static force_inline void
-pixman_fill1_line (uint32_t *dst, int offs, int width, int v)
-{
- if (offs)
- {
- int leading_pixels = 32 - offs;
- if (leading_pixels >= width)
- {
- if (v)
- *dst |= A1_FILL_MASK (width, offs);
- else
- *dst &= ~A1_FILL_MASK (width, offs);
- return;
- }
- else
- {
- if (v)
- *dst++ |= A1_FILL_MASK (leading_pixels, offs);
- else
- *dst++ &= ~A1_FILL_MASK (leading_pixels, offs);
- width -= leading_pixels;
- }
- }
- while (width >= 32)
- {
- if (v)
- *dst++ = 0xFFFFFFFF;
- else
- *dst++ = 0;
- width -= 32;
- }
- if (width > 0)
- {
- if (v)
- *dst |= A1_FILL_MASK (width, 0);
- else
- *dst &= ~A1_FILL_MASK (width, 0);
- }
-}
-
-static void
-pixman_fill1 (uint32_t *bits,
- int stride,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- uint32_t *dst = bits + y * stride + (x >> 5);
- int offs = x & 31;
-
- if (xor & 1)
- {
- while (height--)
- {
- pixman_fill1_line (dst, offs, width, 1);
- dst += stride;
- }
- }
- else
- {
- while (height--)
- {
- pixman_fill1_line (dst, offs, width, 0);
- dst += stride;
- }
- }
-}
-
-static void
-pixman_fill8 (uint32_t *bits,
- int stride,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- int byte_stride = stride * (int) sizeof (uint32_t);
- uint8_t *dst = (uint8_t *) bits;
- uint8_t v = xor & 0xff;
- int i;
-
- dst = dst + y * byte_stride + x;
-
- while (height--)
- {
- for (i = 0; i < width; ++i)
- dst[i] = v;
-
- dst += byte_stride;
- }
-}
-
-static void
-pixman_fill16 (uint32_t *bits,
- int stride,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- int short_stride =
- (stride * (int)sizeof (uint32_t)) / (int)sizeof (uint16_t);
- uint16_t *dst = (uint16_t *)bits;
- uint16_t v = xor & 0xffff;
- int i;
-
- dst = dst + y * short_stride + x;
-
- while (height--)
- {
- for (i = 0; i < width; ++i)
- dst[i] = v;
-
- dst += short_stride;
- }
-}
-
-static void
-pixman_fill32 (uint32_t *bits,
- int stride,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- int i;
-
- bits = bits + y * stride + x;
-
- while (height--)
- {
- for (i = 0; i < width; ++i)
- bits[i] = xor;
-
- bits += stride;
- }
-}
-
-static pixman_bool_t
-fast_path_fill (pixman_implementation_t *imp,
- uint32_t * bits,
- int stride,
- int bpp,
- int x,
- int y,
- int width,
- int height,
- uint32_t xor)
-{
- switch (bpp)
- {
- case 1:
- pixman_fill1 (bits, stride, x, y, width, height, xor);
- break;
-
- case 8:
- pixman_fill8 (bits, stride, x, y, width, height, xor);
- break;
-
- case 16:
- pixman_fill16 (bits, stride, x, y, width, height, xor);
- break;
-
- case 32:
- pixman_fill32 (bits, stride, x, y, width, height, xor);
- break;
-
- default:
- return _pixman_implementation_fill (
- imp->delegate, bits, stride, bpp, x, y, width, height, xor);
- break;
- }
-
- return TRUE;
-}
-
-pixman_implementation_t *
-_pixman_implementation_create_fast_path (void)
-{
- pixman_implementation_t *general = _pixman_implementation_create_general ();
- pixman_implementation_t *imp = _pixman_implementation_create (general, c_fast_paths);
-
- imp->fill = fast_path_fill;
-
- return imp;
-}
+/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
+/*
+ * Copyright © 2000 SuSE, Inc.
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include "pixman-private.h"
+#include "pixman-combine32.h"
+#include "pixman-fast-path.h"
+
+static force_inline uint32_t
+fetch_24 (uint8_t *a)
+{
+ if (((unsigned long)a) & 1)
+ {
+#ifdef WORDS_BIGENDIAN
+ return (*a << 16) | (*(uint16_t *)(a + 1));
+#else
+ return *a | (*(uint16_t *)(a + 1) << 8);
+#endif
+ }
+ else
+ {
+#ifdef WORDS_BIGENDIAN
+ return (*(uint16_t *)a << 8) | *(a + 2);
+#else
+ return *(uint16_t *)a | (*(a + 2) << 16);
+#endif
+ }
+}
+
+static force_inline void
+store_24 (uint8_t *a,
+ uint32_t v)
+{
+ if (((unsigned long)a) & 1)
+ {
+#ifdef WORDS_BIGENDIAN
+ *a = (uint8_t) (v >> 16);
+ *(uint16_t *)(a + 1) = (uint16_t) (v);
+#else
+ *a = (uint8_t) (v);
+ *(uint16_t *)(a + 1) = (uint16_t) (v >> 8);
+#endif
+ }
+ else
+ {
+#ifdef WORDS_BIGENDIAN
+ *(uint16_t *)a = (uint16_t)(v >> 8);
+ *(a + 2) = (uint8_t)v;
+#else
+ *(uint16_t *)a = (uint16_t)v;
+ *(a + 2) = (uint8_t)(v >> 16);
+#endif
+ }
+}
+
+static force_inline uint32_t
+over (uint32_t src,
+ uint32_t dest)
+{
+ uint32_t a = ~src >> 24;
+
+ UN8x4_MUL_UN8_ADD_UN8x4 (dest, a, src);
+
+ return dest;
+}
+
+static uint32_t
+in (uint32_t x,
+ uint8_t y)
+{
+ uint16_t a = y;
+
+ UN8x4_MUL_UN8 (x, a);
+
+ return x;
+}
+
+/*
+ * Naming convention:
+ *
+ * op_src_mask_dest
+ */
+static void
+fast_composite_over_x888_8_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *src, *src_line;
+ uint32_t *dst, *dst_line;
+ uint8_t *mask, *mask_line;
+ int src_stride, mask_stride, dst_stride;
+ uint8_t m;
+ uint32_t s, d;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+
+ while (height--)
+ {
+ src = src_line;
+ src_line += src_stride;
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+
+ w = width;
+ while (w--)
+ {
+ m = *mask++;
+ if (m)
+ {
+ s = *src | 0xff000000;
+
+ if (m == 0xff)
+ {
+ *dst = s;
+ }
+ else
+ {
+ d = in (s, m);
+ *dst = over (d, *dst);
+ }
+ }
+ src++;
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_in_n_8_8 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dest_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint8_t *dst_line, *dst;
+ uint8_t *mask_line, *mask, m;
+ int dst_stride, mask_stride;
+ int32_t w;
+ uint16_t t;
+
+ src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
+
+ srca = src >> 24;
+
+ PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ if (srca == 0xff)
+ {
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+
+ if (m == 0)
+ *dst = 0;
+ else if (m != 0xff)
+ *dst = MUL_UN8 (m, *dst, t);
+
+ dst++;
+ }
+ }
+ }
+ else
+ {
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ m = MUL_UN8 (m, srca, t);
+
+ if (m == 0)
+ *dst = 0;
+ else if (m != 0xff)
+ *dst = MUL_UN8 (m, *dst, t);
+
+ dst++;
+ }
+ }
+ }
+}
+
+static void
+fast_composite_in_8_8 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dest_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint8_t *dst_line, *dst;
+ uint8_t *src_line, *src;
+ int dst_stride, src_stride;
+ int32_t w;
+ uint8_t s;
+ uint16_t t;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+
+ if (s == 0)
+ *dst = 0;
+ else if (s != 0xff)
+ *dst = MUL_UN8 (s, *dst, t);
+
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_over_n_8_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint32_t *dst_line, *dst, d;
+ uint8_t *mask_line, *mask, m;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ *dst = src;
+ else
+ *dst = over (src, *dst);
+ }
+ else if (m)
+ {
+ d = in (src, m);
+ *dst = over (d, *dst);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_add_n_8888_8888_ca (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, s;
+ uint32_t *dst_line, *dst, d;
+ uint32_t *mask_line, *mask, ma;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ ma = *mask++;
+
+ if (ma)
+ {
+ d = *dst;
+ s = src;
+
+ UN8x4_MUL_UN8x4_ADD_UN8x4 (s, ma, d);
+
+ *dst = s;
+ }
+
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca, s;
+ uint32_t *dst_line, *dst, d;
+ uint32_t *mask_line, *mask, ma;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ ma = *mask++;
+ if (ma == 0xffffffff)
+ {
+ if (srca == 0xff)
+ *dst = src;
+ else
+ *dst = over (src, *dst);
+ }
+ else if (ma)
+ {
+ d = *dst;
+ s = src;
+
+ UN8x4_MUL_UN8x4 (s, ma);
+ UN8x4_MUL_UN8 (ma, srca);
+ ma = ~ma;
+ UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
+
+ *dst = d;
+ }
+
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_over_n_8_0888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint8_t *dst_line, *dst;
+ uint32_t d;
+ uint8_t *mask_line, *mask, m;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ {
+ d = src;
+ }
+ else
+ {
+ d = fetch_24 (dst);
+ d = over (src, d);
+ }
+ store_24 (dst, d);
+ }
+ else if (m)
+ {
+ d = over (in (src, m), fetch_24 (dst));
+ store_24 (dst, d);
+ }
+ dst += 3;
+ }
+ }
+}
+
+static void
+fast_composite_over_n_8_0565 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint16_t *dst_line, *dst;
+ uint32_t d;
+ uint8_t *mask_line, *mask, m;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ {
+ d = src;
+ }
+ else
+ {
+ d = *dst;
+ d = over (src, CONVERT_0565_TO_0888 (d));
+ }
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ else if (m)
+ {
+ d = *dst;
+ d = over (in (src, m), CONVERT_0565_TO_0888 (d));
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca, s;
+ uint16_t src16;
+ uint16_t *dst_line, *dst;
+ uint32_t d;
+ uint32_t *mask_line, *mask, ma;
+ int dst_stride, mask_stride;
+ int32_t w;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ src16 = CONVERT_8888_TO_0565 (src);
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ ma = *mask++;
+ if (ma == 0xffffffff)
+ {
+ if (srca == 0xff)
+ {
+ *dst = src16;
+ }
+ else
+ {
+ d = *dst;
+ d = over (src, CONVERT_0565_TO_0888 (d));
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ }
+ else if (ma)
+ {
+ d = *dst;
+ d = CONVERT_0565_TO_0888 (d);
+
+ s = src;
+
+ UN8x4_MUL_UN8x4 (s, ma);
+ UN8x4_MUL_UN8 (ma, srca);
+ ma = ~ma;
+ UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
+
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_over_8888_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *dst_line, *dst;
+ uint32_t *src_line, *src, s;
+ int dst_stride, src_stride;
+ uint8_t a;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ a = s >> 24;
+ if (a == 0xff)
+ *dst = s;
+ else if (s)
+ *dst = over (s, *dst);
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_src_x888_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *dst_line, *dst;
+ uint32_t *src_line, *src;
+ int dst_stride, src_stride;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ *dst++ = (*src++) | 0xff000000;
+ }
+}
+
+#if 0
+static void
+fast_composite_over_8888_0888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint8_t *dst_line, *dst;
+ uint32_t d;
+ uint32_t *src_line, *src, s;
+ uint8_t a;
+ int dst_stride, src_stride;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ a = s >> 24;
+ if (a)
+ {
+ if (a == 0xff)
+ d = s;
+ else
+ d = over (s, fetch_24 (dst));
+
+ store_24 (dst, d);
+ }
+ dst += 3;
+ }
+ }
+}
+#endif
+
+static void
+fast_composite_over_8888_0565 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint16_t *dst_line, *dst;
+ uint32_t d;
+ uint32_t *src_line, *src, s;
+ uint8_t a;
+ int dst_stride, src_stride;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ a = s >> 24;
+ if (s)
+ {
+ if (a == 0xff)
+ {
+ d = s;
+ }
+ else
+ {
+ d = *dst;
+ d = over (s, CONVERT_0565_TO_0888 (d));
+ }
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_src_x888_0565 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint16_t *dst_line, *dst;
+ uint32_t *src_line, *src, s;
+ int dst_stride, src_stride;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ *dst = CONVERT_8888_TO_0565 (s);
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_add_8_8 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint8_t *dst_line, *dst;
+ uint8_t *src_line, *src;
+ int dst_stride, src_stride;
+ int32_t w;
+ uint8_t s, d;
+ uint16_t t;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ if (s)
+ {
+ if (s != 0xff)
+ {
+ d = *dst;
+ t = d + s;
+ s = t | (0 - (t >> 8));
+ }
+ *dst = s;
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_add_8888_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *dst_line, *dst;
+ uint32_t *src_line, *src;
+ int dst_stride, src_stride;
+ int32_t w;
+ uint32_t s, d;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ s = *src++;
+ if (s)
+ {
+ if (s != 0xffffffff)
+ {
+ d = *dst;
+ if (d)
+ UN8x4_ADD_UN8x4 (s, d);
+ }
+ *dst = s;
+ }
+ dst++;
+ }
+ }
+}
+
+static void
+fast_composite_add_n_8_8 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint8_t *dst_line, *dst;
+ uint8_t *mask_line, *mask;
+ int dst_stride, mask_stride;
+ int32_t w;
+ uint32_t src;
+ uint8_t sa;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+ sa = (src >> 24);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ while (w--)
+ {
+ uint16_t tmp;
+ uint16_t a;
+ uint32_t m, d;
+ uint32_t r;
+
+ a = *mask++;
+ d = *dst;
+
+ m = MUL_UN8 (sa, a, tmp);
+ r = ADD_UN8 (m, d, tmp);
+
+ *dst++ = r;
+ }
+ }
+}
+
+#ifdef WORDS_BIGENDIAN
+#define CREATE_BITMASK(n) (0x80000000 >> (n))
+#define UPDATE_BITMASK(n) ((n) >> 1)
+#else
+#define CREATE_BITMASK(n) (1 << (n))
+#define UPDATE_BITMASK(n) ((n) << 1)
+#endif
+
+#define TEST_BIT(p, n) \
+ (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31))
+#define SET_BIT(p, n) \
+ do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0);
+
+static void
+fast_composite_add_1000_1000 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *dst_line, *dst;
+ uint32_t *src_line, *src;
+ int dst_stride, src_stride;
+ int32_t w;
+
+ PIXMAN_IMAGE_GET_LINE (src_image, 0, src_y, uint32_t,
+ src_stride, src_line, 1);
+ PIXMAN_IMAGE_GET_LINE (dst_image, 0, dest_y, uint32_t,
+ dst_stride, dst_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ src = src_line;
+ src_line += src_stride;
+ w = width;
+
+ while (w--)
+ {
+ /*
+ * TODO: improve performance by processing uint32_t data instead
+ * of individual bits
+ */
+ if (TEST_BIT (src, src_x + w))
+ SET_BIT (dst, dest_x + w);
+ }
+ }
+}
+
+static void
+fast_composite_over_n_1_8888 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint32_t *dst, *dst_line;
+ uint32_t *mask, *mask_line;
+ int mask_stride, dst_stride;
+ uint32_t bitcache, bitmask;
+ int32_t w;
+
+ if (width <= 0)
+ return;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t,
+ dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
+ mask_stride, mask_line, 1);
+ mask_line += mask_x >> 5;
+
+ if (srca == 0xff)
+ {
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (mask_x & 31);
+
+ while (w--)
+ {
+ if (bitmask == 0)
+ {
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (0);
+ }
+ if (bitcache & bitmask)
+ *dst = src;
+ bitmask = UPDATE_BITMASK (bitmask);
+ dst++;
+ }
+ }
+ }
+ else
+ {
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (mask_x & 31);
+
+ while (w--)
+ {
+ if (bitmask == 0)
+ {
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (0);
+ }
+ if (bitcache & bitmask)
+ *dst = over (src, *dst);
+ bitmask = UPDATE_BITMASK (bitmask);
+ dst++;
+ }
+ }
+ }
+}
+
+static void
+fast_composite_over_n_1_0565 (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint16_t *dst, *dst_line;
+ uint32_t *mask, *mask_line;
+ int mask_stride, dst_stride;
+ uint32_t bitcache, bitmask;
+ int32_t w;
+ uint32_t d;
+ uint16_t src565;
+
+ if (width <= 0)
+ return;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t,
+ dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
+ mask_stride, mask_line, 1);
+ mask_line += mask_x >> 5;
+
+ if (srca == 0xff)
+ {
+ src565 = CONVERT_8888_TO_0565 (src);
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (mask_x & 31);
+
+ while (w--)
+ {
+ if (bitmask == 0)
+ {
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (0);
+ }
+ if (bitcache & bitmask)
+ *dst = src565;
+ bitmask = UPDATE_BITMASK (bitmask);
+ dst++;
+ }
+ }
+ }
+ else
+ {
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+ w = width;
+
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (mask_x & 31);
+
+ while (w--)
+ {
+ if (bitmask == 0)
+ {
+ bitcache = *mask++;
+ bitmask = CREATE_BITMASK (0);
+ }
+ if (bitcache & bitmask)
+ {
+ d = over (src, CONVERT_0565_TO_0888 (*dst));
+ *dst = CONVERT_8888_TO_0565 (d);
+ }
+ bitmask = UPDATE_BITMASK (bitmask);
+ dst++;
+ }
+ }
+ }
+}
+
+/*
+ * Simple bitblt
+ */
+
+static void
+fast_composite_solid_fill (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src;
+
+ src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
+
+ if (dst_image->bits.format == PIXMAN_a1)
+ {
+ src = src >> 31;
+ }
+ else if (dst_image->bits.format == PIXMAN_a8)
+ {
+ src = src >> 24;
+ }
+ else if (dst_image->bits.format == PIXMAN_r5g6b5 ||
+ dst_image->bits.format == PIXMAN_b5g6r5)
+ {
+ src = CONVERT_8888_TO_0565 (src);
+ }
+
+ pixman_fill (dst_image->bits.bits, dst_image->bits.rowstride,
+ PIXMAN_FORMAT_BPP (dst_image->bits.format),
+ dest_x, dest_y,
+ width, height,
+ src);
+}
+
+static void
+fast_composite_src_memcpy (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ int bpp = PIXMAN_FORMAT_BPP (dst_image->bits.format) / 8;
+ uint32_t n_bytes = width * bpp;
+ int dst_stride, src_stride;
+ uint8_t *dst;
+ uint8_t *src;
+
+ src_stride = src_image->bits.rowstride * 4;
+ dst_stride = dst_image->bits.rowstride * 4;
+
+ src = (uint8_t *)src_image->bits.bits + src_y * src_stride + src_x * bpp;
+ dst = (uint8_t *)dst_image->bits.bits + dest_y * dst_stride + dest_x * bpp;
+
+ while (height--)
+ {
+ memcpy (dst, src, n_bytes);
+
+ dst += dst_stride;
+ src += src_stride;
+ }
+}
+
+FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, SRC, COVER)
+FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, SRC, NONE)
+FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, SRC, PAD)
+FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, SRC, NORMAL)
+FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, OVER, COVER)
+FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, OVER, NONE)
+FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, OVER, PAD)
+FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, OVER, NORMAL)
+FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, SRC, COVER)
+FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, SRC, NONE)
+FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, SRC, PAD)
+FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, SRC, NORMAL)
+FAST_NEAREST (565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL)
+FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, OVER, COVER)
+FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, OVER, NONE)
+FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, OVER, PAD)
+FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, OVER, NORMAL)
+
+/* Use more unrolling for src_0565_0565 because it is typically CPU bound */
+static force_inline void
+scaled_nearest_scanline_565_565_SRC (uint16_t * dst,
+ uint16_t * src,
+ int32_t w,
+ pixman_fixed_t vx,
+ pixman_fixed_t unit_x,
+ pixman_fixed_t max_vx)
+{
+ uint16_t tmp1, tmp2, tmp3, tmp4;
+ while ((w -= 4) >= 0)
+ {
+ tmp1 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ tmp2 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ tmp3 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ tmp4 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ *dst++ = tmp1;
+ *dst++ = tmp2;
+ *dst++ = tmp3;
+ *dst++ = tmp4;
+ }
+ if (w & 2)
+ {
+ tmp1 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ tmp2 = src[pixman_fixed_to_int (vx)];
+ vx += unit_x;
+ *dst++ = tmp1;
+ *dst++ = tmp2;
+ }
+ if (w & 1)
+ *dst++ = src[pixman_fixed_to_int (vx)];
+}
+
+FAST_NEAREST_MAINLOOP (565_565_cover_SRC,
+ scaled_nearest_scanline_565_565_SRC,
+ uint16_t, uint16_t, COVER)
+FAST_NEAREST_MAINLOOP (565_565_none_SRC,
+ scaled_nearest_scanline_565_565_SRC,
+ uint16_t, uint16_t, NONE)
+FAST_NEAREST_MAINLOOP (565_565_pad_SRC,
+ scaled_nearest_scanline_565_565_SRC,
+ uint16_t, uint16_t, PAD)
+
+static force_inline uint32_t
+fetch_nearest (pixman_repeat_t src_repeat,
+ pixman_format_code_t format,
+ uint32_t *src, int x, int src_width)
+{
+ if (repeat (src_repeat, &x, src_width))
+ {
+ if (format == PIXMAN_x8r8g8b8)
+ return *(src + x) | 0xff000000;
+ else
+ return *(src + x);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static force_inline void
+combine_over (uint32_t s, uint32_t *dst)
+{
+ if (s)
+ {
+ uint8_t ia = 0xff - (s >> 24);
+
+ if (ia)
+ UN8x4_MUL_UN8_ADD_UN8x4 (*dst, ia, s);
+ else
+ *dst = s;
+ }
+}
+
+static force_inline void
+combine_src (uint32_t s, uint32_t *dst)
+{
+ *dst = s;
+}
+
+static void
+fast_composite_scaled_nearest (pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t *dst_line;
+ uint32_t *src_line;
+ int dst_stride, src_stride;
+ int src_width, src_height;
+ pixman_repeat_t src_repeat;
+ pixman_fixed_t unit_x, unit_y;
+ pixman_format_code_t src_format;
+ pixman_vector_t v;
+ pixman_fixed_t vy;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ /* pass in 0 instead of src_x and src_y because src_x and src_y need to be
+ * transformed from destination space to source space
+ */
+ PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, uint32_t, src_stride, src_line, 1);
+
+ /* reference point is the center of the pixel */
+ v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2;
+ v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2;
+ v.vector[2] = pixman_fixed_1;
+
+ if (!pixman_transform_point_3d (src_image->common.transform, &v))
+ return;
+
+ unit_x = src_image->common.transform->matrix[0][0];
+ unit_y = src_image->common.transform->matrix[1][1];
+
+ /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
+ v.vector[0] -= pixman_fixed_e;
+ v.vector[1] -= pixman_fixed_e;
+
+ src_height = src_image->bits.height;
+ src_width = src_image->bits.width;
+ src_repeat = src_image->common.repeat;
+ src_format = src_image->bits.format;
+
+ vy = v.vector[1];
+ while (height--)
+ {
+ pixman_fixed_t vx = v.vector[0];
+ int y = pixman_fixed_to_int (vy);
+ uint32_t *dst = dst_line;
+
+ dst_line += dst_stride;
+
+ /* adjust the y location by a unit vector in the y direction
+ * this is equivalent to transforming y+1 of the destination point to source space */
+ vy += unit_y;
+
+ if (!repeat (src_repeat, &y, src_height))
+ {
+ if (op == PIXMAN_OP_SRC)
+ memset (dst, 0, sizeof (*dst) * width);
+ }
+ else
+ {
+ int w = width;
+
+ uint32_t *src = src_line + y * src_stride;
+
+ while (w >= 2)
+ {
+ uint32_t s1, s2;
+ int x1, x2;
+
+ x1 = pixman_fixed_to_int (vx);
+ vx += unit_x;
+
+ x2 = pixman_fixed_to_int (vx);
+ vx += unit_x;
+
+ w -= 2;
+
+ s1 = fetch_nearest (src_repeat, src_format, src, x1, src_width);
+ s2 = fetch_nearest (src_repeat, src_format, src, x2, src_width);
+
+ if (op == PIXMAN_OP_OVER)
+ {
+ combine_over (s1, dst++);
+ combine_over (s2, dst++);
+ }
+ else
+ {
+ combine_src (s1, dst++);
+ combine_src (s2, dst++);
+ }
+ }
+
+ while (w--)
+ {
+ uint32_t s;
+ int x;
+
+ x = pixman_fixed_to_int (vx);
+ vx += unit_x;
+
+ s = fetch_nearest (src_repeat, src_format, src, x, src_width);
+
+ if (op == PIXMAN_OP_OVER)
+ combine_over (s, dst++);
+ else
+ combine_src (s, dst++);
+ }
+ }
+ }
+}
+
+static const pixman_fast_path_t c_fast_paths[] =
+{
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5, fast_composite_over_n_1_0565),
+ PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5, fast_composite_over_n_1_0565),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca),
+ PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888),
+ PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565),
+ PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888),
+ PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8_8),
+ PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1000_1000),
+ PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca),
+ PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, a1, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, fast_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, fast_composite_src_x888_8888),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8x8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8a8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8x8, null, b8g8r8x8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, b8g8r8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, fast_composite_src_memcpy),
+ PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
+ PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
+ PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8),
+ PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8),
+
+ SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, 8888_8888),
+
+ SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, 8888_8888),
+
+ SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, 8888_565),
+ SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, 8888_565),
+
+ SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, 565_565),
+
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, 8888_8888),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, 8888_8888),
+
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, 8888_565),
+
+#define NEAREST_FAST_PATH(op,s,d) \
+ { PIXMAN_OP_ ## op, \
+ PIXMAN_ ## s, SCALED_NEAREST_FLAGS, \
+ PIXMAN_null, 0, \
+ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
+ fast_composite_scaled_nearest, \
+ }
+
+ NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8),
+ NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8),
+ NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8),
+ NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8),
+
+ NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8),
+ NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8),
+ NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8),
+ NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8),
+
+ NEAREST_FAST_PATH (OVER, x8r8g8b8, x8r8g8b8),
+ NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8),
+ NEAREST_FAST_PATH (OVER, x8b8g8r8, x8b8g8r8),
+ NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8),
+
+ NEAREST_FAST_PATH (OVER, x8r8g8b8, a8r8g8b8),
+ NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8),
+ NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8),
+ NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8),
+
+ { PIXMAN_OP_NONE },
+};
+
+#ifdef WORDS_BIGENDIAN
+#define A1_FILL_MASK(n, offs) (((1 << (n)) - 1) << (32 - (offs) - (n)))
+#else
+#define A1_FILL_MASK(n, offs) (((1 << (n)) - 1) << (offs))
+#endif
+
+static force_inline void
+pixman_fill1_line (uint32_t *dst, int offs, int width, int v)
+{
+ if (offs)
+ {
+ int leading_pixels = 32 - offs;
+ if (leading_pixels >= width)
+ {
+ if (v)
+ *dst |= A1_FILL_MASK (width, offs);
+ else
+ *dst &= ~A1_FILL_MASK (width, offs);
+ return;
+ }
+ else
+ {
+ if (v)
+ *dst++ |= A1_FILL_MASK (leading_pixels, offs);
+ else
+ *dst++ &= ~A1_FILL_MASK (leading_pixels, offs);
+ width -= leading_pixels;
+ }
+ }
+ while (width >= 32)
+ {
+ if (v)
+ *dst++ = 0xFFFFFFFF;
+ else
+ *dst++ = 0;
+ width -= 32;
+ }
+ if (width > 0)
+ {
+ if (v)
+ *dst |= A1_FILL_MASK (width, 0);
+ else
+ *dst &= ~A1_FILL_MASK (width, 0);
+ }
+}
+
+static void
+pixman_fill1 (uint32_t *bits,
+ int stride,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ uint32_t *dst = bits + y * stride + (x >> 5);
+ int offs = x & 31;
+
+ if (xor & 1)
+ {
+ while (height--)
+ {
+ pixman_fill1_line (dst, offs, width, 1);
+ dst += stride;
+ }
+ }
+ else
+ {
+ while (height--)
+ {
+ pixman_fill1_line (dst, offs, width, 0);
+ dst += stride;
+ }
+ }
+}
+
+static void
+pixman_fill8 (uint32_t *bits,
+ int stride,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ int byte_stride = stride * (int) sizeof (uint32_t);
+ uint8_t *dst = (uint8_t *) bits;
+ uint8_t v = xor & 0xff;
+ int i;
+
+ dst = dst + y * byte_stride + x;
+
+ while (height--)
+ {
+ for (i = 0; i < width; ++i)
+ dst[i] = v;
+
+ dst += byte_stride;
+ }
+}
+
+static void
+pixman_fill16 (uint32_t *bits,
+ int stride,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ int short_stride =
+ (stride * (int)sizeof (uint32_t)) / (int)sizeof (uint16_t);
+ uint16_t *dst = (uint16_t *)bits;
+ uint16_t v = xor & 0xffff;
+ int i;
+
+ dst = dst + y * short_stride + x;
+
+ while (height--)
+ {
+ for (i = 0; i < width; ++i)
+ dst[i] = v;
+
+ dst += short_stride;
+ }
+}
+
+static void
+pixman_fill32 (uint32_t *bits,
+ int stride,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ int i;
+
+ bits = bits + y * stride + x;
+
+ while (height--)
+ {
+ for (i = 0; i < width; ++i)
+ bits[i] = xor;
+
+ bits += stride;
+ }
+}
+
+static pixman_bool_t
+fast_path_fill (pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ switch (bpp)
+ {
+ case 1:
+ pixman_fill1 (bits, stride, x, y, width, height, xor);
+ break;
+
+ case 8:
+ pixman_fill8 (bits, stride, x, y, width, height, xor);
+ break;
+
+ case 16:
+ pixman_fill16 (bits, stride, x, y, width, height, xor);
+ break;
+
+ case 32:
+ pixman_fill32 (bits, stride, x, y, width, height, xor);
+ break;
+
+ default:
+ return _pixman_implementation_fill (
+ imp->delegate, bits, stride, bpp, x, y, width, height, xor);
+ break;
+ }
+
+ return TRUE;
+}
+
+pixman_implementation_t *
+_pixman_implementation_create_fast_path (pixman_implementation_t *fallback)
+{
+ pixman_implementation_t *imp = _pixman_implementation_create (fallback, c_fast_paths);
+
+ imp->fill = fast_path_fill;
+
+ return imp;
+}
diff --git a/pixman/pixman/pixman-mmx.c b/pixman/pixman/pixman-mmx.c
index 6daa364fb..027234773 100644
--- a/pixman/pixman/pixman-mmx.c
+++ b/pixman/pixman/pixman-mmx.c
@@ -3340,10 +3340,9 @@ mmx_fill (pixman_implementation_t *imp,
}
pixman_implementation_t *
-_pixman_implementation_create_mmx (void)
+_pixman_implementation_create_mmx (pixman_implementation_t *fallback)
{
- pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
- pixman_implementation_t *imp = _pixman_implementation_create (general, mmx_fast_paths);
+ pixman_implementation_t *imp = _pixman_implementation_create (fallback, mmx_fast_paths);
imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index 1662d2c46..664260b9f 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -534,31 +534,31 @@ pixman_implementation_t *
_pixman_implementation_create_general (void);
pixman_implementation_t *
-_pixman_implementation_create_fast_path (void);
+_pixman_implementation_create_fast_path (pixman_implementation_t *fallback);
#ifdef USE_MMX
pixman_implementation_t *
-_pixman_implementation_create_mmx (void);
+_pixman_implementation_create_mmx (pixman_implementation_t *fallback);
#endif
#ifdef USE_SSE2
pixman_implementation_t *
-_pixman_implementation_create_sse2 (void);
+_pixman_implementation_create_sse2 (pixman_implementation_t *fallback);
#endif
#ifdef USE_ARM_SIMD
pixman_implementation_t *
-_pixman_implementation_create_arm_simd (void);
+_pixman_implementation_create_arm_simd (pixman_implementation_t *fallback);
#endif
#ifdef USE_ARM_NEON
pixman_implementation_t *
-_pixman_implementation_create_arm_neon (void);
+_pixman_implementation_create_arm_neon (pixman_implementation_t *fallback);
#endif
#ifdef USE_VMX
pixman_implementation_t *
-_pixman_implementation_create_vmx (void);
+_pixman_implementation_create_vmx (pixman_implementation_t *fallback);
#endif
pixman_implementation_t *
diff --git a/pixman/pixman/pixman-sse2.c b/pixman/pixman/pixman-sse2.c
index 3c0a42f41..ae5545604 100644
--- a/pixman/pixman/pixman-sse2.c
+++ b/pixman/pixman/pixman-sse2.c
@@ -5957,13 +5957,8 @@ sse2_fill (pixman_implementation_t *imp,
__attribute__((__force_align_arg_pointer__))
#endif
pixman_implementation_t *
-_pixman_implementation_create_sse2 (void)
+_pixman_implementation_create_sse2 (pixman_implementation_t *fallback)
{
-#ifdef USE_MMX
- pixman_implementation_t *fallback = _pixman_implementation_create_mmx ();
-#else
- pixman_implementation_t *fallback = _pixman_implementation_create_fast_path ();
-#endif
pixman_implementation_t *imp = _pixman_implementation_create (fallback, sse2_fast_paths);
/* SSE2 constants */
diff --git a/pixman/pixman/pixman-vmx.c b/pixman/pixman/pixman-vmx.c
index e811cf733..6868704a8 100644
--- a/pixman/pixman/pixman-vmx.c
+++ b/pixman/pixman/pixman-vmx.c
@@ -1613,10 +1613,9 @@ static const pixman_fast_path_t vmx_fast_paths[] =
};
pixman_implementation_t *
-_pixman_implementation_create_vmx (void)
+_pixman_implementation_create_vmx (pixman_implementation_t *fallback)
{
- pixman_implementation_t *fast = _pixman_implementation_create_fast_path ();
- pixman_implementation_t *imp = _pixman_implementation_create (fast, vmx_fast_paths);
+ pixman_implementation_t *imp = _pixman_implementation_create (fallback, vmx_fast_paths);
/* Set up function pointers */