/* xgettext C/C++/ObjectiveC backend.
- Copyright (C) 1995-1998, 2000-2009, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2009, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
/* Specification. */
#include "x-c.h"
+#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include "xalloc.h"
#include "xvasprintf.h"
#include "hash.h"
+#include "po-charset.h"
#include "gettext.h"
#define _(s) gettext(s)
add_keyword (name, &objc_keywords);
}
+static bool additional_keywords_kde;
+
+void
+activate_additional_keywords_kde ()
+{
+ additional_keywords_kde = true;
+}
+
/* Finish initializing the keywords hash tables.
Called after argument processing, before each file is processed. */
static void
x_c_keyword ("dnpgettext:2c,3,4");
x_c_keyword ("dcnpgettext:2c,3,4");
+ if (additional_keywords_kde)
+ {
+ x_c_keyword ("i18n:1");
+ x_c_keyword ("i18nc:1c,2");
+ x_c_keyword ("i18np:1,2");
+ x_c_keyword ("i18ncp:1c,2,3");
+ x_c_keyword ("i18nd:2");
+ x_c_keyword ("i18ndc:2c,3");
+ x_c_keyword ("i18ndp:2,3");
+ x_c_keyword ("i18ndcp:2c,3,4");
+ x_c_keyword ("ki18n:1");
+ x_c_keyword ("ki18nc:1c,2");
+ x_c_keyword ("ki18np:1,2");
+ x_c_keyword ("ki18ncp:1c,2,3");
+ x_c_keyword ("ki18nd:2");
+ x_c_keyword ("ki18ndc:2c,3");
+ x_c_keyword ("ki18ndp:2,3");
+ x_c_keyword ("ki18ndcp:2c,3,4");
+ x_c_keyword ("I18N_NOOP:1");
+ x_c_keyword ("I18NC_NOOP:1c,2");
+ x_c_keyword ("I18N_NOOP2:1c,2");
+ x_c_keyword ("I18N_NOOP2_NOSTRIP:1c,2");
+ x_c_keyword ("xi18n:1");
+ x_c_keyword ("xi18nc:1c,2");
+ x_c_keyword ("xi18np:1,2");
+ x_c_keyword ("xi18ncp:1c,2,3");
+ x_c_keyword ("xi18nd:2");
+ x_c_keyword ("xi18ndc:2c,3");
+ x_c_keyword ("xi18ndp:2,3");
+ x_c_keyword ("xi18ndcp:2c,3,4");
+ x_c_keyword ("kxi18n:1");
+ x_c_keyword ("kxi18nc:1c,2");
+ x_c_keyword ("kxi18np:1,2");
+ x_c_keyword ("kxi18ncp:1c,2,3");
+ x_c_keyword ("kxi18nd:2");
+ x_c_keyword ("kxi18ndc:2c,3");
+ x_c_keyword ("kxi18ndp:2,3");
+ x_c_keyword ("kxi18ndcp:2c,3,4");
+ x_c_keyword ("XI18N_NOOP:1");
+ x_c_keyword ("XI18NC_NOOP:1c,2");
+ x_c_keyword ("XI18N_NOOP2:1c,2");
+ x_c_keyword ("XI18N_NOOP2_NOSTRIP:1c,2");
+ }
+
x_objc_keyword ("gettext");
x_objc_keyword ("dgettext:2");
x_objc_keyword ("dcgettext:2");
#endif
}
+void
+init_flag_table_kde ()
+{
+ xgettext_record_flag ("i18n:1:kde-format");
+ xgettext_record_flag ("i18nc:2:kde-format");
+ xgettext_record_flag ("i18np:1:kde-format");
+ xgettext_record_flag ("i18ncp:2:kde-format");
+ xgettext_record_flag ("i18nd:2:kde-format");
+ xgettext_record_flag ("i18ndc:3:kde-format");
+ xgettext_record_flag ("i18ndp:2:kde-format");
+ xgettext_record_flag ("i18ndcp:3:kde-format");
+ xgettext_record_flag ("ki18n:1:kde-format");
+ xgettext_record_flag ("ki18nc:2:kde-format");
+ xgettext_record_flag ("ki18np:1:kde-format");
+ xgettext_record_flag ("ki18ncp:2:kde-format");
+ xgettext_record_flag ("ki18nd:2:kde-format");
+ xgettext_record_flag ("ki18ndc:3:kde-format");
+ xgettext_record_flag ("ki18ndp:2:kde-format");
+ xgettext_record_flag ("ki18ndcp:3:kde-format");
+ xgettext_record_flag ("I18N_NOOP:1:kde-format");
+ xgettext_record_flag ("I18NC_NOOP:2:kde-format");
+ xgettext_record_flag ("I18N_NOOP2:2:kde-format");
+ xgettext_record_flag ("I18N_NOOP2_NOSTRIP:2:kde-format");
+ xgettext_record_flag ("xi18n:1:kde-kuit-format");
+ xgettext_record_flag ("xi18nc:2:kde-kuit-format");
+ xgettext_record_flag ("xi18np:1:kde-kuit-format");
+ xgettext_record_flag ("xi18ncp:2:kde-kuit-format");
+ xgettext_record_flag ("xi18nd:2:kde-kuit-format");
+ xgettext_record_flag ("xi18ndc:3:kde-kuit-format");
+ xgettext_record_flag ("xi18ndp:2:kde-kuit-format");
+ xgettext_record_flag ("xi18ndcp:3:kde-kuit-format");
+ xgettext_record_flag ("kxi18n:1:kde-kuit-format");
+ xgettext_record_flag ("kxi18nc:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18np:1:kde-kuit-format");
+ xgettext_record_flag ("kxi18ncp:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18nd:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndc:3:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndp:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndcp:3:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP:1:kde-kuit-format");
+ xgettext_record_flag ("XI18NC_NOOP:2:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP2:2:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP2_NOSTRIP:2:kde-kuit-format");
+}
/* ======================== Reading of characters. ======================== */
/* True if ObjectiveC extensions are recognized. */
static bool objc_extensions;
+/* True if C++ extensions are recognized. */
+static bool cxx_extensions;
+
enum token_type_ty
{
token_type_character_constant, /* 'x' */
char *string; /* for token_type_name, token_type_string_literal */
refcounted_string_list_ty *comment; /* for token_type_string_literal,
token_type_objc_special */
+ enum literalstring_escape_type escape; /* for token_type_string_literal */
long number;
int line_number;
};
-/* 7. Replace escape sequences within character strings with their
- single character equivalents. This is called from phase 5, because
- we don't have to worry about the #include argument. There are
- pathological cases which could bite us (like the DOS directory
- separator), but just pretend it can't happen. */
+/* Free the memory pointed to by a 'struct token_ty'. */
+static inline void
+free_token (token_ty *tp)
+{
+ if (tp->type == token_type_name || tp->type == token_type_string_literal)
+ free (tp->string);
+ if (tp->type == token_type_string_literal
+ || tp->type == token_type_objc_special)
+ drop_reference (tp->comment);
+}
-#define P7_QUOTES (1000 + '"')
-#define P7_QUOTE (1000 + '\'')
-#define P7_NEWLINE (1000 + '\n')
-static int
-phase7_getc ()
+static char *
+literalstring_parse (const char *string, lex_pos_ty *pos,
+ enum literalstring_escape_type type)
{
- int c, n, j;
+ struct mixed_string_buffer *bp;
+ const char *p;
- /* Use phase 3, because phase 4 elides comments. */
- c = phase3_getc ();
+ /* Start accumulating the string. */
+ bp = mixed_string_buffer_alloc (lc_string,
+ logical_file_name,
+ line_number);
- /* Return a magic newline indicator, so that we can distinguish
- between the user requesting a newline in the string (e.g. using
- "\n" or "\012") from the user failing to terminate the string or
- character constant. The ANSI C standard says: 3.1.3.4 Character
- Constants contain "any character except single quote, backslash or
- newline; or an escape sequence" and 3.1.4 String Literals contain
- "any character except double quote, backslash or newline; or an
- escape sequence".
-
- Most compilers give a fatal error in this case, however gcc is
- stupidly silent, even though this is a very common typo. OK, so
- "gcc --pedantic" will tell me, but that gripes about too much other
- stuff. Could I have a "gcc -Wnewline-in-string" option, or
- better yet a "gcc -fno-newline-in-string" option, please? Gcc is
- also inconsistent between string literals and character constants:
- you may not embed newlines in character constants; try it, you get
- a useful diagnostic. --PMiller */
- if (c == '\n')
- return P7_NEWLINE;
-
- if (c == '"')
- return P7_QUOTES;
- if (c == '\'')
- return P7_QUOTE;
- if (c != '\\')
- return c;
- c = phase3_getc ();
- switch (c)
+ for (p = string; ; )
{
- default:
- /* Unknown escape sequences really should be an error, but just
- ignore them, and let the real compiler complain. */
- phase3_ungetc (c);
- return '\\';
-
- case '"':
- case '\'':
- case '?':
- case '\\':
- return c;
+ int c = *p++;
- case 'a':
- return '\a';
- case 'b':
- return '\b';
+ if (c == '\0')
+ break;
- /* The \e escape is preculiar to gcc, and assumes an ASCII
- character set (or superset). We don't provide support for it
- here. */
-
- case 'f':
- return '\f';
- case 'n':
- return '\n';
- case 'r':
- return '\r';
- case 't':
- return '\t';
- case 'v':
- return '\v';
-
- case 'x':
- c = phase3_getc ();
- switch (c)
+ if (c != '\\')
{
- default:
- phase3_ungetc (c);
- phase3_ungetc ('x');
- return '\\';
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- break;
+ mixed_string_buffer_append_char (bp, c);
+ continue;
}
- n = 0;
- for (;;)
+
+ if (!(type & LET_ANSI_C) && !(type & LET_UNICODE))
{
- switch (c)
- {
- default:
- phase3_ungetc (c);
- return n;
+ mixed_string_buffer_append_char (bp, '\\');
+ continue;
+ }
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = n * 16 + c - '0';
+ c = *p++;
+ if (c == '\0')
+ break;
+
+ if (type & LET_ANSI_C)
+ switch (c)
+ {
+ case '"':
+ case '\'':
+ case '?':
+ case '\\':
+ mixed_string_buffer_append_char (bp, c);
+ continue;
+
+ case 'a':
+ mixed_string_buffer_append_char (bp, '\a');
+ continue;
+ case 'b':
+ mixed_string_buffer_append_char (bp, '\b');
+ continue;
+
+ /* The \e escape is preculiar to gcc, and assumes an ASCII
+ character set (or superset). We don't provide support for it
+ here. */
+
+ case 'f':
+ mixed_string_buffer_append_char (bp, '\f');
+ continue;
+ case 'n':
+ mixed_string_buffer_append_char (bp, '\n');
+ continue;
+ case 'r':
+ mixed_string_buffer_append_char (bp, '\r');
+ continue;
+ case 't':
+ mixed_string_buffer_append_char (bp, '\t');
+ continue;
+ case 'v':
+ mixed_string_buffer_append_char (bp, '\v');
+ continue;
+
+ case 'x':
+ c = *p++;
+ if (c == '\0')
break;
+ switch (c)
+ {
+ default:
+ mixed_string_buffer_append_char (bp, '\\');
+ mixed_string_buffer_append_char (bp, 'x');
+ mixed_string_buffer_append_char (bp, c);
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ {
+ int n;
+
+ for (n = 0; ; c = *p++)
+ {
+ switch (c)
+ {
+ default:
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = n * 16 + c - '0';
+ continue;
+
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F':
+ n = n * 16 + 10 + c - 'A';
+ continue;
+
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f':
+ n = n * 16 + 10 + c - 'a';
+ continue;
+ }
+ break;
+ }
+
+ mixed_string_buffer_append_char (bp, n);
+ --p;
+ }
+ break;
+ }
+ continue;
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- n = n * 16 + 10 + c - 'A';
- break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ {
+ int n, j;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- n = n * 16 + 10 + c - 'a';
- break;
+ for (n = 0, j = 0; j < 3; ++j)
+ {
+ n = n * 8 + c - '0';
+ c = *p++;
+ switch (c)
+ {
+ default:
+ break;
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ continue;
+ }
+ break;
+ }
+
+ mixed_string_buffer_append_char (bp, n);
+ --p;
}
- c = phase3_getc ();
- }
- return n;
+ continue;
+ }
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- n = 0;
- for (j = 0; j < 3; ++j)
- {
- n = n * 8 + c - '0';
- c = phase3_getc ();
- switch (c)
+ if (type & LET_UNICODE)
+ switch (c)
+ {
+ case 'U': case 'u':
{
- default:
- break;
+ unsigned char buf[8];
+ int prefix = c;
+ int length = prefix == 'u' ? 4 : 8;
+ int n, j;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- continue;
- }
- break;
- }
- phase3_ungetc (c);
- return n;
- }
-}
+ for (n = 0, j = 0; j < length; j++)
+ {
+ c = *p++;
+
+ if (c >= '0' && c <= '9')
+ n = (n << 4) + (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ n = (n << 4) + (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ n = (n << 4) + (c - 'a' + 10);
+ else
+ break;
+
+ buf[j] = c;
+ }
+ if (j == length)
+ {
+ if (n < 0x110000)
+ mixed_string_buffer_append_unicode (bp, n);
+ else
+ {
+ error_with_progname = false;
+ error_at_line (0, 0,
+ pos->file_name, pos->line_number,
+ _("\
+warning: invalid Unicode character"));
+ error_with_progname = true;
+ }
+ }
+ else
+ {
+ int i;
-static void
-phase7_ungetc (int c)
-{
- phase3_ungetc (c);
-}
+ mixed_string_buffer_append_char (bp, '\\');
+ mixed_string_buffer_append_char (bp, prefix);
+ for (i = 0; i < j; i++)
+ mixed_string_buffer_append_char (bp, buf[i]);
-/* Free the memory pointed to by a 'struct token_ty'. */
-static inline void
-free_token (token_ty *tp)
-{
- if (tp->type == token_type_name || tp->type == token_type_string_literal)
- free (tp->string);
- if (tp->type == token_type_string_literal
- || tp->type == token_type_objc_special)
- drop_reference (tp->comment);
+ --p;
+ }
+ }
+ continue;
+ }
+
+ if (c == '\0')
+ break;
+
+ mixed_string_buffer_append_char (bp, c);
+ }
+
+ return mixed_string_buffer_done (bp);
}
+struct literalstring_parser literalstring_c =
+ {
+ literalstring_parse
+ };
+
/* 5. Parse each resulting logical line as preprocessing tokens and
white space. Preprocessing tokens and C tokens don't always match. */
static int bufmax;
int bufpos;
int c;
+ int last_was_backslash;
+ bool raw_expected = false;
+ int delimiter_left_end;
+ int delimiter_right_start;
+ int last_rparen;
if (phase5_pushback_length)
{
continue;
default:
+ /* Recognize string literals prefixed by R, u8, u8R, u,
+ uR, U, UR, L, or LR. It is defined in the C standard
+ ISO/IEC 9899:201x and the C++ standard ISO/IEC
+ 14882:2011. The raw string literals prefixed by R,
+ u8R, uR, UR, or LR are only valid in C++.
+
+ Since gettext's argument is a byte sequence, we are
+ only interested in u8, R, and u8R. */
+ if (c == '"')
+ {
+ bool is_prefix = false;
+
+ switch (buffer[0])
+ {
+ case 'R':
+ if (cxx_extensions && bufpos == 1)
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
+ break;
+ case 'u':
+ if (bufpos == 1)
+ is_prefix = true;
+ else
+ switch (buffer[1])
+ {
+ case 'R':
+ if (cxx_extensions && bufpos == 2)
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
+ break;
+ case '8':
+ if (bufpos == 2)
+ is_prefix = true;
+ else if (cxx_extensions
+ && bufpos == 3 && buffer[2] == 'R')
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
+ break;
+ }
+ break;
+ case 'U':
+ case 'L':
+ if (bufpos == 1)
+ is_prefix = true;
+ else if (cxx_extensions
+ && bufpos == 2 && buffer[1] == 'R')
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
+ break;
+ }
+
+ if (is_prefix)
+ goto string;
+ }
phase4_ungetc (c);
break;
}
but ignoring it has no effect unless one of the keywords is
"L". Just pretend it won't happen. Also, we don't need to
remember the character constant. */
+ last_was_backslash = false;
for (;;)
{
- c = phase7_getc ();
- if (c == P7_NEWLINE)
+ c = phase3_getc ();
+ if (last_was_backslash)
{
+ last_was_backslash = false;
+ continue;
+ }
+ switch (c)
+ {
+ case '\\':
+ last_was_backslash = true;
+ /* FALLTHROUGH */
+ default:
+ continue;
+ case '\n':
error_with_progname = false;
error (0, 0, _("%s:%d: warning: unterminated character constant"),
logical_file_name, line_number - 1);
error_with_progname = true;
- phase7_ungetc ('\n');
+ phase3_ungetc ('\n');
+ break;
+ case EOF: case '\'':
break;
}
- if (c == EOF || c == P7_QUOTE)
- break;
+ break;
}
tp->type = token_type_character_constant;
return;
case '"':
- /* We could worry about the 'L' before wide string constants,
- but since gettext's argument is not a wide character string,
- let the compiler complain about the argument not matching the
- prototype. Just pretend it won't happen. */
- bufpos = 0;
- for (;;)
- {
- c = phase7_getc ();
- if (c == P7_NEWLINE)
- {
- error_with_progname = false;
- error (0, 0, _("%s:%d: warning: unterminated string literal"),
- logical_file_name, line_number - 1);
- error_with_progname = true;
- phase7_ungetc ('\n');
- break;
- }
- if (c == EOF || c == P7_QUOTES)
+ {
+ string:
+ /* We could worry about the 'L' before wide string constants,
+ but since gettext's argument is not a wide character string,
+ let the compiler complain about the argument not matching the
+ prototype. Just pretend it won't happen. */
+ last_was_backslash = false;
+ delimiter_left_end = -1;
+ delimiter_right_start = -1;
+ last_rparen = -1;
+ bufpos = 0;
+ for (;;)
+ {
+ c = phase3_getc ();
+ if (last_was_backslash && !raw_expected)
+ {
+ last_was_backslash = false;
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = c;
+ continue;
+ }
+ switch (c)
+ {
+ case '\\':
+ last_was_backslash = true;
+ /* FALLTHROUGH */
+ default:
+ if (raw_expected)
+ {
+ if (c == '(' && delimiter_left_end < 0)
+ delimiter_left_end = bufpos;
+ else if (c == ')' && delimiter_left_end >= 0)
+ last_rparen = bufpos;
+ }
+ else if (c == '\n')
+ {
+ error_with_progname = false;
+ error (0, 0,
+ _("%s:%d: warning: unterminated string literal"),
+ logical_file_name, line_number - 1);
+ error_with_progname = true;
+ phase3_ungetc ('\n');
+ break;
+ }
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = c;
+ continue;
+
+ case '"':
+ if (raw_expected && delimiter_left_end >= 0)
+ {
+ if (last_rparen < 0
+ || delimiter_left_end != bufpos - (last_rparen + 1)
+ || strncmp (buffer, buffer + last_rparen + 1,
+ delimiter_left_end) != 0)
+ {
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = c;
+ continue;
+ }
+ delimiter_right_start = last_rparen;
+ }
+ break;
+
+ case EOF:
+ break;
+ }
break;
- if (c == P7_QUOTE)
- c = '\'';
- if (bufpos >= bufmax)
- {
- bufmax = 2 * bufmax + 10;
- buffer = xrealloc (buffer, bufmax);
- }
- buffer[bufpos++] = c;
- }
- if (bufpos >= bufmax)
- {
- bufmax = 2 * bufmax + 10;
- buffer = xrealloc (buffer, bufmax);
- }
- buffer[bufpos] = 0;
- tp->type = token_type_string_literal;
- tp->string = xstrdup (buffer);
- tp->comment = add_reference (savable_comment);
- return;
+ }
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos] = 0;
+
+ if (raw_expected)
+ {
+ if (delimiter_left_end < 0 || delimiter_right_start < 0)
+ {
+ error_with_progname = false;
+ error (0, 0, _("%s:%d: warning: unterminated string literal"),
+ logical_file_name, line_number - 1);
+ error_with_progname = true;
+ }
+ else
+ {
+ buffer[delimiter_right_start] = '\0';
+ tp->type = token_type_string_literal;
+ tp->string = xstrdup (&buffer[delimiter_left_end + 1]);
+ tp->escape = LET_NONE;
+ tp->comment = add_reference (savable_comment);
+ return;
+ }
+ }
+ tp->type = token_type_string_literal;
+ tp->string = xstrdup (buffer);
+ tp->escape = LET_ANSI_C | LET_UNICODE;
+ tp->comment = add_reference (savable_comment);
+ return;
+ }
case '(':
tp->type = token_type_lparen;
default:
/* We could carefully recognize each of the 2 and 3 character
- operators, but it is not necessary, as we only need to recognize
- gettext invocations. Don't bother. */
+ operators, but it is not necessary, as we only need to recognize
+ gettext invocations. Don't bother. */
tp->type = token_type_symbol;
return;
}
tp->string = new_string;
tp->comment = add_reference (savable_comment);
tp->type = token_type_string_literal;
+ tp->escape = LET_ANSI_C | LET_UNICODE;
}
}
/* 8. Concatenate adjacent string literals to form single string
literals (because we don't expand macros, there are a few things we
- will miss). */
+ will miss).
+
+ FIXME: handle the case when the string literals have different
+ tp->escape setting. */
static void
phase8_get (token_ty *tp)
char *string;
/* This field is used only for xgettext_token_type_string_literal. */
+ enum literalstring_escape_type escape;
+
+ /* This field is used only for xgettext_token_type_string_literal. */
refcounted_string_list_ty *comment;
/* These fields are only for
tp->type = xgettext_token_type_string_literal;
tp->string = token.string;
+ tp->escape = token.escape;
tp->comment = token.comment;
tp->pos.file_name = logical_file_name;
tp->pos.line_number = token.line_number;
case xgettext_token_type_string_literal:
if (extract_all)
- remember_a_message (mlp, NULL, token.string, inner_context,
- &token.pos, NULL, token.comment);
+ {
+ char *string;
+ refcounted_string_list_ty *comment;
+ const char *encoding;
+
+ string = literalstring_parse (token.string, &token.pos,
+ token.escape);
+ free (token.string);
+ token.string = string;
+
+ if (token.comment != NULL)
+ {
+ comment = savable_comment_convert_encoding (token.comment,
+ &token.pos);
+ drop_reference (token.comment);
+ token.comment = comment;
+ }
+
+ /* token.string and token.comment are already converted
+ to UTF-8. Prevent further conversion in
+ remember_a_message. */
+ encoding = xgettext_current_source_encoding;
+ xgettext_current_source_encoding = po_charset_utf8;
+ remember_a_message (mlp, NULL, token.string, inner_context,
+ &token.pos, NULL, token.comment);
+ xgettext_current_source_encoding = encoding;
+ }
else
- arglist_parser_remember (argparser, arg, token.string,
- inner_context,
- token.pos.file_name, token.pos.line_number,
- token.comment);
+ arglist_parser_remember_literal (argparser, arg, token.string,
+ inner_context,
+ token.pos.file_name,
+ token.pos.line_number,
+ token.comment,
+ token.escape);
drop_reference (token.comment);
next_context_iter = null_context_list_iterator;
selectorcall_context_iter = null_context_list_iterator;
msgdomain_list_ty *mdlp)
{
objc_extensions = false;
+ cxx_extensions = false;
+ extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
+}
+
+void
+extract_cxx (FILE *f,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ objc_extensions = false;
+ cxx_extensions = true;
extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
}
msgdomain_list_ty *mdlp)
{
objc_extensions = true;
+ cxx_extensions = false;
extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
}