glsl: Parse define directive in preprocessor.
authorMichal Krol <michal@vmware.com>
Fri, 19 Jun 2009 10:02:28 +0000 (12:02 +0200)
committerMichal Krol <michal@vmware.com>
Mon, 7 Sep 2009 08:11:45 +0000 (10:11 +0200)
src/glsl/pp/SConscript
src/glsl/pp/sl_pp_context.c
src/glsl/pp/sl_pp_context.h
src/glsl/pp/sl_pp_define.c [new file with mode: 0644]
src/glsl/pp/sl_pp_macro.c [new file with mode: 0644]
src/glsl/pp/sl_pp_macro.h [new file with mode: 0644]
src/glsl/pp/sl_pp_process.c
src/glsl/pp/sl_pp_process.h

index 3d4a1cb967ca2c8a39fd91e02343a363f93fde65..1fde3dfccf364520867c83197285f3baed698423 100644 (file)
@@ -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',
index 71712de1fe263fe71dc52eb4eb0ce2ae2202292b..8722376ae52c1521058817c7d881780b6737dcb0 100644 (file)
@@ -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
index e4686b89e33a4d7be67601e58f96ba8582a0f05d..cb81f73ab9e9c65986287eb072d5b9179e8c03cc 100644 (file)
 #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 (file)
index 0000000..5ce0f05
--- /dev/null
@@ -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 <stdlib.h>
+#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 = &macro->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 (file)
index 0000000..eed0978
--- /dev/null
@@ -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 <stdlib.h>
+#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 (file)
index 0000000..4ebbff5
--- /dev/null
@@ -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 */
index 1005c501050dd27c38e9bba2823d481c0f00d922..2a375df71a47385d85357cbefffa078cd5bcd007 100644 (file)
@@ -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;
 
index d6401de960edf07a1ea4a9608bdc5fcc4ec37c11..f7df9a2850a9278bc7eb7f3a6dc2d79ceea84a8e 100644 (file)
@@ -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 */