2010-05-10 13:17:25 -07:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef GLCPP_H
|
|
|
|
|
#define GLCPP_H
|
|
|
|
|
|
2010-05-24 11:27:23 -07:00
|
|
|
#include <stdint.h>
|
2012-06-09 16:31:06 -07:00
|
|
|
#include <stdbool.h>
|
2010-05-24 11:27:23 -07:00
|
|
|
|
2012-12-05 12:56:16 -08:00
|
|
|
#include "main/mtypes.h"
|
|
|
|
|
|
2014-02-24 23:39:14 -08:00
|
|
|
#include "util/ralloc.h"
|
2010-05-18 22:10:04 -07:00
|
|
|
|
2010-07-29 12:40:49 +03:00
|
|
|
#include "program/hash_table.h"
|
2010-05-10 13:17:25 -07:00
|
|
|
|
|
|
|
|
#define yyscan_t void*
|
|
|
|
|
|
2010-05-18 22:10:04 -07:00
|
|
|
/* Some data types used for parser values. */
|
2010-05-10 16:16:06 -07:00
|
|
|
|
glsl/glcpp: Add short-circuiting for || and && in #if/#elif for OpenGL ES.
The GLSL ES Specification 3.00.4 says:
#if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate
as for C++ except for the following:
...
• Undefined identifiers not consumed by the defined operator do not
default to '0'. Use of such identifiers causes an error.
[Page 11 (page 127 of the PDF file)]
as well as:
The semantics of applying operators in the preprocessor match those
standard in the C++ preprocessor with the following exceptions:
• The 2nd operand in a logical and ('&&') operation is evaluated if
and only if the 1st operand evaluates to non-zero.
• The 2nd operand in a logical or ('||') operation is evaluated if
and only if the 1st operand evaluates to zero.
If an operand is not evaluated, the presence of undefined identifiers
in the operand will not cause an error.
(Note that neither of these deviations from C++ preprocessor behavior apply to
non-ES GLSL, at least as of specfication version 4.30.6).
The first portion of this, (generating an error for an undefined macro in an
(short-circuiting to squelch errors), was not implemented previously, but is
implemented in this commit.
A test is added for "make check" to ensure this behavior.
Note: The change as implemented does make the error message a bit less
precise, (it just states that an undefined macro was encountered, but not the
name of the macro).
This commit fixes the following Khronos GLES3 conformance test:
undefined_identifiers.valid_undefined_identifier_1_vertex
undefined_identifiers.valid_undefined_identifier_1_fragment
undefined_identifiers.valid_undefined_identifier_2_vertex
undefined_identifiers.valid_undefined_identifier_2_fragment
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-06-13 14:54:46 -07:00
|
|
|
typedef struct expression_value {
|
|
|
|
|
intmax_t value;
|
2014-06-13 15:16:05 -07:00
|
|
|
char *undefined_macro;
|
glsl/glcpp: Add short-circuiting for || and && in #if/#elif for OpenGL ES.
The GLSL ES Specification 3.00.4 says:
#if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate
as for C++ except for the following:
...
• Undefined identifiers not consumed by the defined operator do not
default to '0'. Use of such identifiers causes an error.
[Page 11 (page 127 of the PDF file)]
as well as:
The semantics of applying operators in the preprocessor match those
standard in the C++ preprocessor with the following exceptions:
• The 2nd operand in a logical and ('&&') operation is evaluated if
and only if the 1st operand evaluates to non-zero.
• The 2nd operand in a logical or ('||') operation is evaluated if
and only if the 1st operand evaluates to zero.
If an operand is not evaluated, the presence of undefined identifiers
in the operand will not cause an error.
(Note that neither of these deviations from C++ preprocessor behavior apply to
non-ES GLSL, at least as of specfication version 4.30.6).
The first portion of this, (generating an error for an undefined macro in an
(short-circuiting to squelch errors), was not implemented previously, but is
implemented in this commit.
A test is added for "make check" to ensure this behavior.
Note: The change as implemented does make the error message a bit less
precise, (it just states that an undefined macro was encountered, but not the
name of the macro).
This commit fixes the following Khronos GLES3 conformance test:
undefined_identifiers.valid_undefined_identifier_1_vertex
undefined_identifiers.valid_undefined_identifier_1_fragment
undefined_identifiers.valid_undefined_identifier_2_vertex
undefined_identifiers.valid_undefined_identifier_2_fragment
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-06-13 14:54:46 -07:00
|
|
|
} expression_value_t;
|
|
|
|
|
|
|
|
|
|
|
2010-05-14 10:05:11 -07:00
|
|
|
typedef struct string_node {
|
2010-05-12 12:17:10 -07:00
|
|
|
const char *str;
|
2010-05-14 10:05:11 -07:00
|
|
|
struct string_node *next;
|
|
|
|
|
} string_node_t;
|
2010-05-12 12:17:10 -07:00
|
|
|
|
2010-05-14 10:05:11 -07:00
|
|
|
typedef struct string_list {
|
|
|
|
|
string_node_t *head;
|
|
|
|
|
string_node_t *tail;
|
|
|
|
|
} string_list_t;
|
2010-05-12 12:17:10 -07:00
|
|
|
|
2010-05-25 14:52:43 -07:00
|
|
|
typedef struct token token_t;
|
|
|
|
|
typedef struct token_list token_list_t;
|
|
|
|
|
|
|
|
|
|
typedef union YYSTYPE
|
|
|
|
|
{
|
2010-05-26 09:32:57 -07:00
|
|
|
intmax_t ival;
|
glsl/glcpp: Add short-circuiting for || and && in #if/#elif for OpenGL ES.
The GLSL ES Specification 3.00.4 says:
#if, #ifdef, #ifndef, #else, #elif, and #endif are defined to operate
as for C++ except for the following:
...
• Undefined identifiers not consumed by the defined operator do not
default to '0'. Use of such identifiers causes an error.
[Page 11 (page 127 of the PDF file)]
as well as:
The semantics of applying operators in the preprocessor match those
standard in the C++ preprocessor with the following exceptions:
• The 2nd operand in a logical and ('&&') operation is evaluated if
and only if the 1st operand evaluates to non-zero.
• The 2nd operand in a logical or ('||') operation is evaluated if
and only if the 1st operand evaluates to zero.
If an operand is not evaluated, the presence of undefined identifiers
in the operand will not cause an error.
(Note that neither of these deviations from C++ preprocessor behavior apply to
non-ES GLSL, at least as of specfication version 4.30.6).
The first portion of this, (generating an error for an undefined macro in an
(short-circuiting to squelch errors), was not implemented previously, but is
implemented in this commit.
A test is added for "make check" to ensure this behavior.
Note: The change as implemented does make the error message a bit less
precise, (it just states that an undefined macro was encountered, but not the
name of the macro).
This commit fixes the following Khronos GLES3 conformance test:
undefined_identifiers.valid_undefined_identifier_1_vertex
undefined_identifiers.valid_undefined_identifier_1_fragment
undefined_identifiers.valid_undefined_identifier_2_vertex
undefined_identifiers.valid_undefined_identifier_2_fragment
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-06-13 14:54:46 -07:00
|
|
|
expression_value_t expression_value;
|
2010-05-25 14:52:43 -07:00
|
|
|
char *str;
|
2010-05-25 16:28:26 -07:00
|
|
|
string_list_t *string_list;
|
2010-05-25 14:52:43 -07:00
|
|
|
token_t *token;
|
|
|
|
|
token_list_t *token_list;
|
|
|
|
|
} YYSTYPE;
|
|
|
|
|
|
|
|
|
|
# define YYSTYPE_IS_TRIVIAL 1
|
|
|
|
|
# define YYSTYPE_IS_DECLARED 1
|
|
|
|
|
|
2010-06-16 16:35:57 -07:00
|
|
|
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
|
|
|
|
|
|
2010-07-21 13:43:47 -07:00
|
|
|
# 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)
|
|
|
|
|
|
2010-05-25 14:52:43 -07:00
|
|
|
struct token {
|
2010-05-20 08:01:44 -07:00
|
|
|
int type;
|
2010-05-25 14:52:43 -07:00
|
|
|
YYSTYPE value;
|
2010-06-16 16:58:31 -07:00
|
|
|
YYLTYPE location;
|
2010-05-25 14:52:43 -07:00
|
|
|
};
|
2010-05-20 08:01:44 -07:00
|
|
|
|
2010-05-19 13:54:37 -07:00
|
|
|
typedef struct token_node {
|
2010-05-25 14:52:43 -07:00
|
|
|
token_t *token;
|
2010-05-19 13:54:37 -07:00
|
|
|
struct token_node *next;
|
|
|
|
|
} token_node_t;
|
|
|
|
|
|
2010-05-25 14:52:43 -07:00
|
|
|
struct token_list {
|
2010-05-19 13:54:37 -07:00
|
|
|
token_node_t *head;
|
|
|
|
|
token_node_t *tail;
|
2010-05-25 20:35:01 -07:00
|
|
|
token_node_t *non_space_tail;
|
2010-05-25 14:52:43 -07:00
|
|
|
};
|
2010-05-19 13:54:37 -07:00
|
|
|
|
2010-05-14 10:44:19 -07:00
|
|
|
typedef struct argument_node {
|
2010-05-19 13:54:37 -07:00
|
|
|
token_list_t *argument;
|
2010-05-14 10:44:19 -07:00
|
|
|
struct argument_node *next;
|
|
|
|
|
} argument_node_t;
|
|
|
|
|
|
|
|
|
|
typedef struct argument_list {
|
|
|
|
|
argument_node_t *head;
|
|
|
|
|
argument_node_t *tail;
|
|
|
|
|
} argument_list_t;
|
|
|
|
|
|
2010-05-12 12:17:10 -07:00
|
|
|
typedef struct glcpp_parser glcpp_parser_t;
|
|
|
|
|
|
2010-05-18 22:10:04 -07:00
|
|
|
typedef enum {
|
|
|
|
|
TOKEN_CLASS_IDENTIFIER,
|
2010-05-20 08:01:44 -07:00
|
|
|
TOKEN_CLASS_IDENTIFIER_FINALIZED,
|
2010-05-18 22:10:04 -07:00
|
|
|
TOKEN_CLASS_FUNC_MACRO,
|
|
|
|
|
TOKEN_CLASS_OBJ_MACRO
|
|
|
|
|
} token_class_t;
|
|
|
|
|
|
|
|
|
|
token_class_t
|
|
|
|
|
glcpp_parser_classify_token (glcpp_parser_t *parser,
|
|
|
|
|
const char *identifier,
|
|
|
|
|
int *parameter_index);
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
int is_function;
|
|
|
|
|
string_list_t *parameters;
|
|
|
|
|
const char *identifier;
|
2010-05-19 13:54:37 -07:00
|
|
|
token_list_t *replacements;
|
2010-05-18 22:10:04 -07:00
|
|
|
} macro_t;
|
|
|
|
|
|
|
|
|
|
typedef struct expansion_node {
|
|
|
|
|
macro_t *macro;
|
2010-05-19 13:54:37 -07:00
|
|
|
token_node_t *replacements;
|
2010-05-18 22:10:04 -07:00
|
|
|
struct expansion_node *next;
|
|
|
|
|
} expansion_node_t;
|
|
|
|
|
|
2010-05-20 22:27:07 -07:00
|
|
|
typedef enum skip_type {
|
|
|
|
|
SKIP_NO_SKIP,
|
|
|
|
|
SKIP_TO_ELSE,
|
|
|
|
|
SKIP_TO_ENDIF
|
|
|
|
|
} skip_type_t;
|
|
|
|
|
|
|
|
|
|
typedef struct skip_node {
|
|
|
|
|
skip_type_t type;
|
2013-12-17 16:37:33 +01:00
|
|
|
bool has_else;
|
2010-06-17 12:41:46 -07:00
|
|
|
YYLTYPE loc; /* location of the initial #if/#elif/... */
|
2010-05-20 22:27:07 -07:00
|
|
|
struct skip_node *next;
|
|
|
|
|
} skip_node_t;
|
|
|
|
|
|
2010-06-02 15:32:03 -07:00
|
|
|
typedef struct active_list {
|
|
|
|
|
const char *identifier;
|
|
|
|
|
token_node_t *marker;
|
|
|
|
|
struct active_list *next;
|
|
|
|
|
} active_list_t;
|
|
|
|
|
|
2016-06-12 18:56:43 -04:00
|
|
|
struct _mesa_glsl_parse_state;
|
|
|
|
|
|
|
|
|
|
typedef void (*glcpp_extension_iterator)(
|
|
|
|
|
struct _mesa_glsl_parse_state *state,
|
|
|
|
|
void (*add_builtin_define)(glcpp_parser_t *, const char *, int),
|
|
|
|
|
glcpp_parser_t *data,
|
|
|
|
|
unsigned version,
|
|
|
|
|
bool es);
|
|
|
|
|
|
2010-05-18 22:10:04 -07:00
|
|
|
struct glcpp_parser {
|
|
|
|
|
yyscan_t scanner;
|
|
|
|
|
struct hash_table *defines;
|
2010-06-02 15:32:03 -07:00
|
|
|
active_list_t *active;
|
2014-06-12 10:39:39 -07:00
|
|
|
int lexing_directive;
|
glcpp: Implicitly resolve version after the first non-space/hash token.
We resolved the implicit version directive when processing control lines,
such as #ifdef, to ensure any built-in macros exist. However, we failed
to resolve it when handling ordinary text.
For example,
int x = __VERSION__;
should resolve __VERSION__ to 110, but since we never resolved the implicit
version, none of the built-in macros exist, so it was left as is.
This also meant we allowed the following shader to slop through:
123
#version 120
Nothing would cause the implicit version to take effect, so when we saw
the #version directive, we thought everything was peachy.
This patch makes the lexer's per-token action resolve the implicit
version on the first non-space/newline/hash token that isn't part of
a #version directive, fulfilling the GLSL language spec:
"The #version directive must occur in a shader before anything else,
except for comments and white space."
Because we emit #version as HASH_TOKEN then VERSION_TOKEN, we have to
allow HASH_TOKEN to slop through as well, so we don't resolve the
implicit version as soon as we see the # character. However, this is
fine, because the parser's HASH_TOKEN NEWLINE rule does resolve the
version, disallowing cases like:
#
#version 120
This patch also adds the above shaders as new glcpp tests.
Fixes dEQP-GLES2.functional.shaders.preprocessor.predefined_macros.
{gl_es_1_vertex,gl_es_1_fragment}.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2016-03-04 18:26:00 -08:00
|
|
|
int lexing_version_directive;
|
2010-05-25 16:59:02 -07:00
|
|
|
int space_tokens;
|
2014-06-20 14:58:48 -07:00
|
|
|
int last_token_was_newline;
|
glsl/glcpp: Correctly parse directives with intervening comments
It's legal (though highly bizarre) for a pre-processor directive to look like
this:
# /* why? */ define FOO bar
This behavior comes about since the specification defines separate logical
phases in a precise order, and comment-removal occurs in a phase before the
identification of directives.
Our implementation does not use an actual separate phase for comment removal,
so some extra care is necessary to correctly parse this. What we want is for
'#' to introduce a directive iff it is the first token on a line, (ignoring
whitespace and comments). Previously, we had a lexical rule that worked only
for whitespace (not comments) with the following regular expression to find a
directive-introducing '#' at the beginning of a line:
HASH ^{HSPACE}*#{HSPACE}*
In this commit, we switch to instead use a simple literal match of '#' to
return a HASH_TOKEN token and add a new <HASH> start condition for whenever
the HASH_TOKEN is the first non-space token of a line. This requires the
addition of the new bit of state: first_non_space_token_this_line.
This approach has a couple of implications on the glcpp parser:
1. The parser now sees two separate tokens, (such as HASH_TOKEN and
HASH_DEFINE) where it previously saw one token (HASH_DEFINE) for
the sequence "#define". This is a straightforward change throughout
the grammar.
2. The parser may now see a SPACE token before the HASH_TOKEN token of
a directive. Previously the lexical regular expression for {HASH}
would eat up the space and there would be no SPACE token.
This second implication is a bit of a nuisance for the parser. It causes a
SPACE token to appear in a production of the grammar with the following two
definitions of a control_line:
control_line
SPACE control_line
This is really ugly, since normally a space would simply be a token
separator, so it wouldn't appear in the tokens of a production. This leads to
a further problem with interleaved spaces and comments:
/* ... */ /* ... */ #define /* ..*/
For this, we must not return several consecutive SPACE tokens, or else we would need an arbitrary number of new productions:
SPACE SPACE control_line
SPACE SPACE SPACE control_line
ad nauseam
To avoid this problem, in this commit we also change the lexer to emit only a
single SPACE token for any series of consecutive spaces, (whether from actual
whitespace or comments). For this compression, we add a new bit of parser
state: last_token_was_space. And we also update the expected results of all
necessary test cases for the new compression of space tokens.
Fortunately, the compression of spaces should not lead to any semantic changes
in terms of what the eventual GLSL compiler sees.
So there's a lot happening in this commit, (particularly for such a tiny
feature). But fortunately, the lexer itself is looking cleaner than ever. The
only ugly bit is all the state updating, but it is at least isolated to a
single shared function.
Of course, a new "make check" test is added for the new feature, (directives
with comments and whitespace interleaved in many combinations).
And this commit fixes the following Khronos GLES3 CTS tests:
function_definition_with_comments_vertex
function_definition_with_comments_fragment
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2014-06-25 12:20:22 -07:00
|
|
|
int last_token_was_space;
|
|
|
|
|
int first_non_space_token_this_line;
|
Treat newlines as space when invoking a function-like macro invocation.
This adds three new pieces of state to the parser, (is_control_line,
newline_as_space, and paren_count), and a large amount of messy
code. I'd definitely like to see a cleaner solution for this.
With this fix, the "define-func-extra-newlines" now passes so we put
it back to test #26 where it was originally (lately it has been known
as test #55).
Also, we tweak test 25 slightly. Previously this test was ending a
file function-like macro name that was not actually a macro (not
followed by a left parenthesis). As is, this fix was making that test
fail because the text_line production expects to see a terminating
NEWLINE, but that NEWLINE is now getting turned into a SPACE here.
This seems unlikely to be a problem in the wild, (function macros
being used in a non-macro sense seems rare enough---but more than
likely they won't happen at the end of a file). Still, we document
this shortcoming in the README.
2010-05-26 15:57:10 -07:00
|
|
|
int newline_as_space;
|
|
|
|
|
int in_control_line;
|
|
|
|
|
int paren_count;
|
glcpp: Replace multi-line comment with a space (even as part of macro definition)
The preprocessor has always replaced multi-line comments with a single space
character, (as required by the specification), but as of commit
bd55ba568b301d0f764cd1ca015e84e1ae932c8b the lexer also emitted a NEWLINE
token for each newline within the comment, (in order to preserve line
numbers).
The emitting of NEWLINE tokens within the comment broke the rule of "replace a
multi-line comment with a single space" as could be exposed by code like the
following:
#define FOO a/*
*/b
FOO
Prior to commit bd55ba568b301d0f764cd1ca015e84e1ae932c8b, this code defined
the macro FOO as "a b" as desired. Since that commit, this code instead
defines FOO as "a" and leaves a stray "b" in the output.
In this commit, we fix this by not emitting the NEWLINE tokens while lexing
the comment, but instead merely counting them in the commented_newlines
variable. Then, when the lexer next encounters a non-commented newline it
switches to a NEWLINE_CATCHUP state to emit as many NEWLINE tokens as
necessary (so that subsequent parsing stages still generate correct line
numbers).
Of course, it would have been more clear if we could have written a loop to
emit all the newlines, but flex conventions prevent that, (we must use
"return" for each token we emit).
It similarly would have been clear to have a new rule restricted to the
<NEWLINE_CATCHUP> state with an action much like the body of this if
condition. The problem with that is that this rule must not consume any
characters. It might be possible to write a rule that matches a single
lookahead of any character, but then we would also need an additional rule to
ensure for the <EOF> case where there are no additional characters available
for the lookahead to match.
Given those considerations, and given that the SKIP-state manipulation already
involves a code block at the top of the lexer function, before any rules, it
seems best to me to go with the implementation here which adds a similar
pre-rule code block for the NEWLINE_CATCHUP.
Finally, this commit also changes the expected output of a few, existing glcpp
tests. The change here is that the space character resulting from the
multi-line comment is now emitted before the newlines corresponding to that
comment. (Previously, the newlines were emitted first, and the space character
afterward.)
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72686
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-19 16:06:31 -08:00
|
|
|
int commented_newlines;
|
2010-05-20 22:27:07 -07:00
|
|
|
skip_node_t *skip_stack;
|
glsl/glcpp: Stop using a lexer start condition (<SKIP>) for token skipping.
Here, "skipping" refers to the lexer not emitting any tokens for portions of
the file within an #if condition (or similar) that evaluates to false.
Previously, the lexer had a special <SKIP> start condition used to control
this skipping. This start condition was not handled like a normal start
condition. Instead, there was a particularly ugly block of code set to be
included at the top of the generated lexing loop that would change from
<INITIAL> to <SKIP> or from <SKIP> to <INITIAL> depending on various pieces of
parser state, (such as parser->skip_state and parser->lexing_directive).
Not only was that an ugly approach, but the <SKIP> start condition was
complicating several glcpp bug fixes I attempted recently that want to use
start conditions for other purposes, (such as a new <HASH> start condition).
The recently added RETURN_TOKEN macro gives us a convenient way to implement
skipping without using a lexer start condition. Now, at the top of the
generated lexer, we examine all the necessary parser state and set a new
parser->skipping bit. Then, in RETURN_TOKEN, we examine parser->skipping to
determine whether to actually emit the token or not.
Besides this, there are only a couple of other places where we need to examine
the skipping bit (other than when returning a token):
* To avoid emitting an error for #error if skipped.
* To avoid entering the <DEFINE> start condition for a #define that is
skipped.
With all of this in place in the present commit, there are hopefully no
behavioral changes with this patch, ("make check" still passes all of the
glcpp tests at least).
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2014-06-20 16:18:23 -07:00
|
|
|
int skipping;
|
2010-05-26 11:15:21 -07:00
|
|
|
token_list_t *lex_from_list;
|
|
|
|
|
token_node_t *lex_from_node;
|
2010-06-16 11:57:48 -07:00
|
|
|
char *output;
|
2010-06-18 19:52:36 -07:00
|
|
|
char *info_log;
|
2012-02-09 20:33:44 -08:00
|
|
|
size_t output_length;
|
|
|
|
|
size_t info_log_length;
|
2010-06-21 12:39:49 -07:00
|
|
|
int error;
|
2016-06-12 18:56:43 -04:00
|
|
|
glcpp_extension_iterator extensions;
|
|
|
|
|
void *state;
|
2014-01-26 18:06:18 -08:00
|
|
|
gl_api api;
|
2016-08-09 14:31:49 -07:00
|
|
|
unsigned version;
|
2012-06-09 16:31:06 -07:00
|
|
|
bool has_new_line_number;
|
|
|
|
|
int new_line_number;
|
|
|
|
|
bool has_new_source_number;
|
|
|
|
|
int new_source_number;
|
2012-11-26 14:53:54 -08:00
|
|
|
bool is_gles;
|
2010-05-18 22:10:04 -07:00
|
|
|
};
|
|
|
|
|
|
2010-05-12 12:17:10 -07:00
|
|
|
glcpp_parser_t *
|
2016-06-12 18:56:43 -04:00
|
|
|
glcpp_parser_create (glcpp_extension_iterator extensions, void *state, gl_api api);
|
2010-05-10 16:16:06 -07:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
glcpp_parser_parse (glcpp_parser_t *parser);
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-12 12:17:10 -07:00
|
|
|
glcpp_parser_destroy (glcpp_parser_t *parser);
|
2010-05-10 16:16:06 -07:00
|
|
|
|
2014-01-17 14:22:49 -08:00
|
|
|
void
|
2014-01-25 11:57:02 -08:00
|
|
|
glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser);
|
2014-01-17 14:22:49 -08:00
|
|
|
|
2010-06-23 14:00:27 -07:00
|
|
|
int
|
2012-09-14 10:13:01 +10:00
|
|
|
glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
|
2016-06-12 18:56:43 -04:00
|
|
|
glcpp_extension_iterator extensions, void *state,
|
|
|
|
|
struct gl_context *g_ctx);
|
2010-06-23 14:00:27 -07:00
|
|
|
|
2010-06-18 19:54:25 -07:00
|
|
|
/* Functions for writing to the info log */
|
|
|
|
|
|
2010-06-17 12:03:25 -07:00
|
|
|
void
|
|
|
|
|
glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
|
|
|
|
|
|
2010-06-18 19:54:25 -07:00
|
|
|
void
|
|
|
|
|
glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
|
|
|
|
|
|
2010-05-10 16:16:06 -07:00
|
|
|
/* Generated by glcpp-lex.l to glcpp-lex.c */
|
|
|
|
|
|
2010-05-10 13:17:25 -07:00
|
|
|
int
|
2010-05-19 10:01:29 -07:00
|
|
|
glcpp_lex_init_extra (glcpp_parser_t *parser, yyscan_t* scanner);
|
2010-05-10 13:17:25 -07:00
|
|
|
|
2010-06-16 12:01:17 -07:00
|
|
|
void
|
|
|
|
|
glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader);
|
|
|
|
|
|
2010-05-10 13:17:25 -07:00
|
|
|
int
|
2010-06-16 16:35:57 -07:00
|
|
|
glcpp_lex (YYSTYPE *lvalp, YYLTYPE *llocp, yyscan_t scanner);
|
2010-05-10 13:17:25 -07:00
|
|
|
|
|
|
|
|
int
|
2010-05-19 10:01:29 -07:00
|
|
|
glcpp_lex_destroy (yyscan_t scanner);
|
2010-05-10 13:17:25 -07:00
|
|
|
|
|
|
|
|
/* Generated by glcpp-parse.y to glcpp-parse.c */
|
|
|
|
|
|
|
|
|
|
int
|
2010-05-10 16:16:06 -07:00
|
|
|
yyparse (glcpp_parser_t *parser);
|
2010-05-10 13:17:25 -07:00
|
|
|
|
|
|
|
|
#endif
|