summaryrefslogtreecommitdiff
path: root/src/glsl
diff options
context:
space:
mode:
authorMichal Krol <michal@vmware.com>2009-06-22 09:05:29 +0200
committerMichal Krol <michal@vmware.com>2009-09-07 10:11:47 +0200
commit6a11d4150cfcdd646c17f8b365b5481c2c583208 (patch)
tree9037f4dc93262d269ba126788a0d5691bb10b4cd /src/glsl
parent5e8e3cddae9b2797cfa525c643c701debe2f4c04 (diff)
glsl: Implement macro expansion.
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/pp/sl_pp_define.c38
-rw-r--r--src/glsl/pp/sl_pp_macro.c204
-rw-r--r--src/glsl/pp/sl_pp_macro.h9
-rw-r--r--src/glsl/pp/sl_pp_process.c31
-rw-r--r--src/glsl/pp/sl_pp_process.h6
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, &macro->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 */