aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccpp.c237
1 files changed, 111 insertions, 126 deletions
diff --git a/tccpp.c b/tccpp.c
index 7eb4501..ced5cc6 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2901,8 +2901,7 @@ ST_FUNC void next_nomacro(void)
static void macro_subst(
TokenString *tok_str,
Sym **nested_list,
- const int *macro_str,
- int can_read_stream
+ const int *macro_str
);
/* substitute arguments in replacement lists in macro_str by the values in
@@ -2992,9 +2991,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
}
} else {
add_var:
- /* NOTE: the stream cannot be read when macro
- substituting an argument */
- macro_subst(&str, nested_list, st, 0);
+ macro_subst(&str, nested_list, st);
}
if (str.len == l0) /* expanded to empty string */
tok_str_add(&str, TOK_PLCHLDR);
@@ -3016,9 +3013,102 @@ static char const ab_month_name[12][4] =
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
+static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
+{
+ CString cstr;
+ int n, ret = 1;
+
+ cstr_new(&cstr);
+ if (t1 != TOK_PLCHLDR)
+ cstr_cat(&cstr, get_tok_str(t1, v1), -1);
+ n = cstr.size;
+ if (t2 != TOK_PLCHLDR)
+ cstr_cat(&cstr, get_tok_str(t2, v2), -1);
+ cstr_ccat(&cstr, '\0');
+
+ tcc_open_bf(tcc_state, ":paste:", cstr.size);
+ memcpy(file->buffer, cstr.data, cstr.size);
+ for (;;) {
+ next_nomacro1();
+ if (0 == *file->buf_ptr)
+ break;
+ if (is_space(tok))
+ continue;
+ tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
+ " preprocessing token", n, cstr.data, (char*)cstr.data + n);
+ ret = 0;
+ break;
+ }
+ tcc_close();
+ //printf("paste <%s>\n", (char*)cstr.data);
+ cstr_free(&cstr);
+ return ret;
+}
+
+/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
+ return the resulting string (which must be freed). */
+static inline int *macro_twosharps(const int *ptr0)
+{
+ int t;
+ CValue cval;
+ TokenString macro_str1;
+ int start_of_nosubsts = -1;
+ const int *ptr;
+
+ /* we search the first '##' */
+ for (ptr = ptr0;;) {
+ TOK_GET(&t, &ptr, &cval);
+ if (t == TOK_PPJOIN)
+ break;
+ if (t == 0)
+ return NULL;
+ }
+
+ tok_str_new(&macro_str1);
+
+ //tok_print(" $$$", ptr0);
+ for (ptr = ptr0;;) {
+ TOK_GET(&t, &ptr, &cval);
+ if (t == 0)
+ break;
+ if (t == TOK_PPJOIN)
+ continue;
+ while (*ptr == TOK_PPJOIN) {
+ int t1; CValue cv1;
+ /* given 'a##b', remove nosubsts preceding 'a' */
+ if (start_of_nosubsts >= 0)
+ macro_str1.len = start_of_nosubsts;
+ /* given 'a##b', remove nosubsts preceding 'b' */
+ while ((t1 = *++ptr) == TOK_NOSUBST)
+ ;
+ if (t1 && t1 != TOK_PPJOIN) {
+ TOK_GET(&t1, &ptr, &cv1);
+ if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) {
+ if (paste_tokens(t, &cval, t1, &cv1)) {
+ t = tok, cval = tokc;
+ } else {
+ tok_str_add2(&macro_str1, t, &cval);
+ t = t1, cval = cv1;
+ }
+ }
+ }
+ }
+ if (t == TOK_NOSUBST) {
+ if (start_of_nosubsts < 0)
+ start_of_nosubsts = macro_str1.len;
+ } else {
+ start_of_nosubsts = -1;
+ }
+ tok_str_add2(&macro_str1, t, &cval);
+ }
+ tok_str_add(&macro_str1, 0);
+ //tok_print(" ###", macro_str1.str);
+ return macro_str1.str;
+}
+
/* peek or read [ws_str == NULL] next token from function macro call,
walking up macro levels up to the file if necessary */
-static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *ws_str)
+static int next_argstream(Sym **nested_list, TokenString *ws_str)
{
int t;
const int *p;
@@ -3081,8 +3171,7 @@ static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *w
static int macro_subst_tok(
TokenString *tok_str,
Sym **nested_list,
- Sym *s,
- int can_read_stream)
+ Sym *s)
{
Sym *args, *sa, *sa1;
int parlevel, *mstr, t, t1, spc;
@@ -3127,6 +3216,7 @@ static int macro_subst_tok(
cstr_free(&cstr);
} else {
int saved_parse_flags = parse_flags;
+ int *joined_str = NULL;
mstr = s->d;
if (s->type.t == MACRO_FUNC) {
@@ -3139,7 +3229,7 @@ static int macro_subst_tok(
| PARSE_FLAG_ACCEPT_STRAYS;
/* get next token from argument stream */
- t = next_argstream(nested_list, can_read_stream, &ws_str);
+ t = next_argstream(nested_list, &ws_str);
if (t != '(') {
/* not a macro substitution after all, restore the
* macro token plus all whitespace we've read.
@@ -3167,7 +3257,7 @@ static int macro_subst_tok(
/* NOTE: empty args are allowed, except if no args */
for(;;) {
do {
- next_argstream(nested_list, can_read_stream, NULL);
+ next_argstream(nested_list, NULL);
} while (is_space(tok) || TOK_LINEFEED == tok);
empty_arg:
/* handle '()' case */
@@ -3192,7 +3282,7 @@ static int macro_subst_tok(
tok = ' ';
if (!check_space(tok, &spc))
tok_str_add2(&str, tok, &tokc);
- next_argstream(nested_list, can_read_stream, NULL);
+ next_argstream(nested_list, NULL);
}
if (parlevel)
expect(")");
@@ -3233,140 +3323,38 @@ static int macro_subst_tok(
sym_push2(nested_list, s->v, 0, 0);
parse_flags = saved_parse_flags;
- macro_subst(tok_str, nested_list, mstr, can_read_stream | 2);
+ joined_str = macro_twosharps(mstr);
+ macro_subst(tok_str, nested_list, joined_str ? joined_str : mstr);
/* pop nested defined symbol */
sa1 = *nested_list;
*nested_list = sa1->prev;
sym_free(sa1);
+ if (joined_str)
+ tok_str_free_str(joined_str);
if (mstr != s->d)
tok_str_free_str(mstr);
}
return 0;
}
-static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
-{
- CString cstr;
- int n, ret = 1;
-
- cstr_new(&cstr);
- if (t1 != TOK_PLCHLDR)
- cstr_cat(&cstr, get_tok_str(t1, v1), -1);
- n = cstr.size;
- if (t2 != TOK_PLCHLDR)
- cstr_cat(&cstr, get_tok_str(t2, v2), -1);
- cstr_ccat(&cstr, '\0');
-
- tcc_open_bf(tcc_state, ":paste:", cstr.size);
- memcpy(file->buffer, cstr.data, cstr.size);
- for (;;) {
- next_nomacro1();
- if (0 == *file->buf_ptr)
- break;
- if (is_space(tok))
- continue;
- tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
- " preprocessing token", n, cstr.data, (char*)cstr.data + n);
- ret = 0;
- break;
- }
- tcc_close();
- //printf("paste <%s>\n", (char*)cstr.data);
- cstr_free(&cstr);
- return ret;
-}
-
-/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
- return the resulting string (which must be freed). */
-static inline int *macro_twosharps(const int *ptr0)
-{
- int t;
- CValue cval;
- TokenString macro_str1;
- int start_of_nosubsts = -1;
- const int *ptr;
-
- /* we search the first '##' */
- for (ptr = ptr0;;) {
- TOK_GET(&t, &ptr, &cval);
- if (t == TOK_PPJOIN)
- break;
- if (t == 0)
- return NULL;
- }
-
- tok_str_new(&macro_str1);
-
- //tok_print(" $$$", ptr0);
- for (ptr = ptr0;;) {
- TOK_GET(&t, &ptr, &cval);
- if (t == 0)
- break;
- if (t == TOK_PPJOIN)
- continue;
- while (*ptr == TOK_PPJOIN) {
- int t1; CValue cv1;
- /* given 'a##b', remove nosubsts preceding 'a' */
- if (start_of_nosubsts >= 0)
- macro_str1.len = start_of_nosubsts;
- /* given 'a##b', remove nosubsts preceding 'b' */
- while ((t1 = *++ptr) == TOK_NOSUBST)
- ;
- if (t1 && t1 != TOK_PPJOIN) {
- TOK_GET(&t1, &ptr, &cv1);
- if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) {
- if (paste_tokens(t, &cval, t1, &cv1)) {
- t = tok, cval = tokc;
- } else {
- tok_str_add2(&macro_str1, t, &cval);
- t = t1, cval = cv1;
- }
- }
- }
- }
- if (t == TOK_NOSUBST) {
- if (start_of_nosubsts < 0)
- start_of_nosubsts = macro_str1.len;
- } else {
- start_of_nosubsts = -1;
- }
- tok_str_add2(&macro_str1, t, &cval);
- }
- tok_str_add(&macro_str1, 0);
- //tok_print(" ###", macro_str1.str);
- return macro_str1.str;
-}
-
/* do macro substitution of macro_str and add result to
(tok_str,tok_len). 'nested_list' is the list of all macros we got
inside to avoid recursing. */
static void macro_subst(
TokenString *tok_str,
Sym **nested_list,
- const int *macro_str,
- int can_read_stream
+ const int *macro_str
)
{
Sym *s;
- const int *ptr;
int t, spc, nosubst;
CValue cval;
- int *macro_str1 = NULL;
- /* first scan for '##' operator handling */
- ptr = macro_str;
spc = nosubst = 0;
- /* first scan for '##' operator handling */
- if (can_read_stream) {
- macro_str1 = macro_twosharps(ptr);
- if (macro_str1)
- ptr = macro_str1;
- }
-
while (1) {
- TOK_GET(&t, &ptr, &cval);
+ TOK_GET(&t, &macro_str, &cval);
if (t <= 0)
break;
@@ -3384,18 +3372,18 @@ static void macro_subst(
{
TokenString str;
- str.str = (int*)ptr;
+ str.str = (int*)macro_str;
begin_macro(&str, 2);
tok = t;
- macro_subst_tok(tok_str, nested_list, s, can_read_stream);
+ macro_subst_tok(tok_str, nested_list, s);
if (str.alloc == 3) {
/* already finished by reading function macro arguments */
break;
}
- ptr = macro_ptr;
+ macro_str = macro_ptr;
end_macro ();
}
@@ -3416,9 +3404,6 @@ no_subst:
nosubst = 1;
}
}
- if (macro_str1)
- tok_str_free_str(macro_str1);
-
}
/* return next token with macro substitution */
@@ -3446,7 +3431,7 @@ ST_FUNC void next(void)
if (s) {
Sym *nested_list = NULL;
tokstr_buf.len = 0;
- macro_subst_tok(&tokstr_buf, &nested_list, s, 1);
+ macro_subst_tok(&tokstr_buf, &nested_list, s);
tok_str_add(&tokstr_buf, 0);
begin_macro(&tokstr_buf, 2);
goto redo;