const char *end;
struct callshape shape;
split_keywordspec (name, &end, &shape);
- if (split_keywordspec_ok (name, end - name))
- /* The characters between name and end should form a valid
- C identifier. */
+ if (split_keywordspec_ok2 (name, end - name))
+ /* The characters between name and end should form a valid C identifier
+ or (in C++) a qualified identifier, i.e. a sequence of names
+ connected by scope resolution operators '::'. */
insert_keyword_callshape (keywords, name, end - name, &shape);
}
}
token_type_rparen, /* ) */
token_type_comma, /* , */
token_type_colon, /* : */
+ token_type_scope, /* :: (C++ only) */
token_type_name, /* abc */
token_type_number, /* 2.7 */
token_type_string_literal, /* "abc" */
return;
case ':':
+ if (cxx_extensions)
+ {
+ c = phase4_getc ();
+ if (c == ':')
+ {
+ tp->type = token_type_scope;
+ return;
+ }
+ phase4_ungetc (c);
+ }
tp->type = token_type_colon;
return;
xgettext_token_type_rparen,
xgettext_token_type_comma,
xgettext_token_type_colon,
+ xgettext_token_type_scope,
xgettext_token_type_string_literal,
xgettext_token_type_other
};
/* 9. Convert the remaining preprocessing tokens to C tokens and
discards any white space from the translation unit. */
+static xgettext_token_ty phase9_pushback[2];
+static int phase9_pushback_length;
+
static void
x_c_lex (xgettext_token_ty *tp)
{
+ if (phase9_pushback_length)
+ {
+ *tp = phase9_pushback[--phase9_pushback_length];
+ return;
+ }
+
for (;;)
{
token_ty token;
tp->type = xgettext_token_type_colon;
return;
+ case token_type_scope:
+ last_non_comment_line = newline_count;
+
+ tp->type = xgettext_token_type_scope;
+ return;
+
case token_type_string_literal:
last_non_comment_line = newline_count;
}
}
+/* Supports 2 tokens of pushback. */
+static void
+x_c_unlex (xgettext_token_ty *tp)
+{
+ if (tp->type != xgettext_token_type_eof)
+ {
+ if (phase9_pushback_length == SIZEOF (phase9_pushback))
+ abort ();
+ phase9_pushback[phase9_pushback_length++] = *tp;
+ }
+}
+
/* ========================= Extracting strings. ========================== */
{
case xgettext_token_type_symbol:
{
- void *keyword_value;
- if (hash_find_entry (objc_extensions ? &objc_keywords : &c_keywords,
- token.string, strlen (token.string),
- &keyword_value)
- == 0)
+ /* Combine symbol1 :: ... :: symbolN to a single string, so that
+ we can recognize function calls with qualified names. The
+ information present for symbolI::...::symbolN has precedence
+ over the information for symbolJ::...::symbolN with J > I. */
+ char *sum = token.string;
+ size_t sum_len = strlen (sum);
+
+ for (;;)
{
- next_shapes = (const struct callshapes *) keyword_value;
- state = 1;
+ xgettext_token_ty token2;
+ x_c_lex (&token2);
+
+ if (token2.type == xgettext_token_type_scope)
+ {
+ xgettext_token_ty token3;
+ x_c_lex (&token3);
+
+ if (token3.type == xgettext_token_type_symbol)
+ {
+ char *addend = token3.string;
+ size_t addend_len = strlen (addend);
+
+ sum =
+ (char *) xrealloc (sum, sum_len + 2 + addend_len + 1);
+ memcpy (sum + sum_len, "::", 2);
+ memcpy (sum + sum_len + 2, addend, addend_len + 1);
+ sum_len += 2 + addend_len;
+
+ free (addend);
+ continue;
+ }
+ x_c_unlex (&token3);
+ }
+ x_c_unlex (&token2);
+ break;
}
- else
- state = 0;
- }
- next_context_iter =
- flag_context_list_iterator (
- flag_context_list_table_lookup (
- flag_context_list_table,
- token.string, strlen (token.string)));
- if (objc_extensions)
- {
- size_t token_string_len = strlen (token.string);
- token.string = xrealloc (token.string, token_string_len + 2);
- token.string[token_string_len] = ':';
- token.string[token_string_len + 1] = '\0';
- selectorcall_context_iter =
- flag_context_list_iterator (
+
+ for (const char *qualifiedname = sum;;)
+ {
+ void *keyword_value;
+ if (hash_find_entry (objc_extensions ? &objc_keywords : &c_keywords,
+ qualifiedname, strlen (qualifiedname),
+ &keyword_value)
+ == 0)
+ {
+ next_shapes = (const struct callshapes *) keyword_value;
+ state = 1;
+ break;
+ }
+
+ qualifiedname = strstr (qualifiedname, "::");
+ if (qualifiedname == NULL)
+ {
+ state = 0;
+ break;
+ }
+ qualifiedname += 2;
+ }
+
+ flag_context_list_ty *context_list;
+ for (const char *qualifiedname = sum;;)
+ {
+ context_list =
flag_context_list_table_lookup (
flag_context_list_table,
- token.string, token_string_len + 1));
- }
- free (token.string);
+ qualifiedname, strlen (qualifiedname));
+ if (context_list != NULL)
+ break;
+
+ qualifiedname = strstr (qualifiedname, "::");
+ if (qualifiedname == NULL)
+ break;
+ qualifiedname += 2;
+ }
+ next_context_iter = flag_context_list_iterator (context_list);
+
+ if (objc_extensions)
+ {
+ sum = xrealloc (sum, sum_len + 2);
+ sum[sum_len] = ':';
+ sum[sum_len + 1] = '\0';
+ selectorcall_context_iter =
+ flag_context_list_iterator (
+ flag_context_list_table_lookup (
+ flag_context_list_table,
+ sum, sum_len + 1));
+ }
+ free (sum);
+ }
break;
case xgettext_token_type_lparen: