{
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) {
(**arg).next = NULL;
arg = &(**arg).next;
+ macro->num_args++;
+
skip_whitespace(input, first, last);
if (*first < last) {
if (input[*first].token == SL_PP_COMMA) {
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;
}
}
- /* 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;
}
#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)
{
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++;
+ }
+ }
+}
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 */
}
-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;
return 0;
}
-
int
sl_pp_process(struct sl_pp_context *context,
const struct sl_pp_token_info *input,
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));
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++;
break;
case SL_PP_EOF:
- if (out_token(&state, &input[i])) {
+ if (sl_pp_process_out(&state, &input[i])) {
return -1;
}
i++;
case SL_PP_NEWLINE:
/* Empty directive. */
- if (out_token(&state, &input[i])) {
+ if (sl_pp_process_out(&state, &input[i])) {
return -1;
}
i++;
case SL_PP_EOF:
/* Empty directive. */
- if (out_token(&state, &input[i])) {
+ if (sl_pp_process_out(&state, &input[i])) {
return -1;
}
i++;
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++;
break;
case SL_PP_EOF:
- if (out_token(&state, &input[i])) {
+ if (sl_pp_process_out(&state, &input[i])) {
return -1;
}
i++;
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++;
#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,
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 */