summaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
authorMichal Krol <[email protected]>2009-06-19 12:02:28 +0200
committerMichal Krol <[email protected]>2009-09-07 10:11:45 +0200
commitfd991d845a5f639b9b675a4840ad234c151d56b4 (patch)
tree46a786562e309631fcdcb3e5ffaec820a4b4baef /src/glsl
parent3ce5e668180748e2eccd1a8d3931ab98c2919df3 (diff)
glsl: Parse define directive in preprocessor.
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/pp/SConscript2
-rw-r--r--src/glsl/pp/sl_pp_context.c1
-rw-r--r--src/glsl/pp/sl_pp_context.h4
-rw-r--r--src/glsl/pp/sl_pp_define.c156
-rw-r--r--src/glsl/pp/sl_pp_macro.c51
-rw-r--r--src/glsl/pp/sl_pp_macro.h50
-rw-r--r--src/glsl/pp/sl_pp_process.c29
-rw-r--r--src/glsl/pp/sl_pp_process.h8
8 files changed, 296 insertions, 5 deletions
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 <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
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 <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
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 */