diff options
Diffstat (limited to 'src/glsl/pp')
| -rw-r--r-- | src/glsl/pp/SConscript | 1 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_context.c | 2 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_context.h | 6 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_if.c | 276 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_macro.c | 24 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_macro.h | 3 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_process.c | 59 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_process.h | 42 | 
8 files changed, 388 insertions, 25 deletions
| diff --git a/src/glsl/pp/SConscript b/src/glsl/pp/SConscript index 623d2362ce..c7718d1d8f 100644 --- a/src/glsl/pp/SConscript +++ b/src/glsl/pp/SConscript @@ -11,6 +11,7 @@ glsl = env.StaticLibrary(          'sl_pp_context.c',          'sl_pp_define.c',          'sl_pp_expression.c', +        'sl_pp_if.c',          'sl_pp_macro.c',          'sl_pp_process.c',          'sl_pp_purify.c', diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c index 6d3076b869..1afe9a5d5e 100644 --- a/src/glsl/pp/sl_pp_context.c +++ b/src/glsl/pp/sl_pp_context.c @@ -33,6 +33,8 @@ void  sl_pp_context_init(struct sl_pp_context *context)  {     memset(context, 0, sizeof(struct sl_pp_context)); +   context->if_ptr = SL_PP_MAX_IF_NESTING; +   context->if_value = 1;  }  void diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h index 56f7077750..e8200d55d7 100644 --- a/src/glsl/pp/sl_pp_context.h +++ b/src/glsl/pp/sl_pp_context.h @@ -31,12 +31,18 @@  #include "sl_pp_macro.h" +#define SL_PP_MAX_IF_NESTING  64 +  struct sl_pp_context {     char *cstr_pool;     unsigned int cstr_pool_max;     unsigned int cstr_pool_len;     struct sl_pp_macro *macro; + +   unsigned int if_stack[SL_PP_MAX_IF_NESTING]; +   unsigned int if_ptr; +   int if_value;  };  void diff --git a/src/glsl/pp/sl_pp_if.c b/src/glsl/pp/sl_pp_if.c new file mode 100644 index 0000000000..e331acc4cd --- /dev/null +++ b/src/glsl/pp/sl_pp_if.c @@ -0,0 +1,276 @@ +/************************************************************************** + *  + * 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 <stdlib.h> +#include "sl_pp_expression.h" +#include "sl_pp_process.h" + + +static int +_evaluate_if_stack(struct sl_pp_context *context) +{ +   unsigned int i; + +   for (i = context->if_ptr; i < SL_PP_MAX_IF_NESTING; i++) { +      if (!(context->if_stack[i] & 1)) { +         return 0; +      } +   } +   return 1; +} + +static int +_parse_if(struct sl_pp_context *context, +          const struct sl_pp_token_info *input, +          unsigned int first, +          unsigned int last) +{ +   unsigned int i; +   struct sl_pp_process_state state; +   struct sl_pp_token_info eof; +   int result; + +   if (!context->if_ptr) { +      /* #if nesting too deep. */ +      return -1; +   } + +   memset(&state, 0, sizeof(state)); +   for (i = first; i < last;) { +      switch (input[i].token) { +      case SL_PP_WHITESPACE: +         i++; +         break; + +      case SL_PP_IDENTIFIER: +         if (sl_pp_macro_expand(context, input, &i, NULL, &state, 0)) { +            free(state.out); +            return -1; +         } +         break; + +      default: +         if (sl_pp_process_out(&state, &input[i])) { +            free(state.out); +            return -1; +         } +         i++; +      } +   } + +   eof.token = SL_PP_EOF; +   if (sl_pp_process_out(&state, &eof)) { +      free(state.out); +      return -1; +   } + +   if (sl_pp_execute_expression(context, state.out, &result)) { +      free(state.out); +      return -1; +   } + +   free(state.out); + +   context->if_ptr--; +   context->if_stack[context->if_ptr] = result ? 1 : 0; +   context->if_value = _evaluate_if_stack(context); + +   return 0; +} + +static int +_parse_else(struct sl_pp_context *context) +{ +   if (context->if_ptr == SL_PP_MAX_IF_NESTING) { +      /* No matching #if. */ +      return -1; +   } + +   /* Bit b1 indicates we already went through #else. */ +   if (context->if_stack[context->if_ptr] & 2) { +      /* No matching #if. */ +      return -1; +   } + +   /* Invert current condition value and mark that we are in the #else block. */ +   context->if_stack[context->if_ptr] = (1 - (context->if_stack[context->if_ptr] & 1)) | 2; +   context->if_value = _evaluate_if_stack(context); + +   return 0; +} + +int +sl_pp_process_if(struct sl_pp_context *context, +                 const struct sl_pp_token_info *input, +                 unsigned int first, +                 unsigned int last) +{ +   return _parse_if(context, input, first, last); +} + +int +sl_pp_process_ifdef(struct sl_pp_context *context, +                    const struct sl_pp_token_info *input, +                    unsigned int first, +                    unsigned int last) +{ +   unsigned int i; + +   if (!context->if_ptr) { +      /* #if nesting too deep. */ +      return -1; +   } + +   for (i = first; i < last; i++) { +      switch (input[i].token) { +      case SL_PP_IDENTIFIER: +         { +            struct sl_pp_macro *macro; +            int macro_name = input[i].data.identifier; +            int defined = 0; + +            for (macro = context->macro; macro; macro = macro->next) { +               if (macro->name == macro_name) { +                  defined = 1; +                  break; +               } +            } + +            context->if_ptr--; +            context->if_stack[context->if_ptr] = defined ? 1 : 0; +            context->if_value = _evaluate_if_stack(context); +         } +         return 0; + +      case SL_PP_WHITESPACE: +         break; + +      default: +         /* Expected an identifier. */ +         return -1; +      } +   } + +   /* Expected an identifier. */ +   return -1; +} + +int +sl_pp_process_ifndef(struct sl_pp_context *context, +                     const struct sl_pp_token_info *input, +                     unsigned int first, +                     unsigned int last) +{ +   unsigned int i; + +   if (!context->if_ptr) { +      /* #if nesting too deep. */ +      return -1; +   } + +   for (i = first; i < last; i++) { +      switch (input[i].token) { +      case SL_PP_IDENTIFIER: +         { +            struct sl_pp_macro *macro; +            int macro_name = input[i].data.identifier; +            int defined = 0; + +            for (macro = context->macro; macro; macro = macro->next) { +               if (macro->name == macro_name) { +                  defined = 1; +                  break; +               } +            } + +            context->if_ptr--; +            context->if_stack[context->if_ptr] = defined ? 0 : 1; +            context->if_value = _evaluate_if_stack(context); +         } +         return 0; + +      case SL_PP_WHITESPACE: +         break; + +      default: +         /* Expected an identifier. */ +         return -1; +      } +   } + +   /* Expected an identifier. */ +   return -1; +} + +int +sl_pp_process_elif(struct sl_pp_context *context, +                   const struct sl_pp_token_info *input, +                   unsigned int first, +                   unsigned int last) +{ +   if (_parse_else(context)) { +      return -1; +   } + +   if (context->if_stack[context->if_ptr] & 1) { +      context->if_ptr++; +      if (_parse_if(context, input, first, last)) { +         return -1; +      } +   } + +   /* We are still in the #if block. */ +   context->if_stack[context->if_ptr] = context->if_stack[context->if_ptr] & ~2; + +   return 0; +} + +int +sl_pp_process_else(struct sl_pp_context *context, +                   const struct sl_pp_token_info *input, +                   unsigned int first, +                   unsigned int last) +{ +   return _parse_else(context); +} + +int +sl_pp_process_endif(struct sl_pp_context *context, +                    const struct sl_pp_token_info *input, +                    unsigned int first, +                    unsigned int last) +{ +   if (context->if_ptr == SL_PP_MAX_IF_NESTING) { +      /* No matching #if. */ +      return -1; +   } + +   context->if_ptr++; +   context->if_value = _evaluate_if_stack(context); + +   return 0; +} diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c index 0138270c67..a8412f0651 100644 --- a/src/glsl/pp/sl_pp_macro.c +++ b/src/glsl/pp/sl_pp_macro.c @@ -78,7 +78,8 @@ sl_pp_macro_expand(struct sl_pp_context *context,                     const struct sl_pp_token_info *input,                     unsigned int *pi,                     struct sl_pp_macro *local, -                   struct sl_pp_process_state *state) +                   struct sl_pp_process_state *state, +                   int mute)  {     int macro_name;     struct sl_pp_macro *macro = NULL; @@ -108,8 +109,10 @@ sl_pp_macro_expand(struct sl_pp_context *context,     }     if (!macro) { -      if (sl_pp_process_out(state, &input[*pi])) { -         return -1; +      if (!mute) { +         if (sl_pp_process_out(state, &input[*pi])) { +            return -1; +         }        }        (*pi)++;        return 0; @@ -244,8 +247,15 @@ sl_pp_macro_expand(struct sl_pp_context *context,     for (j = 0;;) {        switch (macro->body[j].token) { +      case SL_PP_NEWLINE: +         if (sl_pp_process_out(state, ¯o->body[j])) { +            return -1; +         } +         j++; +         break; +        case SL_PP_IDENTIFIER: -         if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state)) { +         if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state, mute)) {              return -1;           }           break; @@ -255,8 +265,10 @@ sl_pp_macro_expand(struct sl_pp_context *context,           return 0;        default: -         if (sl_pp_process_out(state, ¯o->body[j])) { -            return -1; +         if (!mute) { +            if (sl_pp_process_out(state, ¯o->body[j])) { +               return -1; +            }           }           j++;        } diff --git a/src/glsl/pp/sl_pp_macro.h b/src/glsl/pp/sl_pp_macro.h index 63edd21aa2..476991d581 100644 --- a/src/glsl/pp/sl_pp_macro.h +++ b/src/glsl/pp/sl_pp_macro.h @@ -55,6 +55,7 @@ sl_pp_macro_expand(struct sl_pp_context *context,                     const struct sl_pp_token_info *input,                     unsigned int *pi,                     struct sl_pp_macro *local, -                   struct sl_pp_process_state *state); +                   struct sl_pp_process_state *state, +                   int mute);  #endif /* SL_PP_MACRO_H */ diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c index baffaf2cd9..441de9439c 100644 --- a/src/glsl/pp/sl_pp_process.c +++ b/src/glsl/pp/sl_pp_process.c @@ -38,14 +38,6 @@ skip_whitespace(const struct sl_pp_token_info *input,     }  } - -struct sl_pp_process_state { -   struct sl_pp_token_info *out; -   unsigned int out_len; -   unsigned int out_max; -}; - -  int  sl_pp_process_out(struct sl_pp_process_state *state,                    const struct sl_pp_token_info *token) @@ -133,16 +125,42 @@ sl_pp_process(struct sl_pp_context *context,                 last = i - 1;                 if (!strcmp(name, "define")) { -                  *macro = sl_pp_macro_new(); -                  if (!*macro) { +                  if (context->if_value) { +                     *macro = sl_pp_macro_new(); +                     if (!*macro) { +                        return -1; +                     } + +                     if (sl_pp_process_define(context, input, first, last, *macro)) { +                        return -1; +                     } + +                     macro = &(**macro).next; +                  } +               } else if (!strcmp(name, "if")) { +                  if (sl_pp_process_if(context, input, first, last)) {                       return -1;                    } - -                  if (sl_pp_process_define(context, input, first, last, *macro)) { +               } else if (!strcmp(name, "ifdef")) { +                  if (sl_pp_process_ifdef(context, input, first, last)) { +                     return -1; +                  } +               } else if (!strcmp(name, "ifndef")) { +                  if (sl_pp_process_ifndef(context, input, first, last)) { +                     return -1; +                  } +               } else if (!strcmp(name, "elif")) { +                  if (sl_pp_process_elif(context, input, first, last)) { +                     return -1; +                  } +               } else if (!strcmp(name, "else")) { +                  if (sl_pp_process_else(context, input, first, last)) { +                     return -1; +                  } +               } else if (!strcmp(name, "endif")) { +                  if (sl_pp_process_endif(context, input, first, last)) {                       return -1;                    } - -                  macro = &(**macro).next;                 } else {                    /* XXX: Ignore. */                 } @@ -198,14 +216,16 @@ sl_pp_process(struct sl_pp_context *context,                 break;              case SL_PP_IDENTIFIER: -               if (sl_pp_macro_expand(context, input, &i, NULL, &state)) { +               if (sl_pp_macro_expand(context, input, &i, NULL, &state, !context->if_value)) {                    return -1;                 }                 break;              default: -               if (sl_pp_process_out(&state, &input[i])) { -                  return -1; +               if (context->if_value) { +                  if (sl_pp_process_out(&state, &input[i])) { +                     return -1; +                  }                 }                 i++;              } @@ -213,6 +233,11 @@ sl_pp_process(struct sl_pp_context *context,        }     } +   if (context->if_ptr != SL_PP_MAX_IF_NESTING) { +      /* #endif expected. */ +      return -1; +   } +     *output = state.out;     return 0;  } diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h index 37cdc4c9a7..cc934bd89c 100644 --- a/src/glsl/pp/sl_pp_process.h +++ b/src/glsl/pp/sl_pp_process.h @@ -33,7 +33,11 @@  #include "sl_pp_token.h" -struct sl_pp_process_state; +struct sl_pp_process_state { +   struct sl_pp_token_info *out; +   unsigned int out_len; +   unsigned int out_max; +};  int  sl_pp_process(struct sl_pp_context *context, @@ -48,6 +52,42 @@ sl_pp_process_define(struct sl_pp_context *context,                       struct sl_pp_macro *macro);  int +sl_pp_process_if(struct sl_pp_context *context, +                 const struct sl_pp_token_info *input, +                 unsigned int first, +                 unsigned int last); + +int +sl_pp_process_ifdef(struct sl_pp_context *context, +                    const struct sl_pp_token_info *input, +                    unsigned int first, +                    unsigned int last); + +int +sl_pp_process_ifndef(struct sl_pp_context *context, +                     const struct sl_pp_token_info *input, +                     unsigned int first, +                     unsigned int last); + +int +sl_pp_process_elif(struct sl_pp_context *context, +                   const struct sl_pp_token_info *input, +                   unsigned int first, +                   unsigned int last); + +int +sl_pp_process_else(struct sl_pp_context *context, +                   const struct sl_pp_token_info *input, +                   unsigned int first, +                   unsigned int last); + +int +sl_pp_process_endif(struct sl_pp_context *context, +                    const struct sl_pp_token_info *input, +                    unsigned int first, +                    unsigned int last); + +int  sl_pp_process_out(struct sl_pp_process_state *state,                    const struct sl_pp_token_info *token); | 
