From fd991d845a5f639b9b675a4840ad234c151d56b4 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Fri, 19 Jun 2009 12:02:28 +0200 Subject: [PATCH] glsl: Parse define directive in preprocessor. --- src/glsl/pp/SConscript | 2 + src/glsl/pp/sl_pp_context.c | 1 + src/glsl/pp/sl_pp_context.h | 4 + src/glsl/pp/sl_pp_define.c | 156 ++++++++++++++++++++++++++++++++++++ src/glsl/pp/sl_pp_macro.c | 51 ++++++++++++ src/glsl/pp/sl_pp_macro.h | 50 ++++++++++++ src/glsl/pp/sl_pp_process.c | 29 +++++-- src/glsl/pp/sl_pp_process.h | 8 ++ 8 files changed, 296 insertions(+), 5 deletions(-) create mode 100644 src/glsl/pp/sl_pp_define.c create mode 100644 src/glsl/pp/sl_pp_macro.c create mode 100644 src/glsl/pp/sl_pp_macro.h diff --git a/src/glsl/pp/SConscript b/src/glsl/pp/SConscript index 3d4a1cb967c..1fde3dfccf3 100644 --- a/src/glsl/pp/SConscript +++ b/src/glsl/pp/SConscript @@ -9,6 +9,8 @@ glsl = env.StaticLibrary( target = 'glsl', source = [ 'sl_pp_context.c', + 'sl_pp_define.c', + 'sl_pp_macro.c', 'sl_pp_process.c', 'sl_pp_purify.c', 'sl_pp_token.c', diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c index 71712de1fe2..8722376ae52 100644 --- a/src/glsl/pp/sl_pp_context.c +++ b/src/glsl/pp/sl_pp_context.c @@ -39,6 +39,7 @@ void sl_pp_context_destroy(struct sl_pp_context *context) { free(context->cstr_pool); + sl_pp_macro_free(context->macro); } int diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h index e4686b89e33..cb81f73ab9e 100644 --- a/src/glsl/pp/sl_pp_context.h +++ b/src/glsl/pp/sl_pp_context.h @@ -28,11 +28,15 @@ #ifndef SL_PP_CONTEXT_H #define SL_PP_CONTEXT_H +#include "sl_pp_macro.h" + struct sl_pp_context { char *cstr_pool; unsigned int cstr_pool_max; unsigned int cstr_pool_len; + + struct sl_pp_macro *macro; }; void diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c new file mode 100644 index 00000000000..5ce0f0551b8 --- /dev/null +++ b/src/glsl/pp/sl_pp_define.c @@ -0,0 +1,156 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "sl_pp_process.h" + + +static void +skip_whitespace(const struct sl_pp_token_info *input, + unsigned int *first, + unsigned int last) +{ + while (*first < last && input[*first].token == SL_PP_WHITESPACE) { + (*first)++; + } +} + + +static int +_parse_formal_args(const struct sl_pp_token_info *input, + unsigned int *first, + unsigned int last, + struct sl_pp_macro *macro) +{ + struct sl_pp_macro_formal_arg **arg; + + skip_whitespace(input, first, last); + if (*first < last) { + if (input[*first].token == SL_PP_RPAREN) { + (*first)++; + return 0; + } + } else { + /* Expected either an identifier or `)'. */ + return -1; + } + + arg = ¯o->arg; + + for (;;) { + if (*first < last && input[*first].token != SL_PP_IDENTIFIER) { + /* Expected an identifier. */ + return -1; + } + + *arg = malloc(sizeof(struct sl_pp_macro_formal_arg)); + if (!*arg) { + return -1; + } + + (**arg).name = input[*first].data.identifier; + (*first)++; + + (**arg).next = NULL; + arg = &(**arg).next; + + skip_whitespace(input, first, last); + if (*first < last) { + if (input[*first].token == SL_PP_COMMA) { + (*first)++; + } else if (input[*first].token == SL_PP_RPAREN) { + (*first)++; + return 0; + } else { + /* Expected either `,' or `)'. */ + return -1; + } + } else { + /* Expected either `,' or `)'. */ + return -1; + } + } +} + + +int +sl_pp_process_define(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_macro *macro) +{ + macro->name = -1; + macro->arg = NULL; + macro->body = NULL; + macro->next = NULL; + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + macro->name = input[first].data.identifier; + first++; + } + + if (macro->name == -1) { + return -1; + } + + /* + * If there is no whitespace between macro name and left paren, a macro + * formal argument list follows. This is the only place where the presence + * of a whitespace matters and it's the only reason why we are dealing + * with whitespace at this level. + */ + if (first < last && input[first].token == SL_PP_LPAREN) { + first++; + if (_parse_formal_args(input, &first, last, macro)) { + return -1; + } + } + + /* Trim whitespace from the left side. */ + skip_whitespace(input, &first, last); + + /* Trom whitespace from the right side. */ + while (first < last && input[last - 1].token == SL_PP_WHITESPACE) { + last--; + } + + /* All that is left between first and last is the macro definition. */ + macro->body_len = last - first; + if (macro->body_len) { + macro->body = malloc(sizeof(struct sl_pp_token_info) * macro->body_len); + if (!macro->body) { + return -1; + } + + memcpy(macro->body, + &input[first], + sizeof(struct sl_pp_token_info) * macro->body_len); + } + + return 0; +} diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c new file mode 100644 index 00000000000..eed09783040 --- /dev/null +++ b/src/glsl/pp/sl_pp_macro.c @@ -0,0 +1,51 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "sl_pp_macro.h" + + +void +sl_pp_macro_free(struct sl_pp_macro *macro) +{ + while (macro) { + struct sl_pp_macro *next_macro = macro->next; + struct sl_pp_macro_formal_arg *arg = macro->arg; + + while (arg) { + struct sl_pp_macro_formal_arg *next_arg = arg->next; + + free(arg); + arg = next_arg; + } + + free(macro->body); + + free(macro); + macro = next_macro; + } +} diff --git a/src/glsl/pp/sl_pp_macro.h b/src/glsl/pp/sl_pp_macro.h new file mode 100644 index 00000000000..4ebbff55906 --- /dev/null +++ b/src/glsl/pp/sl_pp_macro.h @@ -0,0 +1,50 @@ +/************************************************************************** + * + * 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_MACRO_H +#define SL_PP_MACRO_H + +#include "sl_pp_token.h" + + +struct sl_pp_macro_formal_arg { + int name; + struct sl_pp_macro_formal_arg *next; +}; + +struct sl_pp_macro { + int name; + struct sl_pp_macro_formal_arg *arg; + struct sl_pp_token_info *body; + unsigned int body_len; + struct sl_pp_macro *next; +}; + +void +sl_pp_macro_free(struct sl_pp_macro *macro); + +#endif /* SL_PP_MACRO_H */ diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c index 1005c501050..2a375df71a4 100644 --- a/src/glsl/pp/sl_pp_process.c +++ b/src/glsl/pp/sl_pp_process.c @@ -80,8 +80,10 @@ sl_pp_process(struct sl_pp_context *context, { unsigned int i = 0; int found_eof = 0; + struct sl_pp_macro **macro; struct process_state state; + macro = &context->macro; memset(&state, 0, sizeof(state)); while (!found_eof) { @@ -94,18 +96,18 @@ sl_pp_process(struct sl_pp_context *context, { const char *name; int found_eol = 0; + unsigned int first; + unsigned int last; + /* Directive name. */ name = sl_pp_context_cstr(context, input[i].data.identifier); i++; skip_whitespace(input, &i); + first = i; + while (!found_eol) { switch (input[i].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 (out_token(&state, &input[i])) { @@ -128,6 +130,23 @@ sl_pp_process(struct sl_pp_context *context, i++; } } + + last = i - 1; + + if (!strcmp(name, "define")) { + *macro = malloc(sizeof(struct sl_pp_macro)); + if (!*macro) { + return -1; + } + + if (sl_pp_process_define(context, input, first, last, *macro)) { + return -1; + } + + macro = &(**macro).next; + } else { + /* XXX: Ignore. */ + } } break; diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h index d6401de960e..f7df9a2850a 100644 --- a/src/glsl/pp/sl_pp_process.h +++ b/src/glsl/pp/sl_pp_process.h @@ -29,6 +29,7 @@ #define SL_PP_PROCESS_H #include "sl_pp_context.h" +#include "sl_pp_macro.h" #include "sl_pp_token.h" @@ -37,4 +38,11 @@ sl_pp_process(struct sl_pp_context *context, const struct sl_pp_token_info *input, struct sl_pp_token_info **output); +int +sl_pp_process_define(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_macro *macro); + #endif /* SL_PP_PROCESS_H */ -- 2.30.2