diff options
Diffstat (limited to 'src/glsl')
27 files changed, 861 insertions, 414 deletions
diff --git a/src/glsl/SConscript b/src/glsl/SConscript index 6f1f81b199..8e18626c40 100644 --- a/src/glsl/SConscript +++ b/src/glsl/SConscript @@ -18,11 +18,12 @@ sources = [ 'pp/sl_pp_process.c', 'pp/sl_pp_purify.c', 'pp/sl_pp_token.c', + 'pp/sl_pp_token_util.c', 'pp/sl_pp_version.c', 'cl/sl_cl_parse.c', ] -glsl = env.StaticLibrary( +glsl = env.ConvenienceLibrary( target = 'glsl', source = sources, ) diff --git a/src/glsl/apps/.gitignore b/src/glsl/apps/.gitignore new file mode 100644 index 0000000000..7e011ce7a1 --- /dev/null +++ b/src/glsl/apps/.gitignore @@ -0,0 +1,5 @@ +compile +process +purify +tokenise +version diff --git a/src/glsl/apps/compile.c b/src/glsl/apps/compile.c index b1165420fb..c9a830b9f3 100644 --- a/src/glsl/apps/compile.c +++ b/src/glsl/apps/compile.c @@ -50,12 +50,8 @@ main(int argc, struct sl_pp_purify_options options; char errmsg[100] = ""; struct sl_pp_context *context; - struct sl_pp_token_info *tokens; unsigned int version; - unsigned int tokens_eaten; - struct sl_pp_token_info *outtokens; FILE *out; - unsigned int i, j; unsigned char *outbytes; unsigned int cboutbytes; unsigned int shader_type; @@ -118,7 +114,7 @@ main(int argc, memset(&options, 0, sizeof(options)); - context = sl_pp_context_create(); + context = sl_pp_context_create(inbuf, &options); if (!context) { fprintf(out, "$CONTEXERROR\n"); @@ -128,24 +124,12 @@ main(int argc, return 0; } - if (sl_pp_tokenise(context, inbuf, &options, &tokens)) { - fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); - - printf("Error: %s.\n", sl_pp_context_error_message(context)); - sl_pp_context_destroy(context); - free(inbuf); - fclose(out); - return 0; - } - - free(inbuf); - - if (sl_pp_version(context, tokens, &version, &tokens_eaten)) { + if (sl_pp_version(context, &version)) { fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); printf("Error: %s\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); - free(tokens); + free(inbuf); fclose(out); return 0; } @@ -156,39 +140,12 @@ main(int argc, printf("Error: %s\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); - free(tokens); - fclose(out); - return 0; - } - - if (sl_pp_process(context, &tokens[tokens_eaten], &outtokens)) { - fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); - - printf("Error: %s\n", sl_pp_context_error_message(context)); - sl_pp_context_destroy(context); - free(tokens); + free(inbuf); fclose(out); return 0; } - free(tokens); - - for (i = j = 0; outtokens[i].token != SL_PP_EOF; i++) { - switch (outtokens[i].token) { - case SL_PP_NEWLINE: - case SL_PP_EXTENSION_REQUIRE: - case SL_PP_EXTENSION_ENABLE: - case SL_PP_EXTENSION_WARN: - case SL_PP_EXTENSION_DISABLE: - case SL_PP_LINE: - break; - default: - outtokens[j++] = outtokens[i]; - } - } - outtokens[j] = outtokens[i]; - - if (sl_cl_compile(context, outtokens, shader_type, 1, &outbytes, &cboutbytes, errmsg, sizeof(errmsg)) == 0) { + if (sl_cl_compile(context, shader_type, 1, &outbytes, &cboutbytes, errmsg, sizeof(errmsg)) == 0) { unsigned int i; unsigned int line = 0; @@ -228,7 +185,7 @@ main(int argc, } sl_pp_context_destroy(context); - free(outtokens); + free(inbuf); fclose(out); return 0; } diff --git a/src/glsl/apps/process.c b/src/glsl/apps/process.c index d7bc16577e..569890210f 100644 --- a/src/glsl/apps/process.c +++ b/src/glsl/apps/process.c @@ -41,9 +41,7 @@ main(int argc, char *inbuf; struct sl_pp_purify_options options; struct sl_pp_context *context; - struct sl_pp_token_info *tokens; unsigned int version; - unsigned int tokens_eaten; struct sl_pp_token_info *outtokens; FILE *out; unsigned int i; @@ -90,7 +88,7 @@ main(int argc, memset(&options, 0, sizeof(options)); - context = sl_pp_context_create(); + context = sl_pp_context_create(inbuf, &options); if (!context) { fprintf(out, "$CONTEXERROR\n"); @@ -99,23 +97,12 @@ main(int argc, return 1; } - if (sl_pp_tokenise(context, inbuf, &options, &tokens)) { + if (sl_pp_version(context, &version)) { fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); free(inbuf); fclose(out); - return 1; - } - - free(inbuf); - - if (sl_pp_version(context, tokens, &version, &tokens_eaten)) { - fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); - - sl_pp_context_destroy(context); - free(tokens); - fclose(out); return -1; } @@ -125,7 +112,7 @@ main(int argc, printf("Error: %s\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); - free(tokens); + free(inbuf); fclose(out); return 0; } @@ -135,21 +122,21 @@ main(int argc, printf("Error: %s\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); - free(tokens); + free(inbuf); fclose(out); return 0; } - if (sl_pp_process(context, &tokens[tokens_eaten], &outtokens)) { + if (sl_pp_process(context, &outtokens)) { fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); - free(tokens); + free(inbuf); fclose(out); return -1; } - free(tokens); + free(inbuf); for (i = 0; outtokens[i].token != SL_PP_EOF; i++) { switch (outtokens[i].token) { diff --git a/src/glsl/apps/tokenise.c b/src/glsl/apps/tokenise.c index 91368c32a4..9ff73157e9 100644 --- a/src/glsl/apps/tokenise.c +++ b/src/glsl/apps/tokenise.c @@ -87,7 +87,7 @@ main(int argc, memset(&options, 0, sizeof(options)); - context = sl_pp_context_create(); + context = sl_pp_context_create(inbuf, &options); if (!context) { fprintf(out, "$CONTEXERROR\n"); @@ -96,7 +96,7 @@ main(int argc, return 1; } - if (sl_pp_tokenise(context, inbuf, &options, &tokens)) { + if (sl_pp_tokenise(context, &tokens)) { fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); diff --git a/src/glsl/apps/version.c b/src/glsl/apps/version.c index 6f77f230ca..40a4a069c3 100644 --- a/src/glsl/apps/version.c +++ b/src/glsl/apps/version.c @@ -41,9 +41,7 @@ main(int argc, char *inbuf; struct sl_pp_purify_options options; struct sl_pp_context *context; - struct sl_pp_token_info *tokens; unsigned int version; - unsigned int tokens_eaten; FILE *out; if (argc != 3) { @@ -88,7 +86,7 @@ main(int argc, memset(&options, 0, sizeof(options)); - context = sl_pp_context_create(); + context = sl_pp_context_create(inbuf, &options); if (!context) { fprintf(out, "$CONTEXERROR\n"); @@ -97,33 +95,19 @@ main(int argc, return 1; } - if (sl_pp_tokenise(context, inbuf, &options, &tokens)) { + if (sl_pp_version(context, &version)) { fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); sl_pp_context_destroy(context); free(inbuf); fclose(out); - return 1; - } - - free(inbuf); - - if (sl_pp_version(context, tokens, &version, &tokens_eaten)) { - fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context)); - - sl_pp_context_destroy(context); - free(tokens); - fclose(out); return -1; } sl_pp_context_destroy(context); - free(tokens); + free(inbuf); - fprintf(out, - "%u\n%u\n", - version, - tokens_eaten); + fprintf(out, "%u\n", version); fclose(out); diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c index a9db65c7ad..e9b3707ac1 100644 --- a/src/glsl/cl/sl_cl_parse.c +++ b/src/glsl/cl/sl_cl_parse.c @@ -321,10 +321,13 @@ struct parse_dict { struct parse_context { struct sl_pp_context *context; - const struct sl_pp_token_info *input; struct parse_dict dict; + struct sl_pp_token_info *tokens; + unsigned int tokens_read; + unsigned int tokens_cap; + unsigned char *out_buf; unsigned int out_cap; @@ -332,6 +335,7 @@ struct parse_context { unsigned int parsing_builtin; char error[256]; + int process_error; }; @@ -366,7 +370,7 @@ _update(struct parse_context *ctx, static void _error(struct parse_context *ctx, - char *msg) + const char *msg) { if (ctx->error[0] == '\0') { strcpy(ctx->error, msg); @@ -374,12 +378,98 @@ _error(struct parse_context *ctx, } +static const struct sl_pp_token_info * +_fetch_token(struct parse_context *ctx, + unsigned int pos) +{ + if (ctx->process_error) { + return NULL; + } + + while (pos >= ctx->tokens_read) { + if (ctx->tokens_read == ctx->tokens_cap) { + ctx->tokens_cap += 1024; + ctx->tokens = realloc(ctx->tokens, + ctx->tokens_cap * sizeof(struct sl_pp_token_info)); + if (!ctx->tokens) { + _error(ctx, "out of memory"); + ctx->process_error = 1; + return NULL; + } + } + if (sl_pp_process_get(ctx->context, &ctx->tokens[ctx->tokens_read])) { + _error(ctx, sl_pp_context_error_message(ctx->context)); + ctx->process_error = 1; + return NULL; + } + switch (ctx->tokens[ctx->tokens_read].token) { + case SL_PP_COMMA: + case SL_PP_SEMICOLON: + case SL_PP_LBRACE: + case SL_PP_RBRACE: + case SL_PP_LPAREN: + case SL_PP_RPAREN: + case SL_PP_LBRACKET: + case SL_PP_RBRACKET: + case SL_PP_DOT: + case SL_PP_INCREMENT: + case SL_PP_ADDASSIGN: + case SL_PP_PLUS: + case SL_PP_DECREMENT: + case SL_PP_SUBASSIGN: + case SL_PP_MINUS: + case SL_PP_BITNOT: + case SL_PP_NOTEQUAL: + case SL_PP_NOT: + case SL_PP_MULASSIGN: + case SL_PP_STAR: + case SL_PP_DIVASSIGN: + case SL_PP_SLASH: + case SL_PP_MODASSIGN: + case SL_PP_MODULO: + case SL_PP_LSHIFTASSIGN: + case SL_PP_LSHIFT: + case SL_PP_LESSEQUAL: + case SL_PP_LESS: + case SL_PP_RSHIFTASSIGN: + case SL_PP_RSHIFT: + case SL_PP_GREATEREQUAL: + case SL_PP_GREATER: + case SL_PP_EQUAL: + case SL_PP_ASSIGN: + case SL_PP_AND: + case SL_PP_BITANDASSIGN: + case SL_PP_BITAND: + case SL_PP_XOR: + case SL_PP_BITXORASSIGN: + case SL_PP_BITXOR: + case SL_PP_OR: + case SL_PP_BITORASSIGN: + case SL_PP_BITOR: + case SL_PP_QUESTION: + case SL_PP_COLON: + case SL_PP_IDENTIFIER: + case SL_PP_UINT: + case SL_PP_FLOAT: + case SL_PP_EOF: + ctx->tokens_read++; + break; + default: + ; /* no-op */ + } + } + return &ctx->tokens[pos]; +} + + static int _parse_token(struct parse_context *ctx, enum sl_pp_token token, struct parse_state *ps) { - if (ctx->input[ps->in].token == token) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == token) { ps->in++; return 0; } @@ -392,8 +482,9 @@ _parse_id(struct parse_context *ctx, int id, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_IDENTIFIER && - ctx->input[ps->in].data.identifier == id) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_IDENTIFIER && input->data.identifier == id) { ps->in++; return 0; } @@ -405,8 +496,10 @@ static int _parse_identifier(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_IDENTIFIER) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data.identifier); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_IDENTIFIER) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data.identifier); do { _emit(ctx, &ps->out, *cstr); @@ -422,8 +515,10 @@ static int _parse_float(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_FLOAT) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._float); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_FLOAT) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data._float); _emit(ctx, &ps->out, 1); do { @@ -440,8 +535,10 @@ static int _parse_uint(struct parse_context *ctx, struct parse_state *ps) { - if (ctx->input[ps->in].token == SL_PP_UINT) { - const char *cstr = sl_pp_context_cstr(ctx->context, ctx->input[ps->in].data._uint); + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); + + if (input && input->token == SL_PP_UINT) { + const char *cstr = sl_pp_context_cstr(ctx->context, input->data._uint); _emit(ctx, &ps->out, 1); do { @@ -614,13 +711,14 @@ _parse_type_qualifier(struct parse_context *ctx, struct parse_state *ps) { struct parse_state p = *ps; + const struct sl_pp_token_info *input = _fetch_token(ctx, p.in); unsigned int e = _emit(ctx, &p.out, 0); int id; - if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[p.in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._const) { _update(ctx, e, TYPE_QUALIFIER_CONST); @@ -771,6 +869,7 @@ _parse_type_specifier_nonarray(struct parse_context *ctx, { struct parse_state p = *ps; unsigned int e = _emit(ctx, &p.out, 0); + const struct sl_pp_token_info *input; int id; if (_parse_struct_specifier(ctx, &p) == 0) { @@ -779,10 +878,11 @@ _parse_type_specifier_nonarray(struct parse_context *ctx, return 0; } - if (ctx->input[p.in].token != SL_PP_IDENTIFIER) { + input = _fetch_token(ctx, p.in); + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[p.in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._void) { _update(ctx, e, TYPE_SPECIFIER_VOID); @@ -1696,13 +1796,14 @@ static int _parse_precision(struct parse_context *ctx, struct parse_state *ps) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); int id; unsigned int precision; - if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[ps->in].data.identifier; + id = input->data.identifier; if (id == ctx->dict.lowp) { precision = PRECISION_LOW; @@ -1724,13 +1825,14 @@ static int _parse_prectype(struct parse_context *ctx, struct parse_state *ps) { + const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in); int id; unsigned int type; - if (ctx->input[ps->in].token != SL_PP_IDENTIFIER) { + if (!input || input->token != SL_PP_IDENTIFIER) { return -1; } - id = ctx->input[ps->in].data.identifier; + id = input->data.identifier; if (id == ctx->dict._int) { type = TYPE_SPECIFIER_INT; @@ -2607,7 +2709,6 @@ _parse_translation_unit(struct parse_context *ctx, int sl_cl_compile(struct sl_pp_context *context, - const struct sl_pp_token_info *input, unsigned int shader_type, unsigned int parsing_builtin, unsigned char **output, @@ -2619,7 +2720,6 @@ sl_cl_compile(struct sl_pp_context *context, struct parse_state ps; ctx.context = context; - ctx.input = input; ADD_NAME_STR(ctx, _void, "void"); ADD_NAME_STR(ctx, _float, "float"); @@ -2699,16 +2799,27 @@ sl_cl_compile(struct sl_pp_context *context, ctx.parsing_builtin = 1; ctx.error[0] = '\0'; + ctx.process_error = 0; + + ctx.tokens_cap = 1024; + ctx.tokens_read = 0; + ctx.tokens = malloc(ctx.tokens_cap * sizeof(struct sl_pp_token_info)); + if (!ctx.tokens) { + strncpy(error, "out of memory", cberror); + return -1; + } ps.in = 0; ps.out = 0; if (_parse_translation_unit(&ctx, &ps)) { strncpy(error, ctx.error, cberror); + free(ctx.tokens); return -1; } *output = ctx.out_buf; *cboutput = ps.out; + free(ctx.tokens); return 0; } diff --git a/src/glsl/cl/sl_cl_parse.h b/src/glsl/cl/sl_cl_parse.h index 23a0d5fee0..dd5791d590 100644 --- a/src/glsl/cl/sl_cl_parse.h +++ b/src/glsl/cl/sl_cl_parse.h @@ -30,7 +30,6 @@ int sl_cl_compile(struct sl_pp_context *context, - const struct sl_pp_token_info *input, unsigned int shader_type, unsigned int parsing_builtin, unsigned char **output, diff --git a/src/glsl/pp/Makefile b/src/glsl/pp/Makefile index 819079f625..fda1c4202b 100644 --- a/src/glsl/pp/Makefile +++ b/src/glsl/pp/Makefile @@ -20,6 +20,7 @@ C_SOURCES = \ sl_pp_process.c \ sl_pp_purify.c \ sl_pp_token.c \ + sl_pp_token_util.c \ sl_pp_version.c include ../Makefile.template diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c index afc1b84d16..74a9bdddfd 100644 --- a/src/glsl/pp/sl_pp_context.c +++ b/src/glsl/pp/sl_pp_context.c @@ -32,7 +32,8 @@ struct sl_pp_context * -sl_pp_context_create(void) +sl_pp_context_create(const char *input, + const struct sl_pp_purify_options *options) { struct sl_pp_context *context; @@ -46,19 +47,30 @@ sl_pp_context_create(void) return NULL; } - context->getc_buf = malloc(64 * sizeof(char)); + context->getc_buf_capacity = 64; + context->getc_buf = malloc(context->getc_buf_capacity * sizeof(char)); if (!context->getc_buf) { sl_pp_context_destroy(context); return NULL; } + if (sl_pp_token_buffer_init(&context->tokens, context)) { + sl_pp_context_destroy(context); + return NULL; + } + context->macro_tail = &context->macro; context->if_ptr = SL_PP_MAX_IF_NESTING; context->if_value = 1; memset(context->error_msg, 0, sizeof(context->error_msg)); + context->error_line = 1; context->line = 1; context->file = 0; + sl_pp_purify_state_init(&context->pure, input, options); + + memset(&context->process_state, 0, sizeof(context->process_state)); + return context; } @@ -69,6 +81,8 @@ sl_pp_context_destroy(struct sl_pp_context *context) free(context->cstr_pool); sl_pp_macro_free(context->macro); free(context->getc_buf); + sl_pp_token_buffer_destroy(&context->tokens); + free(context->process_state.out); free(context); } } @@ -79,6 +93,19 @@ sl_pp_context_error_message(const struct sl_pp_context *context) return context->error_msg; } +void +sl_pp_context_error_position(const struct sl_pp_context *context, + unsigned int *file, + unsigned int *line) +{ + if (file) { + *file = 0; + } + if (line) { + *line = context->error_line; + } +} + int sl_pp_context_add_predefined(struct sl_pp_context *context, const char *name, diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h index d95d29e275..3eada380cd 100644 --- a/src/glsl/pp/sl_pp_context.h +++ b/src/glsl/pp/sl_pp_context.h @@ -30,7 +30,9 @@ #include "sl_pp_dict.h" #include "sl_pp_macro.h" +#include "sl_pp_process.h" #include "sl_pp_purify.h" +#include "sl_pp_token_util.h" #define SL_PP_MAX_IF_NESTING 64 @@ -71,6 +73,7 @@ struct sl_pp_context { unsigned int if_value; char error_msg[SL_PP_MAX_ERROR_MSG]; + unsigned int error_line; unsigned int line; unsigned int file; @@ -80,6 +83,10 @@ struct sl_pp_context { char *getc_buf; unsigned int getc_buf_size; unsigned int getc_buf_capacity; + + struct sl_pp_token_buffer tokens; + + struct sl_pp_process_state process_state; }; #endif /* SL_PP_CONTEXT_H */ diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c index e004c9f95b..808a6a0d4f 100644 --- a/src/glsl/pp/sl_pp_define.c +++ b/src/glsl/pp/sl_pp_define.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_error.c b/src/glsl/pp/sl_pp_error.c index a9eeff98ba..b628e37ce8 100644 --- a/src/glsl/pp/sl_pp_error.c +++ b/src/glsl/pp/sl_pp_error.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_extension.c b/src/glsl/pp/sl_pp_extension.c index 67b24404d4..8af5731e84 100644 --- a/src/glsl/pp/sl_pp_extension.c +++ b/src/glsl/pp/sl_pp_extension.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" diff --git a/src/glsl/pp/sl_pp_if.c b/src/glsl/pp/sl_pp_if.c index 6610bc69f3..f12f0f142c 100644 --- a/src/glsl/pp/sl_pp_if.c +++ b/src/glsl/pp/sl_pp_if.c @@ -31,55 +31,50 @@ #include "sl_pp_process.h" -static void -skip_whitespace(const struct sl_pp_token_info *input, - unsigned int *pi) -{ - while (input[*pi].token == SL_PP_WHITESPACE) { - (*pi)++; - } -} - static int _parse_defined(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int *pi, + struct sl_pp_token_buffer *buffer, struct sl_pp_process_state *state) { + struct sl_pp_token_info input; int parens = 0; int macro_name; struct sl_pp_macro *macro; int defined = 0; struct sl_pp_token_info result; - skip_whitespace(input, pi); - if (input[*pi].token == SL_PP_LPAREN) { - (*pi)++; - skip_whitespace(input, pi); + if (sl_pp_token_buffer_skip_white(buffer, &input)) { + return -1; + } + + if (input.token == SL_PP_LPAREN) { + if (sl_pp_token_buffer_skip_white(buffer, &input)) { + return -1; + } parens = 1; } - if (input[*pi].token != SL_PP_IDENTIFIER) { + if (input.token != SL_PP_IDENTIFIER) { strcpy(context->error_msg, "expected an identifier"); return -1; } - macro_name = input[*pi].data.identifier; + macro_name = input.data.identifier; for (macro = context->macro; macro; macro = macro->next) { if (macro->name == macro_name) { defined = 1; break; } } - (*pi)++; if (parens) { - skip_whitespace(input, pi); - if (input[*pi].token != SL_PP_RPAREN) { + if (sl_pp_token_buffer_skip_white(buffer, &input)) { + return -1; + } + if (input.token != SL_PP_RPAREN) { strcpy(context->error_msg, "expected `)'"); return -1; } - (*pi)++; } result.token = SL_PP_UINT; @@ -108,12 +103,10 @@ _evaluate_if_stack(struct sl_pp_context *context) static int _parse_if(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last) + struct sl_pp_token_buffer *buffer) { - unsigned int i; struct sl_pp_process_state state; + int found_end = 0; struct sl_pp_token_info eof; int result; @@ -123,34 +116,40 @@ _parse_if(struct sl_pp_context *context, } memset(&state, 0, sizeof(state)); - for (i = first; i < last;) { - switch (input[i].token) { + while (!found_end) { + struct sl_pp_token_info input; + + sl_pp_token_buffer_get(buffer, &input); + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_IDENTIFIER: - if (input[i].data.identifier == context->dict.defined) { - i++; - if (_parse_defined(context, input, &i, &state)) { + if (input.data.identifier == context->dict.defined) { + if (_parse_defined(context, buffer, &state)) { free(state.out); return -1; } } else { - if (sl_pp_macro_expand(context, input, &i, NULL, &state, sl_pp_macro_expand_unknown_to_0)) { + sl_pp_token_buffer_unget(buffer, &input); + if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_unknown_to_0)) { free(state.out); return -1; } } break; + case SL_PP_NEWLINE: + case SL_PP_EOF: + found_end = 1; + break; + default: - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&state, &input)) { strcpy(context->error_msg, "out of memory"); free(state.out); return -1; } - i++; } } @@ -198,11 +197,9 @@ _parse_else(struct sl_pp_context *context) int sl_pp_process_if(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last) + struct sl_pp_token_buffer *buffer) { - return _parse_if(context, input, first, last); + return _parse_if(context, buffer); } int @@ -301,9 +298,7 @@ sl_pp_process_ifndef(struct sl_pp_context *context, int sl_pp_process_elif(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last) + struct sl_pp_token_buffer *buffer) { if (_parse_else(context)) { return -1; @@ -311,7 +306,7 @@ sl_pp_process_elif(struct sl_pp_context *context, if (context->if_stack[context->if_ptr] & 1) { context->if_ptr++; - if (_parse_if(context, input, first, last)) { + if (_parse_if(context, buffer)) { return -1; } } diff --git a/src/glsl/pp/sl_pp_line.c b/src/glsl/pp/sl_pp_line.c index ed5acc697c..6f7e9eb562 100644 --- a/src/glsl/pp/sl_pp_line.c +++ b/src/glsl/pp/sl_pp_line.c @@ -27,45 +27,51 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_public.h" #include "sl_pp_process.h" int sl_pp_process_line(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last, + struct sl_pp_token_buffer *buffer, struct sl_pp_process_state *pstate) { - unsigned int i; struct sl_pp_process_state state; + int found_end = 0; int line_number = -1; int file_number = -1; unsigned int line; unsigned int file; memset(&state, 0, sizeof(state)); - for (i = first; i < last;) { - switch (input[i].token) { + while (!found_end) { + struct sl_pp_token_info input; + + sl_pp_token_buffer_get(buffer, &input); + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_IDENTIFIER: - if (sl_pp_macro_expand(context, input, &i, NULL, &state, sl_pp_macro_expand_normal)) { + sl_pp_token_buffer_unget(buffer, &input); + if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_normal)) { free(state.out); return -1; } break; + case SL_PP_NEWLINE: + case SL_PP_EOF: + found_end = 1; + break; + default: - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&state, &input)) { strcpy(context->error_msg, "out of memory"); free(state.out); return -1; } - i++; } } diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c index 08b44c7cbe..9f520b8fc5 100644 --- a/src/glsl/pp/sl_pp_macro.c +++ b/src/glsl/pp/sl_pp_macro.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_public.h" #include "sl_pp_macro.h" #include "sl_pp_process.h" @@ -88,15 +89,6 @@ sl_pp_macro_reset(struct sl_pp_macro *macro) _macro_init(macro); } -static void -skip_whitespace(const struct sl_pp_token_info *input, - unsigned int *pi) -{ - while (input[*pi].token == SL_PP_WHITESPACE) { - (*pi)++; - } -} - static int _out_number(struct sl_pp_context *context, struct sl_pp_process_state *state, @@ -119,24 +111,28 @@ _out_number(struct sl_pp_context *context, int sl_pp_macro_expand(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int *pi, + struct sl_pp_token_buffer *tokens, struct sl_pp_macro *local, struct sl_pp_process_state *state, enum sl_pp_macro_expand_behaviour behaviour) { int mute = (behaviour == sl_pp_macro_expand_mute); + struct sl_pp_token_info input; int macro_name; struct sl_pp_macro *macro = NULL; struct sl_pp_macro *actual_arg = NULL; unsigned int j; - if (input[*pi].token != SL_PP_IDENTIFIER) { + if (sl_pp_token_buffer_get(tokens, &input)) { + return -1; + } + + if (input.token != SL_PP_IDENTIFIER) { strcpy(context->error_msg, "expected an identifier"); return -1; } - macro_name = input[*pi].data.identifier; + macro_name = input.data.identifier; /* First look for predefined macros. */ @@ -145,21 +141,18 @@ sl_pp_macro_expand(struct sl_pp_context *context, if (!mute && _out_number(context, state, context->line)) { return -1; } - (*pi)++; return 0; } if (macro_name == context->dict.___FILE__) { if (!mute && _out_number(context, state, context->file)) { return -1; } - (*pi)++; return 0; } if (macro_name == context->dict.___VERSION__) { if (!mute && _out_number(context, state, 110)) { return -1; } - (*pi)++; return 0; } @@ -175,7 +168,6 @@ sl_pp_macro_expand(struct sl_pp_context *context, return -1; } } - (*pi)++; return 0; } } @@ -187,16 +179,10 @@ sl_pp_macro_expand(struct sl_pp_context *context, if (!mute && _out_number(context, state, 1)) { return -1; } - (*pi)++; return 0; } } - /* TODO: For FEATURE_es2_glsl, expand to 1 the following symbols. - * GL_ES - * GL_FRAGMENT_PRECISION_HIGH - */ - if (local) { for (macro = local; macro; macro = macro->next) { if (macro->name == macro_name) { @@ -220,25 +206,26 @@ sl_pp_macro_expand(struct sl_pp_context *context, return -1; } } else if (!mute) { - if (sl_pp_process_out(state, &input[*pi])) { + if (sl_pp_process_out(state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } } - (*pi)++; return 0; } - (*pi)++; - if (macro->num_args >= 0) { - skip_whitespace(input, pi); - if (input[*pi].token != SL_PP_LPAREN) { + if (sl_pp_token_buffer_skip_white(tokens, &input)) { + return -1; + } + if (input.token != SL_PP_LPAREN) { strcpy(context->error_msg, "expected `('"); return -1; } - (*pi)++; - skip_whitespace(input, pi); + if (sl_pp_token_buffer_skip_white(tokens, &input)) { + return -1; + } + sl_pp_token_buffer_unget(tokens, &input); } if (macro->num_args > 0) { @@ -247,103 +234,85 @@ sl_pp_macro_expand(struct sl_pp_context *context, for (j = 0; j < (unsigned int)macro->num_args; j++) { struct sl_pp_process_state arg_state; - unsigned int i; int done = 0; unsigned int paren_nesting = 0; struct sl_pp_token_info eof; memset(&arg_state, 0, sizeof(arg_state)); - for (i = *pi; !done;) { - switch (input[i].token) { + while (!done) { + if (sl_pp_token_buffer_get(tokens, &input)) { + goto fail_arg; + } + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_COMMA: if (!paren_nesting) { if (j < (unsigned int)macro->num_args - 1) { done = 1; - i++; } else { strcpy(context->error_msg, "too many actual macro arguments"); - return -1; + goto fail_arg; } } else { - if (sl_pp_process_out(&arg_state, &input[i])) { + if (sl_pp_process_out(&arg_state, &input)) { strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + goto fail_arg; } - i++; } break; case SL_PP_LPAREN: paren_nesting++; - if (sl_pp_process_out(&arg_state, &input[i])) { - strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + if (sl_pp_process_out(&arg_state, &input)) { + goto oom_arg; } - i++; break; case SL_PP_RPAREN: if (!paren_nesting) { if (j == (unsigned int)macro->num_args - 1) { done = 1; - i++; } else { strcpy(context->error_msg, "too few actual macro arguments"); - return -1; + goto fail_arg; } } else { paren_nesting--; - if (sl_pp_process_out(&arg_state, &input[i])) { - strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + if (sl_pp_process_out(&arg_state, &input)) { + goto oom_arg; } - i++; } break; case SL_PP_IDENTIFIER: - if (sl_pp_macro_expand(context, input, &i, local, &arg_state, sl_pp_macro_expand_normal)) { - free(arg_state.out); - return -1; + sl_pp_token_buffer_unget(tokens, &input); + if (sl_pp_macro_expand(context, tokens, local, &arg_state, sl_pp_macro_expand_normal)) { + goto fail_arg; } break; case SL_PP_EOF: strcpy(context->error_msg, "too few actual macro arguments"); - return -1; + goto fail_arg; default: - if (sl_pp_process_out(&arg_state, &input[i])) { - strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + if (sl_pp_process_out(&arg_state, &input)) { + goto oom_arg; } - i++; } } - (*pi) = i; - eof.token = SL_PP_EOF; if (sl_pp_process_out(&arg_state, &eof)) { - strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + goto oom_arg; } *pmacro = sl_pp_macro_new(); if (!*pmacro) { - strcpy(context->error_msg, "out of memory"); - free(arg_state.out); - return -1; + goto oom_arg; } (**pmacro).name = formal_arg->name; @@ -351,47 +320,95 @@ sl_pp_macro_expand(struct sl_pp_context *context, formal_arg = formal_arg->next; pmacro = &(**pmacro).next; + + continue; + +oom_arg: + strcpy(context->error_msg, "out of memory"); +fail_arg: + free(arg_state.out); + goto fail; } } /* Right paren for non-empty argument list has already been eaten. */ if (macro->num_args == 0) { - skip_whitespace(input, pi); - if (input[*pi].token != SL_PP_RPAREN) { + if (sl_pp_token_buffer_skip_white(tokens, &input)) { + goto fail; + } + if (input.token != SL_PP_RPAREN) { strcpy(context->error_msg, "expected `)'"); - return -1; + goto fail; } - (*pi)++; } - for (j = 0;;) { - switch (macro->body[j].token) { - case SL_PP_NEWLINE: - if (sl_pp_process_out(state, ¯o->body[j])) { - strcpy(context->error_msg, "out of memory"); - return -1; - } - j++; - break; + /* XXX: This is all wrong, we should be ungetting all tokens + * back to the main token buffer. + */ + { + struct sl_pp_token_buffer buffer; - case SL_PP_IDENTIFIER: - if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state, behaviour)) { - return -1; - } - break; + /* Seek to the end. + */ + for (j = 0; macro->body[j].token != SL_PP_EOF; j++) { + } + j++; + + /* Create a context-less token buffer since we are not going to underrun + * its internal buffer. + */ + if (sl_pp_token_buffer_init(&buffer, NULL)) { + strcpy(context->error_msg, "out of memory"); + goto fail; + } - case SL_PP_EOF: - sl_pp_macro_free(actual_arg); - return 0; + /* Unget the tokens in reverse order so later they will be fetched correctly. + */ + for (; j > 0; j--) { + sl_pp_token_buffer_unget(&buffer, ¯o->body[j - 1]); + } - default: - if (!mute) { - if (sl_pp_process_out(state, ¯o->body[j])) { + /* Expand. + */ + for (;;) { + struct sl_pp_token_info input; + + sl_pp_token_buffer_get(&buffer, &input); + switch (input.token) { + case SL_PP_NEWLINE: + if (sl_pp_process_out(state, &input)) { strcpy(context->error_msg, "out of memory"); - return -1; + sl_pp_token_buffer_destroy(&buffer); + goto fail; + } + break; + + case SL_PP_IDENTIFIER: + sl_pp_token_buffer_unget(&buffer, &input); + if (sl_pp_macro_expand(context, &buffer, actual_arg, state, behaviour)) { + sl_pp_token_buffer_destroy(&buffer); + goto fail; + } + break; + + case SL_PP_EOF: + sl_pp_token_buffer_destroy(&buffer); + sl_pp_macro_free(actual_arg); + return 0; + + default: + if (!mute) { + if (sl_pp_process_out(state, &input)) { + strcpy(context->error_msg, "out of memory"); + sl_pp_token_buffer_destroy(&buffer); + goto fail; + } } } - j++; } } + +fail: + sl_pp_macro_free(actual_arg); + return -1; } diff --git a/src/glsl/pp/sl_pp_macro.h b/src/glsl/pp/sl_pp_macro.h index 3ad3438236..1d21068109 100644 --- a/src/glsl/pp/sl_pp_macro.h +++ b/src/glsl/pp/sl_pp_macro.h @@ -33,6 +33,7 @@ struct sl_pp_context; struct sl_pp_process_state; +struct sl_pp_token_buffer; struct sl_pp_macro_formal_arg { int name; @@ -64,8 +65,7 @@ enum sl_pp_macro_expand_behaviour { int sl_pp_macro_expand(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int *pi, + struct sl_pp_token_buffer *tokens, struct sl_pp_macro *local, struct sl_pp_process_state *state, enum sl_pp_macro_expand_behaviour behaviour); diff --git a/src/glsl/pp/sl_pp_pragma.c b/src/glsl/pp/sl_pp_pragma.c index 489eb17b8e..caf4c63f65 100644 --- a/src/glsl/pp/sl_pp_pragma.c +++ b/src/glsl/pp/sl_pp_pragma.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_process.h" diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c index e2adc2a021..f89986dd8e 100644 --- a/src/glsl/pp/sl_pp_process.c +++ b/src/glsl/pp/sl_pp_process.c @@ -27,19 +27,11 @@ #include <stdlib.h> #include <string.h> +#include "sl_pp_context.h" #include "sl_pp_process.h" #include "sl_pp_public.h" -static void -skip_whitespace(const struct sl_pp_token_info *input, - unsigned int *pi) -{ - while (input[*pi].token == SL_PP_WHITESPACE) { - (*pi)++; - } -} - int sl_pp_process_out(struct sl_pp_process_state *state, const struct sl_pp_token_info *token) @@ -67,133 +59,157 @@ sl_pp_process_out(struct sl_pp_process_state *state, } int -sl_pp_process(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - struct sl_pp_token_info **output) +sl_pp_process_get(struct sl_pp_context *context, + struct sl_pp_token_info *output) { - unsigned int i = 0; - int found_eof = 0; - struct sl_pp_process_state state; + if (!context->process_state.out) { + if (context->line > 1) { + struct sl_pp_token_info ti; - memset(&state, 0, sizeof(state)); + ti.token = SL_PP_LINE; + ti.data.line.lineno = context->line - 1; + ti.data.line.fileno = context->file; + if (sl_pp_process_out(&context->process_state, &ti)) { + strcpy(context->error_msg, "out of memory"); + return -1; + } - if (context->line > 1) { - struct sl_pp_token_info ti; + ti.token = SL_PP_NEWLINE; + if (sl_pp_process_out(&context->process_state, &ti)) { + strcpy(context->error_msg, "out of memory"); + return -1; + } + } + } - ti.token = SL_PP_LINE; - ti.data.line.lineno = context->line - 1; - ti.data.line.fileno = context->file; - if (sl_pp_process_out(&state, &ti)) { - strcpy(context->error_msg, "out of memory"); - return -1; + for (;;) { + struct sl_pp_token_info input; + int found_eof = 0; + + if (context->process_state.out_len) { + *output = context->process_state.out[0]; + + if (context->process_state.out_len > 1) { + unsigned int i; + + for (i = 1; i < context->process_state.out_len; i++) { + context->process_state.out[i - 1] = context->process_state.out[i]; + } + } + context->process_state.out_len--; + + return 0; } - ti.token = SL_PP_NEWLINE; - if (sl_pp_process_out(&state, &ti)) { - strcpy(context->error_msg, "out of memory"); + if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) { return -1; } - } - - while (!found_eof) { - skip_whitespace(input, &i); - if (input[i].token == SL_PP_HASH) { - i++; - skip_whitespace(input, &i); - switch (input[i].token) { + if (input.token == SL_PP_HASH) { + if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) { + return -1; + } + switch (input.token) { case SL_PP_IDENTIFIER: { int name; int found_eol = 0; - unsigned int first; - unsigned int last; struct sl_pp_token_info endof; + struct sl_pp_token_peek peek; + int result = 0; /* Directive name. */ - name = input[i].data.identifier; - i++; - skip_whitespace(input, &i); + name = input.data.identifier; - first = i; + if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) { + return -1; + } + sl_pp_token_buffer_unget(&context->tokens, &input); + + if (sl_pp_token_peek_init(&peek, &context->tokens)) { + return -1; + } while (!found_eol) { - switch (input[i].token) { + if (sl_pp_token_peek_get(&peek, &input)) { + sl_pp_token_peek_destroy(&peek); + return -1; + } + switch (input.token) { case SL_PP_NEWLINE: /* Preserve newline just for the sake of line numbering. */ - endof = input[i]; - i++; + endof = input; found_eol = 1; break; case SL_PP_EOF: - endof = input[i]; - i++; + endof = input; found_eof = 1; found_eol = 1; break; default: - i++; + break; } } - last = i - 1; - if (name == context->dict._if) { - if (sl_pp_process_if(context, input, first, last)) { - return -1; + struct sl_pp_token_buffer buffer; + + result = sl_pp_token_peek_to_buffer(&peek, &buffer); + if (result == 0) { + result = sl_pp_process_if(context, &buffer); + sl_pp_token_buffer_destroy(&buffer); } } else if (name == context->dict.ifdef) { - if (sl_pp_process_ifdef(context, input, first, last)) { - return -1; - } + result = sl_pp_process_ifdef(context, peek.tokens, 0, peek.size - 1); } else if (name == context->dict.ifndef) { - if (sl_pp_process_ifndef(context, input, first, last)) { - return -1; - } + result = sl_pp_process_ifndef(context, peek.tokens, 0, peek.size - 1); } else if (name == context->dict.elif) { - if (sl_pp_process_elif(context, input, first, last)) { - return -1; + struct sl_pp_token_buffer buffer; + + result = sl_pp_token_peek_to_buffer(&peek, &buffer); + if (result == 0) { + result = sl_pp_process_elif(context, &buffer); + sl_pp_token_buffer_destroy(&buffer); } } else if (name == context->dict._else) { - if (sl_pp_process_else(context, input, first, last)) { - return -1; - } + result = sl_pp_process_else(context, peek.tokens, 0, peek.size - 1); } else if (name == context->dict.endif) { - if (sl_pp_process_endif(context, input, first, last)) { - return -1; - } + result = sl_pp_process_endif(context, peek.tokens, 0, peek.size - 1); } else if (context->if_value) { if (name == context->dict.define) { - if (sl_pp_process_define(context, input, first, last)) { - return -1; - } + result = sl_pp_process_define(context, peek.tokens, 0, peek.size - 1); } else if (name == context->dict.error) { - sl_pp_process_error(context, input, first, last); - return -1; + sl_pp_process_error(context, peek.tokens, 0, peek.size - 1); + result = -1; } else if (name == context->dict.extension) { - if (sl_pp_process_extension(context, input, first, last, &state)) { - return -1; - } + result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &context->process_state); } else if (name == context->dict.line) { - if (sl_pp_process_line(context, input, first, last, &state)) { - return -1; + struct sl_pp_token_buffer buffer; + + result = sl_pp_token_peek_to_buffer(&peek, &buffer); + if (result == 0) { + result = sl_pp_process_line(context, &buffer, &context->process_state); + sl_pp_token_buffer_destroy(&buffer); } } else if (name == context->dict.pragma) { - if (sl_pp_process_pragma(context, input, first, last, &state)) { - return -1; - } + result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &context->process_state); } else if (name == context->dict.undef) { - if (sl_pp_process_undef(context, input, first, last)) { - return -1; - } + result = sl_pp_process_undef(context, peek.tokens, 0, peek.size - 1); } else { strcpy(context->error_msg, "unrecognised directive name"); - return -1; + result = -1; } } - if (sl_pp_process_out(&state, &endof)) { + sl_pp_token_peek_commit(&peek); + sl_pp_token_peek_destroy(&peek); + + if (result) { + return result; + } + + if (sl_pp_process_out(&context->process_state, &endof)) { strcpy(context->error_msg, "out of memory"); return -1; } @@ -203,21 +219,19 @@ sl_pp_process(struct sl_pp_context *context, case SL_PP_NEWLINE: /* Empty directive. */ - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } context->line++; - i++; break; case SL_PP_EOF: /* Empty directive. */ - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } - i++; found_eof = 1; break; @@ -228,36 +242,40 @@ sl_pp_process(struct sl_pp_context *context, } else { int found_eol = 0; + sl_pp_token_buffer_unget(&context->tokens, &input); + while (!found_eol) { - switch (input[i].token) { + if (sl_pp_token_buffer_get(&context->tokens, &input)) { + return -1; + } + + switch (input.token) { case SL_PP_WHITESPACE: /* Drop whitespace all together at this point. */ - i++; break; case SL_PP_NEWLINE: /* Preserve newline just for the sake of line numbering. */ - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } context->line++; - i++; found_eol = 1; break; case SL_PP_EOF: - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } - i++; found_eof = 1; found_eol = 1; break; case SL_PP_IDENTIFIER: - if (sl_pp_macro_expand(context, input, &i, NULL, &state, + sl_pp_token_buffer_unget(&context->tokens, &input); + if (sl_pp_macro_expand(context, &context->tokens, NULL, &context->process_state, context->if_value ? sl_pp_macro_expand_normal : sl_pp_macro_expand_mute)) { return -1; } @@ -265,22 +283,45 @@ sl_pp_process(struct sl_pp_context *context, default: if (context->if_value) { - if (sl_pp_process_out(&state, &input[i])) { + if (sl_pp_process_out(&context->process_state, &input)) { strcpy(context->error_msg, "out of memory"); return -1; } } - i++; } } } - } - if (context->if_ptr != SL_PP_MAX_IF_NESTING) { - strcpy(context->error_msg, "expected `#endif' directive"); - return -1; + if (found_eof) { + if (context->if_ptr != SL_PP_MAX_IF_NESTING) { + strcpy(context->error_msg, "expected `#endif' directive"); + return -1; + } + } } +} - *output = state.out; - return 0; +int +sl_pp_process(struct sl_pp_context *context, + struct sl_pp_token_info **output) +{ + struct sl_pp_process_state state; + + memset(&state, 0, sizeof(state)); + for (;;) { + struct sl_pp_token_info input; + + if (sl_pp_process_get(context, &input)) { + free(state.out); + return -1; + } + if (sl_pp_process_out(&state, &input)) { + free(state.out); + return -1; + } + if (input.token == SL_PP_EOF) { + *output = state.out; + return 0; + } + } } diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h index 24311bab60..fe6ff0d464 100644 --- a/src/glsl/pp/sl_pp_process.h +++ b/src/glsl/pp/sl_pp_process.h @@ -28,11 +28,12 @@ #ifndef SL_PP_PROCESS_H #define SL_PP_PROCESS_H -#include "sl_pp_context.h" #include "sl_pp_macro.h" #include "sl_pp_token.h" +struct sl_pp_context; + struct sl_pp_process_state { struct sl_pp_token_info *out; unsigned int out_len; @@ -53,9 +54,7 @@ sl_pp_process_undef(struct sl_pp_context *context, int sl_pp_process_if(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last); + struct sl_pp_token_buffer *input); int sl_pp_process_ifdef(struct sl_pp_context *context, @@ -71,9 +70,7 @@ sl_pp_process_ifndef(struct sl_pp_context *context, int sl_pp_process_elif(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last); + struct sl_pp_token_buffer *buffer); int sl_pp_process_else(struct sl_pp_context *context, @@ -109,9 +106,7 @@ sl_pp_process_extension(struct sl_pp_context *context, int sl_pp_process_line(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int first, - unsigned int last, + struct sl_pp_token_buffer *buffer, struct sl_pp_process_state *state); int diff --git a/src/glsl/pp/sl_pp_public.h b/src/glsl/pp/sl_pp_public.h index 076903649c..12528d6f8d 100644 --- a/src/glsl/pp/sl_pp_public.h +++ b/src/glsl/pp/sl_pp_public.h @@ -37,7 +37,8 @@ struct sl_pp_context; struct sl_pp_context * -sl_pp_context_create(void); +sl_pp_context_create(const char *input, + const struct sl_pp_purify_options *options); void sl_pp_context_destroy(struct sl_pp_context *context); @@ -45,6 +46,11 @@ sl_pp_context_destroy(struct sl_pp_context *context); const char * sl_pp_context_error_message(const struct sl_pp_context *context); +void +sl_pp_context_error_position(const struct sl_pp_context *context, + unsigned int *file, + unsigned int *line); + int sl_pp_context_add_extension(struct sl_pp_context *context, const char *name, @@ -65,13 +71,14 @@ sl_pp_context_cstr(const struct sl_pp_context *context, int sl_pp_version(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int *version, - unsigned int *tokens_eaten); + unsigned int *version); + +int +sl_pp_process_get(struct sl_pp_context *context, + struct sl_pp_token_info *output); int sl_pp_process(struct sl_pp_context *context, - const struct sl_pp_token_info *input, struct sl_pp_token_info **output); #endif /* SL_PP_PUBLIC_H */ diff --git a/src/glsl/pp/sl_pp_token.c b/src/glsl/pp/sl_pp_token.c index e9a60b6c50..a708978700 100644 --- a/src/glsl/pp/sl_pp_token.c +++ b/src/glsl/pp/sl_pp_token.c @@ -39,13 +39,12 @@ static int _pure_getc(struct sl_pp_context *context) { char c; - unsigned int current_line; if (context->getc_buf_size) { return context->getc_buf[--context->getc_buf_size]; } - if (sl_pp_purify_getc(&context->pure, &c, ¤t_line, context->error_msg, sizeof(context->error_msg)) == 0) { + if (sl_pp_purify_getc(&context->pure, &c, &context->error_line, context->error_msg, sizeof(context->error_msg)) == 0) { return PURE_ERROR; } return c; @@ -508,7 +507,7 @@ _tokenise_number(struct sl_pp_context *context, } -static int +int sl_pp_token_get(struct sl_pp_context *context, struct sl_pp_token_info *out) { @@ -810,20 +809,16 @@ sl_pp_token_get(struct sl_pp_context *context, int sl_pp_tokenise(struct sl_pp_context *context, - const char *input, - const struct sl_pp_purify_options *options, struct sl_pp_token_info **output) { struct sl_pp_token_info *out = NULL; unsigned int out_len = 0; unsigned int out_max = 0; - sl_pp_purify_state_init(&context->pure, input, options); - for (;;) { struct sl_pp_token_info info; - if (sl_pp_token_get(context, &info)) { + if (sl_pp_token_buffer_get(&context->tokens, &info)) { free(out); return -1; } diff --git a/src/glsl/pp/sl_pp_token.h b/src/glsl/pp/sl_pp_token.h index ba9834a9f2..a12b193401 100644 --- a/src/glsl/pp/sl_pp_token.h +++ b/src/glsl/pp/sl_pp_token.h @@ -123,9 +123,11 @@ struct sl_pp_token_info { struct sl_pp_purify_options; int +sl_pp_token_get(struct sl_pp_context *context, + struct sl_pp_token_info *out); + +int sl_pp_tokenise(struct sl_pp_context *context, - const char *input, - const struct sl_pp_purify_options *options, struct sl_pp_token_info **output); #endif /* SL_PP_TOKEN_H */ diff --git a/src/glsl/pp/sl_pp_token_util.c b/src/glsl/pp/sl_pp_token_util.c new file mode 100644 index 0000000000..c85263d9a1 --- /dev/null +++ b/src/glsl/pp/sl_pp_token_util.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdlib.h> +#include "sl_pp_token_util.h" + + +int +sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer, + struct sl_pp_context *context) +{ + buffer->context = context; + buffer->size = 0; + buffer->capacity = 64; + buffer->tokens = malloc(buffer->capacity * sizeof(struct sl_pp_token_info)); + if (!buffer->tokens) { + return -1; + } + return 0; +} + +void +sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer) +{ + free(buffer->tokens); +} + +int +sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer, + struct sl_pp_token_info *out) +{ + /* Pop from stack first if not empty. */ + if (buffer->size) { + *out = buffer->tokens[--buffer->size]; + return 0; + } + + assert(buffer->context); + return sl_pp_token_get(buffer->context, out); +} + +void +sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer, + const struct sl_pp_token_info *in) +{ + /* Resize if needed. */ + if (buffer->size == buffer->capacity) { + buffer->capacity += 64; + buffer->tokens = realloc(buffer->tokens, + buffer->capacity * sizeof(struct sl_pp_token_info)); + assert(buffer->tokens); + } + + /* Push token on stack. */ + buffer->tokens[buffer->size++] = *in; +} + +int +sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer, + struct sl_pp_token_info *out) +{ + if (sl_pp_token_buffer_get(buffer, out)) { + return -1; + } + + while (out->token == SL_PP_WHITESPACE) { + if (sl_pp_token_buffer_get(buffer, out)) { + return -1; + } + } + + return 0; +} + + + +int +sl_pp_token_peek_init(struct sl_pp_token_peek *peek, + struct sl_pp_token_buffer *buffer) +{ + peek->buffer = buffer; + peek->size = 0; + peek->capacity = 64; + peek->tokens = malloc(peek->capacity * sizeof(struct sl_pp_token_info)); + if (!peek->tokens) { + return -1; + } + return 0; +} + +void +sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek) +{ + /* Abort. */ + while (peek->size) { + sl_pp_token_buffer_unget(peek->buffer, &peek->tokens[--peek->size]); + } + free(peek->tokens); +} + +int +sl_pp_token_peek_get(struct sl_pp_token_peek *peek, + struct sl_pp_token_info *out) +{ + /* Get token from buffer. */ + if (sl_pp_token_buffer_get(peek->buffer, out)) { + return -1; + } + + /* Save it. */ + if (peek->size == peek->capacity) { + peek->capacity += 64; + peek->tokens = realloc(peek->tokens, + peek->capacity * sizeof(struct sl_pp_token_info)); + assert(peek->tokens); + } + peek->tokens[peek->size++] = *out; + return 0; +} + +void +sl_pp_token_peek_commit(struct sl_pp_token_peek *peek) +{ + peek->size = 0; +} + +int +sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek, + struct sl_pp_token_buffer *buffer) +{ + unsigned int i; + + if (sl_pp_token_buffer_init(buffer, NULL)) { + return -1; + } + for (i = peek->size; i > 0; i--) { + sl_pp_token_buffer_unget(buffer, &peek->tokens[i - 1]); + } + return 0; +} + +int +sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek, + struct sl_pp_token_info *out) +{ + if (sl_pp_token_peek_get(peek, out)) { + return -1; + } + + while (out->token == SL_PP_WHITESPACE) { + if (sl_pp_token_peek_get(peek, out)) { + return -1; + } + } + + return 0; +} diff --git a/src/glsl/pp/sl_pp_token_util.h b/src/glsl/pp/sl_pp_token_util.h new file mode 100644 index 0000000000..2a668ad0a8 --- /dev/null +++ b/src/glsl/pp/sl_pp_token_util.h @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_TOKEN_UTIL_H +#define SL_PP_TOKEN_UTIL_H + +#include <assert.h> +#include <stdlib.h> +#include "sl_pp_token.h" + + +struct sl_pp_context; + +/* + * A token buffer allows one to get and unget a token + * from a preprocessor context. + */ +struct sl_pp_token_buffer { + struct sl_pp_context *context; + unsigned int size; + unsigned int capacity; + struct sl_pp_token_info *tokens; +}; + +int +sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer, + struct sl_pp_context *context); + +void +sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer); + +int +sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer, + struct sl_pp_token_info *out); + +void +sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer, + const struct sl_pp_token_info *in); + +int +sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer, + struct sl_pp_token_info *out); + + +/* + * A token peek allows one to get a number of tokens from a buffer + * and then either commit the operation or abort it, + * effectively ungetting the peeked tokens. + */ +struct sl_pp_token_peek { + struct sl_pp_token_buffer *buffer; + unsigned int size; + unsigned int capacity; + struct sl_pp_token_info *tokens; +}; + +int +sl_pp_token_peek_init(struct sl_pp_token_peek *peek, + struct sl_pp_token_buffer *buffer); + +void +sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek); + +int +sl_pp_token_peek_get(struct sl_pp_token_peek *peek, + struct sl_pp_token_info *out); + +void +sl_pp_token_peek_commit(struct sl_pp_token_peek *peek); + +int +sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek, + struct sl_pp_token_buffer *buffer); + +int +sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek, + struct sl_pp_token_info *out); + +#endif /* SL_PP_TOKEN_UTIL_H */ diff --git a/src/glsl/pp/sl_pp_version.c b/src/glsl/pp/sl_pp_version.c index db06523749..3c995b7750 100644 --- a/src/glsl/pp/sl_pp_version.c +++ b/src/glsl/pp/sl_pp_version.c @@ -33,21 +33,23 @@ int sl_pp_version(struct sl_pp_context *context, - const struct sl_pp_token_info *input, - unsigned int *version, - unsigned int *tokens_eaten) + unsigned int *version) { - unsigned int i = 0; + struct sl_pp_token_peek peek; unsigned int line = context->line; /* Default values if `#version' is not present. */ *version = 110; - *tokens_eaten = 0; + + if (sl_pp_token_peek_init(&peek, &context->tokens)) { + return -1; + } /* There can be multiple `#version' directives present. * Accept the value of the last one. */ for (;;) { + struct sl_pp_token_info input; int found_hash = 0; int found_version = 0; int found_number = 0; @@ -55,82 +57,101 @@ sl_pp_version(struct sl_pp_context *context, /* Skip whitespace and newlines and seek for hash. */ while (!found_hash) { - switch (input[i].token) { + if (sl_pp_token_peek_get(&peek, &input)) { + sl_pp_token_peek_destroy(&peek); + return -1; + } + + switch (input.token) { case SL_PP_NEWLINE: line++; - /* pass thru */ + break; + case SL_PP_WHITESPACE: - i++; break; case SL_PP_HASH: - i++; found_hash = 1; break; default: + sl_pp_token_peek_destroy(&peek); return 0; } } /* Skip whitespace and seek for `version'. */ while (!found_version) { - switch (input[i].token) { + if (sl_pp_token_peek_get(&peek, &input)) { + sl_pp_token_peek_destroy(&peek); + return -1; + } + + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_IDENTIFIER: - if (input[i].data.identifier != context->dict.version) { + if (input.data.identifier != context->dict.version) { + sl_pp_token_peek_destroy(&peek); return 0; } - i++; found_version = 1; break; default: + sl_pp_token_peek_destroy(&peek); return 0; } } + sl_pp_token_peek_commit(&peek); + /* Skip whitespace and seek for version number. */ while (!found_number) { - switch (input[i].token) { + if (sl_pp_token_buffer_get(&context->tokens, &input)) { + sl_pp_token_peek_destroy(&peek); + return -1; + } + + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_UINT: - *version = atoi(sl_pp_context_cstr(context, input[i].data._uint)); - i++; + *version = atoi(sl_pp_context_cstr(context, input.data._uint)); found_number = 1; break; default: strcpy(context->error_msg, "expected version number after `#version'"); + sl_pp_token_peek_destroy(&peek); return -1; } } /* Skip whitespace and seek for either newline or eof. */ while (!found_end) { - switch (input[i].token) { + if (sl_pp_token_buffer_get(&context->tokens, &input)) { + sl_pp_token_peek_destroy(&peek); + return -1; + } + + switch (input.token) { case SL_PP_WHITESPACE: - i++; break; case SL_PP_NEWLINE: line++; /* pass thru */ case SL_PP_EOF: - i++; - *tokens_eaten = i; context->line = line; found_end = 1; break; default: strcpy(context->error_msg, "expected end of line after version number"); + sl_pp_token_peek_destroy(&peek); return -1; } } |