diff options
Diffstat (limited to 'pp.c')
| -rw-r--r-- | pp.c | 37 | 
1 files changed, 23 insertions, 14 deletions
| @@ -10,8 +10,10 @@  struct macroparam {  	char *name; -	/* whether or not the argument needs to be stringized */ -	bool stringize; +	enum { +		PARAMTOK = 1<<0,  /* the parameter is used normally */ +		PARAMSTR = 1<<1,  /* the parameter is used with the '#' operator */ +	} flags;  };  struct macroarg { @@ -214,7 +216,7 @@ define(void)  		while (scan(&tok), tok.kind == TIDENT) {  			p = arrayadd(¶ms, sizeof(*p));  			p->name = tok.lit; -			p->stringize = false; +			p->flags = 0;  			if (scan(&tok), tok.kind != TCOMMA)  				break;  		} @@ -227,18 +229,24 @@ define(void)  	m->nparam = params.len / sizeof(m->param[0]);  	/* read macro body */ +	i = macroparam(m, t);  	while (t->kind != TNEWLINE && t->kind != TEOF) {  		if (t->kind == THASHHASH)  			error(&t->loc, "'##' operator is not yet implemented");  		prev = t->kind;  		t = arrayadd(&repl, sizeof(*t));  		scan(t); -		if (prev == THASH && m->kind == MACROFUNC) { +		if (m->kind != MACROFUNC) +			continue; +		if (i != -1) +			m->param[i].flags |= PARAMTOK; +		i = macroparam(m, t); +		if (prev == THASH) {  			tokencheck(t, TIDENT, "after '#' operator"); -			i = macroparam(m, t);  			if (i == -1)  				error(&t->loc, "'%s' is not a macro parameter name", t->lit); -			m->param[i].stringize = true; +			m->param[i].flags |= PARAMSTR; +			i = -1;  		}  	}  	m->token = repl.val; @@ -423,7 +431,7 @@ expand(struct token *t)  			t = rawnext();  		}  		for (i = 0; i < m->nparam && t->kind != TRPAREN; ++i) { -			if (m->param[i].stringize) { +			if (m->param[i].flags & PARAMSTR) {  				str = (struct array){0};  				arrayaddbuf(&str, "\"", 1);  			} @@ -441,15 +449,15 @@ expand(struct token *t)  					case TLPAREN: ++paren; break;  					case TRPAREN: --paren; break;  					} -					if (m->param[i].stringize) +					if (m->param[i].flags & PARAMSTR)  						stringize(&str, t);  				} -				if (!expand(t)) { +				if (m->param[i].flags & PARAMTOK && !expand(t)) {  					arrayaddbuf(&tok, t, sizeof(*t));  					++arg[i].ntoken;  				}  			} -			if (m->param[i].stringize) { +			if (m->param[i].flags & PARAMSTR) {  				arrayaddbuf(&str, "\"", 2);  				arg[i].str = (struct token){  					.kind = TSTRINGLIT, @@ -460,10 +468,11 @@ expand(struct token *t)  		if (i < m->nparam)  			error(&t->loc, "not enough arguments for macro '%s'", m->name);  		tokencheck(t, TRPAREN, "after macro arguments"); -		t = tok.val; -		for (i = 0; i < m->nparam; ++i) { -			arg[i].token = t; -			t += arg[i].ntoken; +		for (i = 0, t = tok.val; i < m->nparam; ++i) { +			if (m->param[i].flags & PARAMTOK) { +				arg[i].token = t; +				t += arg[i].ntoken; +			}  		}  		m->arg = arg;  	} | 
