On Tue, May 08, 2007 at 02:33:13AM +0200, Harald van Dijk wrote:
> Hi,
>
> Here's a patch to handle spacing during stringizing
and here's a patch to be applied on top of it. It fixes stringizing in
cases involving macro or macro argument substitutions where the
replacement is empty. If this happens, whitespace before and after the
replacement needs to be combined. An example:
#define MKSTR(x) STR(x)
#define STR(x) #x
#define EMPTY /* nothing */
MKSTR(.EMPTY.) /* ".." */
MKSTR(.EMPTY .) /* ". ." */
MKSTR(. EMPTY.) /* ". ." */
MKSTR(. EMPTY .) /* ". ." */
With the first patch, the third MKSTR invocation would expand to "..".
It also fixes spacing in concatenated macro arguments.
#define MKSTR(x) STR(x)
#define STR(x) #x
#define CAT(x,y) x##y
MKSTR(CAT(. a,b .)) /* ". ab ." */
With the previous patch, it would expand to ".ab.".
--- tinycc-rl-1.0.0/tcc.c
+++ tinycc-rl-1.0.0/tcc.c
@@ -3129,13 +3129,16 @@
tok_str_new(&str);
last_tok = 0;
+ save_tf = 0;
while(1) {
TOK_GET(t, tf, macro_str, cval);
+ tf |= save_tf;
- save_tf = tf;
+ save_tf = 0;
if (!t)
break;
if (t == '#') {
/* stringize */
+ save_tf = tf;
TOK_GET(t, tf, macro_str, cval);
if (!t)
break;
@@ -3162,11 +3165,12 @@
} else {
tok_str_add2(&str, t, save_tf, &cval);
}
+ save_tf = 0;
} else if (t >= TOK_IDENT) {
s = sym_find2(args, t);
if (s) {
st = (int *)s->c;
- st[1] = save_tf;
+ st[1] = save_tf = tf;
/* if '##' is present before or after, no arg substitution */
if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
/* special case for var arg macros : ## eats the
@@ -3189,17 +3193,19 @@
} else {
int t1;
add_var:
+ save_tf = 0;
for(;;) {
TOK_GET(t1, tf, st, cval);
if (!t1)
break;
- tok_str_add2(&str, t1, save_tf, &cval);
+ tok_str_add2(&str, t1, tf, &cval);
}
}
} else {
/* NOTE: the stream cannot be read when macro
substituing an argument */
- macro_subst(&str, nested_list, st, NULL);
+ if (macro_subst(&str, nested_list, st, NULL) > 0)
+ save_tf = 0;
}
} else {
tok_str_add(&str, t, tf);
@@ -3221,8 +3227,8 @@
/* do macro substitution of current token with macro 's' and add
result to (tok_str,tok_len). 'nested_list' is the list of all
- macros we got inside to avoid recursing. Return non zero if no
+ macros we got inside to avoid recursing. Return -1 if no
- substitution needs to be done */
+ substitution needs to be done, else the number of added tokens. */
static int macro_subst_tok(TokenString *tok_str,
Sym **nested_list, Sym *s, struct macro_level
**can_read_stream)
{
@@ -3267,6 +3273,7 @@
cval.cstr = &cstr;
tok_str_add2(tok_str, t1, tok_flags, &cval);
cstr_free(&cstr);
+ return 1;
} else {
mstr = (int *)s->c;
mstr[1] = tok_flags;
@@ -3360,15 +3367,15 @@
mstr_allocated = 1;
}
sym_push2(nested_list, s->v, 0, 0);
- macro_subst(tok_str, nested_list, mstr, can_read_stream);
+ t = macro_subst(tok_str, nested_list, mstr, can_read_stream);
/* pop nested defined symbol */
sa1 = *nested_list;
*nested_list = sa1->prev;
sym_free(sa1);
if (mstr_allocated)
tok_str_free(mstr);
+ return t;
}
- return 0;
}
/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
@@ -3512,14 +3519,14 @@
/* 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. */
+ inside to avoid recursing. Return the number of added tokens. */
-static void macro_subst(TokenString *tok_str, Sym **nested_list,
+static int macro_subst(TokenString *tok_str, Sym **nested_list,
- const int *macro_str, struct macro_level **
can_read_stream)
+ const int *macro_str, struct macro_level **
can_read_stream)
{
Sym *s;
int *macro_str1;
const int *ptr;
- int t, tf, ret;
+ int t, tf, save_tf, len, ret;
CValue cval;
struct macro_level ml;
@@ -3528,12 +3535,18 @@
macro_str1 = macro_twosharps(ptr);
if (macro_str1)
ptr = macro_str1;
+
+ save_tf = 0;
+ len = 0;
while (1) {
/* NOTE: ptr == NULL can only happen if tokens are read from
file stream due to a macro function call */
if (ptr == NULL)
break;
TOK_GET(t, tf, ptr, cval);
+ tf |= save_tf;
+ save_tf = 0;
+
if (t == 0)
break;
s = define_find(t);
@@ -3552,15 +3565,21 @@
macro_ptr = ml.p;
if (can_read_stream && *can_read_stream == &ml)
*can_read_stream = ml.prev;
- if (ret != 0)
+ if (ret < 0)
goto no_subst;
+ if (ret == 0)
+ save_tf = tf;
+ if (ret > 0)
+ len += ret;
} else {
no_subst:
tok_str_add2(tok_str, t, tf, &cval);
+ len += 1;
}
}
if (macro_str1)
tok_str_free(macro_str1);
+ return len;
}
@@ -3584,7 +3603,7 @@
tok_str_new(&str);
nested_list = NULL;
ml = NULL;
- if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
+ if (macro_subst_tok(&str, &nested_list, s, &ml) >= 0) {
/* substitution done, NOTE: maybe empty */
tok_str_add(&str, 0, 0);
macro_ptr = str.str;
@@ -8483,7 +8502,7 @@
tok_str_new(&str);
nested_list = NULL;
ml = NULL;
- if (macro_subst_tok(&str, &nested_list, top, &ml) == 0) {
+ if (macro_subst_tok(&str, &nested_list, top, &ml) >= 0) {
int t, tf, *stri;
CValue cval;
preprocess_out("#define ");
--- tinycc-rl-1.0.0/tcc.h
+++ tinycc-rl-1.0.0/tcc.h
@@ -707,8 +707,8 @@
int *p;
};
-static void macro_subst(TokenString *tok_str, Sym **nested_list,
+static int macro_subst(TokenString *tok_str, Sym **nested_list,
- const int *macro_str, struct macro_level
**can_read_stream);
+ const int *macro_str, struct macro_level
**can_read_stream);
void gen_op(int op);
void force_charshort_cast(int t);
static void gen_cast(CType *type);
_______________________________________________
Tinycc-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel