Mesa (master): glsl/pp: Fix handling of if/elif/else cases.

Michał Król michal at kemper.freedesktop.org
Mon Feb 15 20:33:35 UTC 2010


Module: Mesa
Branch: master
Commit: ee67167358e91e9ffde8aa9e5b96e5def4c16904
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ee67167358e91e9ffde8aa9e5b96e5def4c16904

Author: Michal Krol <michal at vmware.com>
Date:   Mon Feb 15 21:33:22 2010 +0100

glsl/pp: Fix handling of if/elif/else cases.

Once if/elif evalutes to true, all subsequent conditions are always false.

---

 src/glsl/pp/sl_pp_context.h |   11 ++++++++++-
 src/glsl/pp/sl_pp_if.c      |   28 ++++++++++++++++++----------
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h
index 983a09c..b5419bc 100644
--- a/src/glsl/pp/sl_pp_context.h
+++ b/src/glsl/pp/sl_pp_context.h
@@ -53,6 +53,15 @@ struct sl_pp_predefined {
    int value;
 };
 
+union sl_pp_if_state {
+   struct {
+      unsigned int condition:1;
+      unsigned int went_thru_else:1;
+      unsigned int had_true_cond:1;
+   } u;
+   unsigned int value;
+};
+
 struct sl_pp_context {
    char *cstr_pool;
    unsigned int cstr_pool_max;
@@ -68,7 +77,7 @@ struct sl_pp_context {
    struct sl_pp_predefined predefined[SL_PP_MAX_PREDEFINED];
    unsigned int num_predefined;
 
-   unsigned int if_stack[SL_PP_MAX_IF_NESTING];
+   union sl_pp_if_state if_stack[SL_PP_MAX_IF_NESTING];
    unsigned int if_ptr;
    unsigned int if_value;
 
diff --git a/src/glsl/pp/sl_pp_if.c b/src/glsl/pp/sl_pp_if.c
index 272c3a2..e233999 100644
--- a/src/glsl/pp/sl_pp_if.c
+++ b/src/glsl/pp/sl_pp_if.c
@@ -108,7 +108,7 @@ _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)) {
+      if (!context->if_stack[i].u.condition) {
          return 0;
       }
    }
@@ -182,7 +182,8 @@ _parse_if(struct sl_pp_context *context,
    free(state.out);
 
    context->if_ptr--;
-   context->if_stack[context->if_ptr] = result ? 1 : 0;
+   context->if_stack[context->if_ptr].value = 0;
+   context->if_stack[context->if_ptr].u.condition = result ? 1 : 0;
    context->if_value = _evaluate_if_stack(context);
 
    return 0;
@@ -191,19 +192,24 @@ _parse_if(struct sl_pp_context *context,
 static int
 _parse_else(struct sl_pp_context *context)
 {
+   union sl_pp_if_state *state = &context->if_stack[context->if_ptr];
+
    if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
       strcpy(context->error_msg, "no matching `#if'");
       return -1;
    }
 
-   /* Bit b1 indicates we already went through #else. */
-   if (context->if_stack[context->if_ptr] & 2) {
+   if (state->u.went_thru_else) {
       strcpy(context->error_msg, "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;
+   /* Once we had a true condition, the subsequent #elifs should always be false. */
+   state->u.had_true_cond |= state->u.condition;
+
+   /* Update current condition value and mark that we are in the #else block. */
+   state->u.condition = !(state->u.had_true_cond | state->u.condition);
+   state->u.went_thru_else = 1;
    context->if_value = _evaluate_if_stack(context);
 
    return 0;
@@ -233,7 +239,8 @@ sl_pp_process_ifdef(struct sl_pp_context *context,
       switch (input[i].token) {
       case SL_PP_IDENTIFIER:
          context->if_ptr--;
-         context->if_stack[context->if_ptr] = _macro_is_defined(context, input[i].data.identifier);
+         context->if_stack[context->if_ptr].value = 0;
+         context->if_stack[context->if_ptr].u.condition = _macro_is_defined(context, input[i].data.identifier);
          context->if_value = _evaluate_if_stack(context);
          return 0;
 
@@ -267,7 +274,8 @@ sl_pp_process_ifndef(struct sl_pp_context *context,
       switch (input[i].token) {
       case SL_PP_IDENTIFIER:
          context->if_ptr--;
-         context->if_stack[context->if_ptr] = !_macro_is_defined(context, input[i].data.identifier);
+         context->if_stack[context->if_ptr].value = 0;
+         context->if_stack[context->if_ptr].u.condition = !_macro_is_defined(context, input[i].data.identifier);
          context->if_value = _evaluate_if_stack(context);
          return 0;
 
@@ -292,7 +300,7 @@ sl_pp_process_elif(struct sl_pp_context *context,
       return -1;
    }
 
-   if (context->if_stack[context->if_ptr] & 1) {
+   if (context->if_stack[context->if_ptr].u.condition) {
       context->if_ptr++;
       if (_parse_if(context, buffer)) {
          return -1;
@@ -300,7 +308,7 @@ sl_pp_process_elif(struct sl_pp_context *context,
    }
 
    /* We are still in the #if block. */
-   context->if_stack[context->if_ptr] = context->if_stack[context->if_ptr] & ~2;
+   context->if_stack[context->if_ptr].u.went_thru_else = 0;
 
    return 0;
 }




More information about the mesa-commit mailing list