summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2010-05-27 14:01:18 -0700
committerCarl Worth <cworth@cworth.org>2010-05-27 14:01:18 -0700
commit85b50e840d969c4d9ebcfcc3df1df7a95e07e34e (patch)
tree736074806acbf49198617c341187694aa320b607
parenta19297b26e971e5a9dbe00b4254931505da4b5a9 (diff)
Add placeholder tokens to support pasting with empty arguments.
Along with a passing test to verify that this works.
-rw-r--r--glcpp-parse.y36
-rw-r--r--tests/058-token-pasting-empty-arguments.c5
2 files changed, 35 insertions, 6 deletions
diff --git a/glcpp-parse.y b/glcpp-parse.y
index 3e0a965..d587a4b 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -132,7 +132,7 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
%parse-param {glcpp_parser_t *parser}
%lex-param {glcpp_parser_t *parser}
-%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF IDENTIFIER IF_EXPANDED INTEGER NEWLINE OTHER SPACE
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF IDENTIFIER IF_EXPANDED INTEGER NEWLINE OTHER PLACEHOLDER SPACE
%token PASTE
%type <ival> expression INTEGER operator SPACE
%type <str> IDENTIFIER OTHER
@@ -746,6 +746,9 @@ _token_print (token_t *token)
case COMMA_FINAL:
printf (",");
break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
default:
fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
break;
@@ -756,6 +759,17 @@ _token_print (token_t *token)
static void
_token_paste (token_t *token, token_t *other)
{
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return;
+
+ /* When 'token' is a placeholder, just return contents of 'other'. */
+ if (token->type == PLACEHOLDER) {
+ token->type = other->type;
+ token->value = other->value;
+ return;
+ }
+
/* A very few single-character punctuators can be combined
* with another to form a multi-character punctuator. */
switch (token->type) {
@@ -1159,10 +1173,20 @@ _expand_function_onto (glcpp_parser_t *parser,
argument = _argument_list_member_at (arguments,
parameter_index);
/* Before substituting, we expand the argument
- * tokens. */
- _glcpp_parser_expand_token_list_onto (parser,
- argument,
- substituted);
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ _glcpp_parser_expand_token_list_onto (parser,
+ argument,
+ substituted);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
} else {
_token_list_append (substituted, node->token);
}
@@ -1196,7 +1220,7 @@ _expand_function_onto (glcpp_parser_t *parser,
if (next_non_space == NULL) {
fprintf (stderr, "Error: '##' cannot appear at either end of a macro expansion\n");
- exit (1);
+ return FUNCTION_STATUS_SUCCESS;
}
_token_paste (node->token, next_non_space->token);
diff --git a/tests/058-token-pasting-empty-arguments.c b/tests/058-token-pasting-empty-arguments.c
new file mode 100644
index 0000000..8ac260c
--- /dev/null
+++ b/tests/058-token-pasting-empty-arguments.c
@@ -0,0 +1,5 @@
+#define paste(x,y) x ## y
+paste(a,b)
+paste(a,)
+paste(,b)
+paste(,)