return expansion;
}
/* processes a #define directive */
private Token parse_define() throws IOException, LexerException {
Token tok = source_token_nonwhite();
if (tok.getType() != IDENTIFIER) {
error(tok, "Expected identifier");
return source_skipline(false);
}
/* if predefined */
String name = tok.getText();
if ("defined".equals(name)) {
error(tok, "Cannot redefine name 'defined'");
return source_skipline(false);
}
MacroData m = new MacroData(getSource());
List<String> args;
tok = retrieveTokenFromSource();
if (tok.getType() == '(') {
tok = source_token_nonwhite();
boolean seenParamName = false;
if (tok.getType() != ')') {
args = new ArrayList<String>();
ARGS:
for (; ; ) {
switch (tok.getType()) {
case IDENTIFIER:
args.add(tok.getText());
seenParamName = true;
break;
case ELLIPSIS:
assert !seenParamName; // PG: let's check this.
if (!seenParamName) {
// This trick correctly implements the semantics of
// C99 variadic macros as described by the standard
// (6.3.10.1).
args.add("__VA_ARGS__");
}
tok = source_token_nonwhite();
if (tok.getType() != ')')
error(tok, "ellipsis must be on last argument");
m.setVariadic(true);
break ARGS;
case NL:
case EOF:
error(tok, "Unterminated macro parameter list");
return tok;
default:
error(tok, "error in macro parameters: "
+ getTextOrDefault(tok, "<Feature Expression>"));
return source_skipline(false);
}
tok = source_token_nonwhite();
switch (tok.getType()) {
case ',':
seenParamName = false;
break;
case ELLIPSIS:
assert seenParamName; // PG: verify if this is true
tok = source_token_nonwhite();
if (tok.getType() != ')')
error(tok, "ellipsis must be on last argument");
if (m.isVariadic()) {
error(tok, "ellipsis must not be repeated");
}
m.setVariadic(true);
break ARGS;
case ')':
break ARGS;
case NL:
case EOF:
/* Do not skip line. */
error(tok, "Unterminated macro parameters");
return tok;
default:
error(tok, "Bad token in macro parameters: "
+ getTextOrDefault(tok, "<Feature Expression>"));
return source_skipline(false);
}
tok = source_token_nonwhite();
}
} else {
assert tok.getType() == ')' : "Expected ')'";
args = Collections.emptyList();
}
m.setArgs(args);
} else {