diff options
| -rw-r--r-- | src/glsl/pp/sl_pp_define.c | 38 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_macro.c | 204 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_macro.h | 9 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_process.c | 31 | ||||
| -rw-r--r-- | src/glsl/pp/sl_pp_process.h | 6 | 
5 files changed, 259 insertions, 29 deletions
| diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c index 5ce0f0551b..39d1435064 100644 --- a/src/glsl/pp/sl_pp_define.c +++ b/src/glsl/pp/sl_pp_define.c @@ -48,6 +48,8 @@ _parse_formal_args(const struct sl_pp_token_info *input,  {     struct sl_pp_macro_formal_arg **arg; +   macro->num_args = 0; +     skip_whitespace(input, first, last);     if (*first < last) {        if (input[*first].token == SL_PP_RPAREN) { @@ -78,6 +80,8 @@ _parse_formal_args(const struct sl_pp_token_info *input,        (**arg).next = NULL;        arg = &(**arg).next; +      macro->num_args++; +        skip_whitespace(input, first, last);        if (*first < last) {           if (input[*first].token == SL_PP_COMMA) { @@ -104,7 +108,12 @@ sl_pp_process_define(struct sl_pp_context *context,                       unsigned int last,                       struct sl_pp_macro *macro)  { +   unsigned int i; +   unsigned int body_len; +   unsigned int j; +     macro->name = -1; +   macro->num_args = -1;     macro->arg = NULL;     macro->body = NULL;     macro->next = NULL; @@ -131,26 +140,25 @@ sl_pp_process_define(struct sl_pp_context *context,        }     } -   /* Trim whitespace from the left side. */ -   skip_whitespace(input, &first, last); +   /* Calculate body size, trim out whitespace, make room for EOF. */ +   body_len = 1; +   for (i = first; i < last; i++) { +      if (input[i].token != SL_PP_WHITESPACE) { +         body_len++; +      } +   } -   /* Trom whitespace from the right side. */ -   while (first < last && input[last - 1].token == SL_PP_WHITESPACE) { -      last--; +   macro->body = malloc(sizeof(struct sl_pp_token_info) * body_len); +   if (!macro->body) { +      return -1;     } -   /* 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; +   for (j = 0, i = first; i < last; i++) { +      if (input[i].token != SL_PP_WHITESPACE) { +         macro->body[j++] = input[i];        } - -      memcpy(macro->body, -             &input[first], -             sizeof(struct sl_pp_token_info) * macro->body_len);     } +   macro->body[j++].token = SL_PP_EOF;     return 0;  } diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c index eed0978304..82591b9d77 100644 --- a/src/glsl/pp/sl_pp_macro.c +++ b/src/glsl/pp/sl_pp_macro.c @@ -27,8 +27,18 @@  #include <stdlib.h>  #include "sl_pp_macro.h" +#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)++; +   } +} +  void  sl_pp_macro_free(struct sl_pp_macro *macro)  { @@ -49,3 +59,197 @@ sl_pp_macro_free(struct sl_pp_macro *macro)        macro = next_macro;     }  } + +int +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) +{ +   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) { +      return -1; +   } + +   macro_name = input[*pi].data.identifier; + +   if (local) { +      for (macro = local; macro; macro = macro->next) { +         if (macro->name == macro_name) { +            break; +         } +      } +   } + +   if (!macro) { +      for (macro = context->macro; macro; macro = macro->next) { +         if (macro->name == macro_name) { +            break; +         } +      } +   } + +   if (!macro) { +      if (sl_pp_process_out(state, &input[*pi])) { +         return -1; +      } +      (*pi)++; +      return 0; +   } + +   (*pi)++; + +   if (macro->num_args >= 0) { +      skip_whitespace(input, pi); +      if (input[*pi].token != SL_PP_LPAREN) { +         return -1; +      } +      (*pi)++; +      skip_whitespace(input, pi); +   } + +   if (macro->num_args > 0) { +      struct sl_pp_macro_formal_arg *formal_arg = macro->arg; +      struct sl_pp_macro **pmacro = &actual_arg; + +      for (j = 0; j < (unsigned int)macro->num_args; j++) { +         unsigned int body_len; +         unsigned int i; +         int done = 0; +         unsigned int paren_nesting = 0; +         unsigned int k; + +         *pmacro = malloc(sizeof(struct sl_pp_macro)); +         if (!*pmacro) { +            return -1; +         } + +         (**pmacro).name = formal_arg->name; +         (**pmacro).num_args = -1; +         (**pmacro).arg = NULL; +         (**pmacro).body = NULL; +         (**pmacro).next = NULL; + +         body_len = 1; +         for (i = *pi; !done; i++) { +            switch (input[i].token) { +            case SL_PP_WHITESPACE: +               break; + +            case SL_PP_COMMA: +               if (!paren_nesting) { +                  if (j < (unsigned int)macro->num_args - 1) { +                     done = 1; +                  } else { +                     return -1; +                  } +               } else { +                  body_len++; +               } +               break; + +            case SL_PP_LPAREN: +               paren_nesting++; +               body_len++; +               break; + +            case SL_PP_RPAREN: +               if (!paren_nesting) { +                  if (j == (unsigned int)macro->num_args - 1) { +                     done = 1; +                  } else { +                     return -1; +                  } +               } else { +                  paren_nesting--; +                  body_len++; +               } +               break; + +            case SL_PP_EOF: +               return -1; + +            default: +               body_len++; +            } +         } + +         (**pmacro).body = malloc(sizeof(struct sl_pp_token_info) * body_len); +         if (!(**pmacro).body) { +            return -1; +         } + +         for (done = 0, k = 0, i = *pi; !done; i++) { +            switch (input[i].token) { +            case SL_PP_WHITESPACE: +               break; + +            case SL_PP_COMMA: +               if (!paren_nesting && j < (unsigned int)macro->num_args - 1) { +                  done = 1; +               } else { +                  (**pmacro).body[k++] = input[i]; +               } +               break; + +            case SL_PP_LPAREN: +               paren_nesting++; +               (**pmacro).body[k++] = input[i]; +               break; + +            case SL_PP_RPAREN: +               if (!paren_nesting && j == (unsigned int)macro->num_args - 1) { +                  done = 1; +               } else { +                  paren_nesting--; +                  (**pmacro).body[k++] = input[i]; +               } +               break; + +            default: +               (**pmacro).body[k++] = input[i]; +            } +         } + +         (**pmacro).body[k++].token = SL_PP_EOF; +         (*pi) = i; + +         formal_arg = formal_arg->next; +         pmacro = &(**pmacro).next; +      } +   } + +   /* 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) { +         return -1; +      } +      (*pi)++; +   } + +   for (j = 0;;) { +      switch (macro->body[j].token) { +      case SL_PP_IDENTIFIER: +         if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state)) { +            return -1; +         } +         break; + +      case SL_PP_EOF: +         sl_pp_macro_free(actual_arg); +         return 0; + +      default: +         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 4ebbff5590..eeb338eec4 100644 --- a/src/glsl/pp/sl_pp_macro.h +++ b/src/glsl/pp/sl_pp_macro.h @@ -38,13 +38,20 @@ struct sl_pp_macro_formal_arg {  struct sl_pp_macro {     int name; +   int num_args;     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); +int +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); +  #endif /* SL_PP_MACRO_H */ diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c index 2a375df71a..e930966604 100644 --- a/src/glsl/pp/sl_pp_process.c +++ b/src/glsl/pp/sl_pp_process.c @@ -39,16 +39,16 @@ skip_whitespace(const struct sl_pp_token_info *input,  } -struct process_state { +struct sl_pp_process_state {     struct sl_pp_token_info *out;     unsigned int out_len;     unsigned int out_max;  }; -static int -out_token(struct process_state *state, -          const struct sl_pp_token_info *token) +int +sl_pp_process_out(struct sl_pp_process_state *state, +                  const struct sl_pp_token_info *token)  {     if (state->out_len >= state->out_max) {        unsigned int new_max = state->out_max; @@ -72,7 +72,6 @@ out_token(struct process_state *state,     return 0;  } -  int  sl_pp_process(struct sl_pp_context *context,                const struct sl_pp_token_info *input, @@ -81,7 +80,7 @@ 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; +   struct sl_pp_process_state state;     macro = &context->macro;     memset(&state, 0, sizeof(state)); @@ -110,7 +109,7 @@ sl_pp_process(struct sl_pp_context *context,                    switch (input[i].token) {                    case SL_PP_NEWLINE:                       /* Preserve newline just for the sake of line numbering. */ -                     if (out_token(&state, &input[i])) { +                     if (sl_pp_process_out(&state, &input[i])) {                          return -1;                       }                       i++; @@ -118,7 +117,7 @@ sl_pp_process(struct sl_pp_context *context,                       break;                    case SL_PP_EOF: -                     if (out_token(&state, &input[i])) { +                     if (sl_pp_process_out(&state, &input[i])) {                          return -1;                       }                       i++; @@ -152,7 +151,7 @@ sl_pp_process(struct sl_pp_context *context,           case SL_PP_NEWLINE:              /* Empty directive. */ -            if (out_token(&state, &input[i])) { +            if (sl_pp_process_out(&state, &input[i])) {                 return -1;              }              i++; @@ -160,7 +159,7 @@ sl_pp_process(struct sl_pp_context *context,           case SL_PP_EOF:              /* Empty directive. */ -            if (out_token(&state, &input[i])) { +            if (sl_pp_process_out(&state, &input[i])) {                 return -1;              }              i++; @@ -182,7 +181,7 @@ sl_pp_process(struct sl_pp_context *context,              case SL_PP_NEWLINE:                 /* Preserve newline just for the sake of line numbering. */ -               if (out_token(&state, &input[i])) { +               if (sl_pp_process_out(&state, &input[i])) {                    return -1;                 }                 i++; @@ -190,7 +189,7 @@ sl_pp_process(struct sl_pp_context *context,                 break;              case SL_PP_EOF: -               if (out_token(&state, &input[i])) { +               if (sl_pp_process_out(&state, &input[i])) {                    return -1;                 }                 i++; @@ -198,8 +197,14 @@ sl_pp_process(struct sl_pp_context *context,                 found_eol = 1;                 break; +            case SL_PP_IDENTIFIER: +               if (sl_pp_macro_expand(context, input, &i, NULL, &state)) { +                  return -1; +               } +               break; +              default: -               if (out_token(&state, &input[i])) { +               if (sl_pp_process_out(&state, &input[i])) {                    return -1;                 }                 i++; diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h index f7df9a2850..37cdc4c9a7 100644 --- a/src/glsl/pp/sl_pp_process.h +++ b/src/glsl/pp/sl_pp_process.h @@ -33,6 +33,8 @@  #include "sl_pp_token.h" +struct sl_pp_process_state; +  int  sl_pp_process(struct sl_pp_context *context,                const struct sl_pp_token_info *input, @@ -45,4 +47,8 @@ sl_pp_process_define(struct sl_pp_context *context,                       unsigned int last,                       struct sl_pp_macro *macro); +int +sl_pp_process_out(struct sl_pp_process_state *state, +                  const struct sl_pp_token_info *token); +  #endif /* SL_PP_PROCESS_H */ | 
