mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 09:08:10 +02:00
glsl: Implement macro expansion.
This commit is contained in:
parent
5e8e3cddae
commit
6a11d4150c
5 changed files with 262 additions and 32 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, ¯o->body[j])) {
|
||||
return -1;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue