int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
-bool c_lex_string_translate = true; /* If we need to translate characters received. */
+
+/* If we need to translate characters received. This is tri-state:
+ 0 means use only the untranslated string; 1 means use only
+ the translated string; -1 means chain the translated string
+ to the untranslated one. */
+int c_lex_string_translate = 1;
static tree interpret_integer (const cpp_token *, unsigned int);
static tree interpret_float (const cpp_token *, unsigned int);
{
value = build_string (istr.len, (char *)istr.text);
free ((void *)istr.text);
+
+ if (c_lex_string_translate == -1)
+ {
+ if (!cpp_interpret_string_notranslate (parse_in, strs, count,
+ &istr, wide))
+ /* Assume that, if we managed to translate the string
+ above, then the untranslated parsing will always
+ succeed. */
+ abort ();
+
+ if (TREE_STRING_LENGTH (value) != (int)istr.len
+ || 0 != strncmp (TREE_STRING_POINTER (value), (char *)istr.text,
+ istr.len))
+ {
+ /* Arrange for us to return the untranslated string in
+ *valp, but to set up the C type of the translated
+ one. */
+ *valp = build_string (istr.len, (char *)istr.text);
+ valp = &TREE_CHAIN (*valp);
+ }
+ free ((void *)istr.text);
+ }
}
else
{
if ((token->type == CPP_STRING || token->type == CPP_WSTRING)
&& flag_const_strings)
{
- tree type;
+ if (c_lex_string_translate)
+ {
+ tree value = token->value;
+ tree type;
- /* Get the current type. It will be an ARRAY_TYPE. */
- type = TREE_TYPE (token->value);
- /* Use build_cplus_array_type to rebuild the array, thereby
- getting the right type. */
- type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
- /* Reset the type of the token. */
- TREE_TYPE (token->value) = type;
+ /* We might as well go ahead and release the chained
+ translated string such that we can reuse its memory. */
+ if (TREE_CHAIN (value))
+ value = TREE_CHAIN (token->value);
+
+ /* Get the current type. It will be an ARRAY_TYPE. */
+ type = TREE_TYPE (value);
+ /* Use build_cplus_array_type to rebuild the array, thereby
+ getting the right type. */
+ type = build_cplus_array_type (TREE_TYPE (type),
+ TYPE_DOMAIN (type));
+ /* Reset the type of the token. */
+ TREE_TYPE (value) = type;
+ }
}
return token;
{
unsigned paren_depth = 0;
unsigned brace_depth = 0;
+ int saved_c_lex_string_translate = c_lex_string_translate;
+ int result;
if (recovering && !or_comma && cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
return 0;
+ if (! recovering)
+ /* If we're looking ahead, keep both translated and untranslated
+ strings. */
+ c_lex_string_translate = -1;
+
while (true)
{
cp_token *token;
/* If we've run out of tokens, then there is no closing `)'. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
- return 0;
+ {
+ result = 0;
+ break;
+ }
token = cp_lexer_peek_token (parser->lexer);
/* This matches the processing in skip_to_end_of_statement. */
if (token->type == CPP_SEMICOLON && !brace_depth)
- return 0;
+ {
+ result = 0;
+ break;
+ }
if (token->type == CPP_OPEN_BRACE)
++brace_depth;
if (token->type == CPP_CLOSE_BRACE)
{
if (!brace_depth--)
- return 0;
+ {
+ result = 0;
+ break;
+ }
}
if (recovering && or_comma && token->type == CPP_COMMA
&& !brace_depth && !paren_depth)
- return -1;
+ {
+ result = -1;
+ break;
+ }
if (!brace_depth)
{
{
if (consume_paren)
cp_lexer_consume_token (parser->lexer);
- return 1;
+ {
+ result = 1;
+ break;
+ }
}
}
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
+
+ c_lex_string_translate = saved_c_lex_string_translate;
+ return result;
}
/* Consume tokens until we reach the end of the current statement.
boolean-literal */
case CPP_CHAR:
case CPP_WCHAR:
- case CPP_STRING:
- case CPP_WSTRING:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
return token->value;
+ case CPP_STRING:
+ case CPP_WSTRING:
+ token = cp_lexer_consume_token (parser->lexer);
+ if (TREE_CHAIN (token->value))
+ return TREE_CHAIN (token->value);
+ else
+ return token->value;
+
case CPP_OPEN_PAREN:
{
tree expr;
/* Set this here since we can be called after
pushing the linkage specification. */
- c_lex_string_translate = true;
+ c_lex_string_translate = 1;
/* Check for the `__extension__' keyword. */
if (cp_parser_extension_opt (parser, &saved_pedantic))
/* Don't translate the CPP_STRING in extern "C". */
if (token1.keyword == RID_EXTERN)
- c_lex_string_translate = false;
+ c_lex_string_translate = 0;
if (token1.type != CPP_EOF)
token2 = *cp_lexer_peek_nth_token (parser->lexer, 2);
- c_lex_string_translate = true;
+ c_lex_string_translate = 1;
/* If the next token is `extern' and the following token is a string
literal, then we have a linkage specification. */
/* Assume C++ linkage. */
linkage = get_identifier ("c++");
}
+ /* If the string is chained to another string, take the latter,
+ that's the untranslated string. */
+ else if (TREE_CHAIN (token->value))
+ linkage = get_identifier (TREE_STRING_POINTER (TREE_CHAIN (token->value)));
/* If it's a simple string constant, things are easier. */
else
linkage = get_identifier (TREE_STRING_POINTER (token->value));
/* Look for the opening `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
/* Look for the string. */
- c_lex_string_translate = false;
+ c_lex_string_translate = 0;
token = cp_parser_require (parser, CPP_STRING, "asm body");
if (!token)
goto finish;
assemble_asm (string);
finish:
- c_lex_string_translate = true;
+ c_lex_string_translate = 1;
}
/* Declarators [gram.dcl.decl] */
tree name;
cp_token *token;
- c_lex_string_translate = false;
-
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
/* Consume the `[' token. */
/* Look for the string-literal. */
token = cp_parser_require (parser, CPP_STRING, "string-literal");
string_literal = token ? token->value : error_mark_node;
- c_lex_string_translate = true;
+ c_lex_string_translate = 1;
/* Look for the `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
/* Parse the expression. */
expression = cp_parser_expression (parser);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- c_lex_string_translate = false;
+ c_lex_string_translate = 0;
/* Add this operand to the list. */
asm_operands = tree_cons (build_tree_list (name, string_literal),
expression,
{
tree attribute_list = NULL_TREE;
- c_lex_string_translate = false;
+ c_lex_string_translate = 0;
while (true)
{
cp_token *token;
/* Consume the comma and keep going. */
cp_lexer_consume_token (parser->lexer);
}
- c_lex_string_translate = true;
+ c_lex_string_translate = 1;
/* We built up the list in reverse order. */
return nreverse (attribute_list);
/* Add tokens to CACHE until a non-nested END token appears. */
static void
-cp_parser_cache_group (cp_parser *parser,
- cp_token_cache *cache,
- enum cpp_ttype end,
- unsigned depth)
+cp_parser_cache_group_1 (cp_parser *parser,
+ cp_token_cache *cache,
+ enum cpp_ttype end,
+ unsigned depth)
{
while (true)
{
/* See if it starts a new group. */
if (token->type == CPP_OPEN_BRACE)
{
- cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, depth + 1);
+ cp_parser_cache_group_1 (parser, cache, CPP_CLOSE_BRACE, depth + 1);
if (depth == 0)
return;
}
else if (token->type == CPP_OPEN_PAREN)
- cp_parser_cache_group (parser, cache, CPP_CLOSE_PAREN, depth + 1);
+ cp_parser_cache_group_1 (parser, cache, CPP_CLOSE_PAREN, depth + 1);
else if (token->type == end)
return;
}
}
+/* Convenient interface for cp_parser_cache_group_1 that makes sure we
+ preserve string tokens in both translated and untranslated
+ forms. */
+
+static void
+cp_parser_cache_group (cp_parser *parser,
+ cp_token_cache *cache,
+ enum cpp_ttype end,
+ unsigned depth)
+{
+ int saved_c_lex_string_translate;
+
+ saved_c_lex_string_translate = c_lex_string_translate;
+ c_lex_string_translate = -1;
+
+ cp_parser_cache_group_1 (parser, cache, end, depth);
+
+ c_lex_string_translate = saved_c_lex_string_translate;
+}
+
+
/* Begin parsing tentatively. We always save tokens while parsing
tentatively so that if the tentative parsing fails we can restore the
tokens. */