glsl: Implement macro expansion.

This commit is contained in:
Michal Krol 2009-06-22 09:05:29 +02:00
parent 5e8e3cddae
commit 6a11d4150c
5 changed files with 262 additions and 32 deletions

View file

@ -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);
/* 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;
/* 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++;
}
memcpy(macro->body,
&input[first],
sizeof(struct sl_pp_token_info) * macro->body_len);
}
macro->body = malloc(sizeof(struct sl_pp_token_info) * 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];
}
}
macro->body[j++].token = SL_PP_EOF;
return 0;
}

View file

@ -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++;
}
}
}

View file

@ -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 */

View file

@ -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++;

View file

@ -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 */