/* Two string-valued tokens can usually just be mashed
* together.
*
- * XXX: This isn't actually legitimate. Several things here
- * should result in a diagnostic since the result cannot be a
- * valid, single pre-processing token. For example, pasting
- * "123" and "abc" is not legal, but we don't catch that
- * here. */
+ * There are some exceptions here. Notably, if the first token
+ * is a string representing an integer, then the second token
+ * must also be a an integer and must begin with a digit.
+ */
if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
(other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
{
char *str;
+ if (token->type == INTEGER_STRING) {
+ if (other->type != INTEGER_STRING)
+ goto FAIL;
+ if (other->value.str[0] < '0' ||
+ other->value.str[0] > '9')
+ goto FAIL;
+ }
+
str = ralloc_asprintf (token, "%s%s", token->value.str,
other->value.str);
combined = _token_create_str (token, token->type, str);
return combined;
}
+ FAIL:
glcpp_error (&token->location, parser, "");
ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \"");
_token_print (&parser->info_log, &parser->info_log_length, token);
}
static token_list_t *
-_token_list_create_with_one_space (void *ctx)
+_token_list_create_with_one_ival (void *ctx, int type, int ival)
{
token_list_t *list;
- token_t *space;
+ token_t *node;
list = _token_list_create (ctx);
- space = _token_create_ival (list, SPACE, SPACE);
- _token_list_append (list, space);
+ node = _token_create_ival (list, type, ival);
+ _token_list_append (list, node);
return list;
}
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ return _token_list_create_with_one_ival (ctx, SPACE, SPACE);
+}
+
+static token_list_t *
+_token_list_create_with_one_integer (void *ctx, int ival)
+{
+ return _token_list_create_with_one_ival (ctx, INTEGER, ival);
+}
+
/* Perform macro expansion on 'list', placing the resulting tokens
* into a new list which is initialized with a first token of type
* 'head_token_type'. Then begin lexing from the resulting list,
/* Special handling for __LINE__ and __FILE__, (not through
* the hash table). */
- if (strcmp(identifier, "__LINE__") == 0) {
- token_list_t *replacement;
- token_t *value;
-
- replacement = _token_list_create (parser);
- value = _token_create_ival (parser, INTEGER,
- node->token->location.first_line);
- _token_list_append (replacement, value);
-
- return replacement;
- }
+ if (strcmp(identifier, "__LINE__") == 0)
+ return _token_list_create_with_one_integer (parser, node->token->location.first_line);
- if (strcmp(identifier, "__FILE__") == 0) {
- token_list_t *replacement;
- token_t *value;
-
- replacement = _token_list_create (parser);
- value = _token_create_ival (parser, INTEGER,
- node->token->location.source);
- _token_list_append (replacement, value);
-
- return replacement;
- }
+ if (strcmp(identifier, "__FILE__") == 0)
+ return _token_list_create_with_one_integer (parser, node->token->location.source);
/* Look up this identifier in the hash table. */
macro = hash_table_find (parser->defines, identifier);