/* xgettext AppData file backend.
- Copyright (C) 2002-2003, 2006, 2013, 2015-2017 Free Software Foundation,
- Inc.
+ Copyright (C) 2002-2003, 2006, 2013, 2015-2017 Free Software Foundation, Inc.
Written by Philip Withnall <philip.withnall@collabora.co.uk>, 2015.
This program is free software: you can redistribute it and/or modify
/* xgettext awk backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2014-2015, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_AWK \
{ "awk", extract_awk, \
- &flag_table_awk, &formatstring_awk, NULL, NULL }, \
+ &flag_table_awk, &formatstring_awk, NULL }, \
/* Scan an awk file and add its translatable strings to mdlp. */
extern void extract_awk (FILE *fp, const char *real_filename,
/* xgettext C/C++/ObjectiveC backend.
- Copyright (C) 1995-1998, 2000-2009, 2012, 2015-2016, 2018 Free Software
- Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2009, 2012-2015, 2018 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
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;
};
-/* 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);
-}
+/* 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. */
+/* Return value of phase7_getc when EOF is reached. */
+#define P7_EOF (-1)
+#define P7_STRING_END (-2)
-static char *
-literalstring_parse (const char *string, lex_pos_ty *pos,
- enum literalstring_escape_type type)
-{
- struct mixed_string_buffer *bp;
- const char *p;
+/* Replace escape sequences within character strings with their single
+ character equivalents. */
+#define P7_QUOTES (-3)
+#define P7_QUOTE (-4)
+#define P7_NEWLINE (-5)
- /* Start accumulating the string. */
- bp = mixed_string_buffer_alloc (lc_string,
- logical_file_name,
- line_number);
+/* Convert an UTF-16 or UTF-32 code point to a return value that can be
+ distinguished from a single-byte return value. */
+#define UNICODE(code) (0x100 + (code))
- for (p = string; ; )
- {
- int c = *p++;
+/* Test a return value of phase7_getuc whether it designates an UTF-16 or
+ UTF-32 code point. */
+#define IS_UNICODE(p7_result) ((p7_result) >= 0x100)
- if (c == '\0')
- break;
+/* Extract the UTF-16 or UTF-32 code of a return value that satisfies
+ IS_UNICODE. */
+#define UNICODE_VALUE(p7_result) ((p7_result) - 0x100)
- if (c != '\\')
- {
- mixed_string_buffer_append_char (bp, c);
- continue;
- }
- if (!(type & LET_ANSI_C) && !(type & LET_UNICODE))
- {
- mixed_string_buffer_append_char (bp, '\\');
- continue;
- }
+static int
+phase7_getc ()
+{
+ int c, n, j;
- c = *p++;
- if (c == '\0')
- break;
+ /* Use phase 3, because phase 4 elides comments. */
+ c = phase3_getc ();
- 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;
+ /* 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)
+ {
+ default:
+ /* Unknown escape sequences really should be an error, but just
+ ignore them, and let the real compiler complain. */
+ phase3_ungetc (c);
+ 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':
- {
- int n;
+ case '"':
+ case '\'':
+ case '?':
+ case '\\':
+ return c;
- 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;
- }
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
- mixed_string_buffer_append_char (bp, n);
- --p;
- }
- break;
- }
- 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 '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
+ 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)
+ {
+ 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;
+ }
+ n = 0;
+ for (;;)
+ {
+ switch (c)
{
- int n, j;
+ default:
+ phase3_ungetc (c);
+ return n;
- 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': case '8': case '9':
+ n = n * 16 + c - '0';
+ break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- continue;
- }
- break;
- }
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ n = n * 16 + 10 + c - 'A';
+ break;
- mixed_string_buffer_append_char (bp, n);
- --p;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ n = n * 16 + 10 + c - 'a';
+ break;
}
- continue;
- }
+ c = phase3_getc ();
+ }
+ return n;
- if (type & LET_UNICODE)
- switch (c)
- {
- case 'U': case 'u':
+ 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)
{
- unsigned char buf[8];
- int prefix = c;
- int length = prefix == 'u' ? 4 : 8;
- int n, j;
-
- 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;
- }
+ default:
+ break;
- 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;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ continue;
+ }
+ break;
+ }
+ phase3_ungetc (c);
+ return n;
- mixed_string_buffer_append_char (bp, '\\');
- mixed_string_buffer_append_char (bp, prefix);
+ case 'U': case 'u':
+ {
+ unsigned char buf[8];
- for (i = 0; i < j; i++)
- mixed_string_buffer_append_char (bp, buf[i]);
+ n = 0;
+ for (j = 0; j < (c == 'u' ? 4 : 8); j++)
+ {
+ int c1 = phase3_getc ();
+
+ if (c1 >= '0' && c1 <= '9')
+ n = (n << 4) + (c1 - '0');
+ else if (c1 >= 'A' && c1 <= 'F')
+ n = (n << 4) + (c1 - 'A' + 10);
+ else if (c1 >= 'a' && c1 <= 'f')
+ n = (n << 4) + (c1 - 'a' + 10);
+ else
+ {
+ phase3_ungetc (c1);
+ while (--j >= 0)
+ phase3_ungetc (buf[j]);
+ phase3_ungetc (c);
+ return '\\';
+ }
- --p;
- }
- }
- continue;
+ buf[j] = c1;
}
- if (c == '\0')
- break;
+ if (n < 0x110000)
+ return UNICODE (n);
+
+ error_with_progname = false;
+ error (0, 0, _("%s:%d: warning: invalid Unicode character"),
+ logical_file_name, line_number);
+ error_with_progname = true;
- mixed_string_buffer_append_char (bp, c);
+ while (--j >= 0)
+ phase3_ungetc (buf[j]);
+ phase3_ungetc (c);
+ return '\\';
+ }
}
+}
+
- return mixed_string_buffer_done (bp);
+static void
+phase7_ungetc (int c)
+{
+ phase3_ungetc (c);
}
-struct literalstring_parser literalstring_c =
- {
- literalstring_parse
- };
+
+/* 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);
+}
/* 5. Parse each resulting logical line as preprocessing tokens and
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 = phase3_getc ();
- if (last_was_backslash)
- {
- last_was_backslash = false;
- continue;
- }
- switch (c)
+ c = phase7_getc ();
+ if (c == P7_NEWLINE)
{
- 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;
- phase3_ungetc ('\n');
- break;
- case EOF: case '\'':
+ phase7_ungetc ('\n');
break;
}
- break;
+ if (c == EOF || c == P7_QUOTE)
+ break;
}
tp->type = token_type_character_constant;
return;
case '"':
{
- string:
+ struct mixed_string_buffer *bp;
+
+ /* Start accumulating the string. */
+ bp = mixed_string_buffer_alloc (lc_string,
+ logical_file_name,
+ line_number);
+
/* 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;
+ c = phase7_getc ();
- 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;
+ /* Keep line_number in sync. */
+ bp->line_number = line_number;
- case EOF:
- break;
- }
- break;
- }
- 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)
+ 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;
}
- else
+ if (c == EOF || c == P7_QUOTES)
+ break;
+ if (c == P7_QUOTE)
+ c = '\'';
+ if (IS_UNICODE (c))
{
- 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;
+ assert (UNICODE_VALUE (c) >= 0
+ && UNICODE_VALUE (c) < 0x110000);
+ mixed_string_buffer_append_unicode (bp,
+ UNICODE_VALUE (c));
}
+ else
+ mixed_string_buffer_append_char (bp, c);
}
tp->type = token_type_string_literal;
- tp->string = xstrdup (buffer);
- tp->escape = LET_ANSI_C | LET_UNICODE;
+ tp->string = mixed_string_buffer_done (bp);
tp->comment = add_reference (savable_comment);
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).
-
- FIXME: handle the case when the string literals have different
- tp->escape setting. */
+ will miss). */
static void
phase8_get (token_ty *tp)
xgettext_token_type_keyword, xgettext_token_type_symbol. */
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;
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;
arglist_parser_alloc (mlp,
state ? next_shapes : NULL)))
{
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding =
+ xgettext_global_source_encoding;
return true;
}
next_context_iter = null_context_list_iterator;
continue;
case xgettext_token_type_rparen:
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
return false;
case xgettext_token_type_comma:
continue;
case xgettext_token_type_string_literal:
+ xgettext_current_source_encoding = po_charset_utf8;
if (extract_all)
- {
- 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;
- }
+ remember_a_message (mlp, NULL, token.string, inner_context,
+ &token.pos, NULL, token.comment);
else
- arglist_parser_remember_literal (argparser, arg, token.string,
- inner_context,
- token.pos.file_name,
- token.pos.line_number,
- token.comment,
- token.escape);
+ arglist_parser_remember (argparser, arg, token.string,
+ inner_context,
+ token.pos.file_name, token.pos.line_number,
+ token.comment);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
drop_reference (token.comment);
next_context_iter = null_context_list_iterator;
selectorcall_context_iter = null_context_list_iterator;
continue;
case xgettext_token_type_eof:
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
return true;
default:
/* xgettext C/C++/ObjectiveC backend.
- Copyright (C) 2001-2003, 2006, 2009, 2015-2016 Free Software Foundation,
- Inc.
+ Copyright (C) 2001-2003, 2006, 2009, 2014-2015, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_C \
{ "C", extract_c, \
&flag_table_c, \
- &formatstring_c, NULL, \
- &literalstring_c }, \
+ &formatstring_c, NULL }, \
{ "C++", extract_cxx, \
&flag_table_c, \
- &formatstring_c, NULL, \
- &literalstring_c }, \
+ &formatstring_c, NULL }, \
{ "ObjectiveC", extract_objc, \
&flag_table_objc, \
- &formatstring_c, &formatstring_objc, \
- &literalstring_c }, \
+ &formatstring_c, &formatstring_objc }, \
{ "GCC-source", extract_c, \
&flag_table_gcc_internal, \
- &formatstring_gcc_internal, &formatstring_gfc_internal, \
- &literalstring_c }, \
+ &formatstring_gcc_internal, &formatstring_gfc_internal }, \
/* Scan a C file and add its translatable strings to mdlp. */
extern void extract_c (FILE *fp, const char *real_filename,
extern void init_flag_table_kde (void);
-extern struct literalstring_parser literalstring_c;
-
-
#ifdef __cplusplus
}
#endif
/* xgettext C# backend.
- Copyright (C) 2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_CSHARP \
{ "C#", extract_csharp, \
- &flag_table_csharp, &formatstring_csharp, NULL, NULL }, \
+ &flag_table_csharp, &formatstring_csharp, NULL }, \
extern void extract_csharp (FILE *fp, const char *real_filename,
const char *logical_filename,
/* xgettext Desktop Entry backend.
- Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ Copyright (C) 2014, 2018 Free Software Foundation, Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2014.
This program is free software: you can redistribute it and/or modify
{ "desktop", "Desktop" }, \
#define SCANNERS_DESKTOP \
- { "Desktop", extract_desktop, NULL, NULL, NULL, NULL }, \
+ { "Desktop", extract_desktop, NULL, NULL, NULL }, \
/* Scan a Desktop Entry file and add its translatable strings to mdlp. */
extern void extract_desktop (FILE *fp, const char *real_filename,
/* xgettext Emacs Lisp backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_ELISP \
{ "EmacsLisp", extract_elisp, \
- &flag_table_elisp, &formatstring_elisp, NULL, NULL }, \
+ &flag_table_elisp, &formatstring_elisp, NULL }, \
/* Scan an Emacs Lisp file and add its translatable strings to mdlp. */
extern void extract_elisp (FILE *fp, const char *real_filename,
/* xgettext glade backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2013-2015, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
{ "ui", NULL }, \
#define SCANNERS_GLADE \
- { "glade", NULL, NULL, NULL, NULL, NULL }, \
+ { "glade", NULL, NULL, NULL, NULL }, \
#ifdef __cplusplus
/* xgettext GSettings schema file backend.
- Copyright (C) 2002-2003, 2006, 2013, 2015-2016 Free Software Foundation,
- Inc.
+ Copyright (C) 2002-2003, 2006, 2013-2015, 2018 Free Software Foundation, Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2013.
This program is free software: you can redistribute it and/or modify
{ "gschema.xml", NULL }, \
#define SCANNERS_GSETTINGS \
- { "gsettings", NULL, NULL, NULL, NULL, NULL }, \
+ { "gsettings", NULL, NULL, NULL, NULL }, \
#ifdef __cplusplus
/* xgettext Java backend.
- Copyright (C) 2001-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Tommy Johansson <tommy.johansson@kanalen.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_JAVA \
{ "Java", extract_java, \
- &flag_table_java, &formatstring_java, NULL, NULL }, \
+ &flag_table_java, &formatstring_java, NULL }, \
extern void extract_java (FILE *fp, const char *real_filename,
const char *logical_filename,
/* xgettext JavaScript backend.
- Copyright (C) 2002-2003, 2006, 2013, 2015-2016 Free Software Foundation,
- Inc.
+ Copyright (C) 2002-2003, 2006, 2010, 2013-2014, 2018 Free Software Foundation, Inc.
This file was written by Andreas Stricker <andy@knitter.ch>, 2010.
It's based on x-python from Bruno Haible.
#define SCANNERS_JAVASCRIPT \
{ "JavaScript", extract_javascript, \
- &flag_table_javascript, &formatstring_javascript, NULL, NULL }, \
+ &flag_table_javascript, &formatstring_javascript, NULL }, \
/* Scan a Python file and add its translatable strings to mdlp. */
extern void extract_javascript (FILE *fp, const char *real_filename,
/* xgettext librep backend.
- Copyright (C) 2001-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_LIBREP \
{ "librep", extract_librep, \
- &flag_table_librep, &formatstring_librep, NULL, NULL }, \
+ &flag_table_librep, &formatstring_librep, NULL }, \
/* Scan a librep file and add its translatable strings to mdlp. */
extern void extract_librep (FILE *fp, const char *real_filename,
/* xgettext Lisp backend.
- Copyright (C) 2001-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_LISP \
{ "Lisp", extract_lisp, \
- &flag_table_lisp, &formatstring_lisp, NULL, NULL }, \
+ &flag_table_lisp, &formatstring_lisp, NULL }, \
/* Scan a Lisp file and add its translatable strings to mdlp. */
extern void extract_lisp (FILE *fp, const char *real_filename,
/* xgettext Lua backend.
- Copyright (C) 2011, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2011-2014, 2018 Free Software Foundation, Inc.
Written by ĽubomÃr Remák <lubomirrk@lubomirr.eu>, 2011
This program is free software: you can redistribute it and/or modify
#define SCANNERS_LUA \
{ "Lua", extract_lua, \
- &flag_table_lua, &formatstring_lua, NULL, NULL }, \
+ &flag_table_lua, &formatstring_lua, NULL }, \
/* Scan a Lua file and add its translatable strings to mdlp. */
extern void extract_lua (FILE * fp, const char *real_filename,
/* xgettext Perl backend.
- Copyright (C) 2002-2003, 2006, 2010, 2015-2016 Free Software Foundation,
- Inc.
+ Copyright (C) 2002-2003, 2006, 2010, 2014, 2018 Free Software Foundation, Inc.
Written by Guido Flohr <guido@imperia.net>, 2002-2003
This program is free software: you can redistribute it and/or modify
#define SCANNERS_PERL \
{ "perl", extract_perl, \
- &flag_table_perl, &formatstring_perl, &formatstring_perl_brace, NULL }, \
+ &flag_table_perl, &formatstring_perl, &formatstring_perl_brace }, \
/* Scan a Perl file and add its translatable strings to mdlp. */
extern void extract_perl (FILE *fp, const char *real_filename,
/* xgettext PHP backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_PHP \
{ "PHP", extract_php, \
- &flag_table_php, &formatstring_php, NULL, NULL }, \
+ &flag_table_php, &formatstring_php, NULL }, \
/* Scan a PHP file and add its translatable strings to mdlp. */
extern void extract_php (FILE *fp, const char *real_filename,
/* xgettext PO backend.
- Copyright (C) 2001-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
{ "pot", "PO" }, \
#define SCANNERS_PO \
- { "PO", extract_po, NULL, NULL, NULL, NULL }, \
+ { "PO", extract_po, NULL, NULL, NULL }, \
/* Scan a PO file and add its translatable strings to mdlp. */
extern void extract_po (FILE *fp, const char *real_filename,
/* xgettext JavaProperties backend.
- Copyright (C) 2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
{ "properties", "JavaProperties" }, \
#define SCANNERS_PROPERTIES \
- { "JavaProperties", extract_properties, NULL, NULL, NULL, NULL }, \
+ { "JavaProperties", extract_properties, NULL, NULL, NULL }, \
/* Scan a JavaProperties file and add its translatable strings to mdlp. */
extern void extract_properties (FILE *fp, const char *real_filename,
/* xgettext Python backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2013-2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_PYTHON \
{ "Python", extract_python, \
- &flag_table_python, &formatstring_python, &formatstring_python_brace, NULL }, \
+ &flag_table_python, &formatstring_python, &formatstring_python_brace }, \
/* Scan a Python file and add its translatable strings to mdlp. */
extern void extract_python (FILE *fp, const char *real_filename,
/* xgettext RST/RSJ backend.
- Copyright (C) 2001-2003, 2006, 2015-2016, 2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_RST \
{ "RST", extract_rst, \
- NULL, &formatstring_pascal, NULL, NULL }, \
+ NULL, &formatstring_pascal, NULL }, \
{ "RSJ", extract_rsj, \
- NULL, &formatstring_pascal, NULL, NULL }, \
+ NULL, &formatstring_pascal, NULL }, \
/* Scan an RST file and add its translatable strings to mdlp. */
extern void extract_rst (FILE *fp, const char *real_filename,
/* xgettext Scheme backend.
- Copyright (C) 2004, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2004.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_SCHEME \
{ "Scheme", extract_scheme, \
- &flag_table_scheme, &formatstring_scheme, NULL, NULL }, \
+ &flag_table_scheme, &formatstring_scheme, NULL }, \
/* Scan a Scheme file and add its translatable strings to mdlp. */
extern void extract_scheme (FILE *fp, const char *real_filename,
/* xgettext sh backend.
- Copyright (C) 2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_SH \
{ "Shell", extract_sh, \
- &flag_table_sh, &formatstring_sh, NULL, NULL }, \
+ &flag_table_sh, &formatstring_sh, NULL }, \
/* Scan a shell script file and add its translatable strings to mdlp. */
extern void extract_sh (FILE *fp, const char *real_filename,
/* xgettext Smalltalk backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_SMALLTALK \
{ "Smalltalk", extract_smalltalk, \
- NULL, &formatstring_smalltalk, NULL, NULL }, \
+ NULL, &formatstring_smalltalk, NULL }, \
/* Scan a Smalltalk file and add its translatable strings to mdlp. */
extern void extract_smalltalk (FILE *fp, const char *real_filename,
/* xgettext NXStringTable backend.
- Copyright (C) 2003, 2006, 2015-2016, 2018 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
{ "strings", "NXStringTable" }, \
#define SCANNERS_STRINGTABLE \
- { "NXStringTable", extract_stringtable, NULL, NULL, NULL, NULL }, \
+ { "NXStringTable", extract_stringtable, NULL, NULL, NULL }, \
/* Scan an NXStringTable file and add its translatable strings to mdlp. */
extern void extract_stringtable (FILE *fp, const char *real_filename,
/* xgettext Tcl Lisp backend.
- Copyright (C) 2002-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_TCL \
{ "Tcl", extract_tcl, \
- &flag_table_tcl, &formatstring_tcl, NULL, NULL }, \
+ &flag_table_tcl, &formatstring_tcl, NULL }, \
/* Scan a Tcl file and add its translatable strings to mdlp. */
extern void extract_tcl (FILE *fp, const char *real_filename,
/* xgettext Vala backend.
- Copyright (C) 2013, 2015-2018 Free Software Foundation, Inc.
+ Copyright (C) 2013-2014, 2018 Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>, 2013.
token_type_ty type;
char *string; /* for token_type_symbol, token_type_string_literal */
refcounted_string_list_ty *comment; /* for token_type_string_literal */
- enum literalstring_escape_type escape;
int line_number;
};
}
+/* Return value of phase7_getc when EOF is reached. */
+#define P7_EOF (-1)
+#define P7_STRING_END (-2)
+
+/* Replace escape sequences within character strings with their single
+ character equivalents. */
+#define P7_QUOTES (-3)
+#define P7_QUOTE (-4)
+#define P7_NEWLINE (-5)
+
+/* Convert an UTF-16 or UTF-32 code point to a return value that can be
+ distinguished from a single-byte return value. */
+#define UNICODE(code) (0x100 + (code))
+
+/* Test a return value of phase7_getuc whether it designates an UTF-16 or
+ UTF-32 code point. */
+#define IS_UNICODE(p7_result) ((p7_result) >= 0x100)
+
+/* Extract the UTF-16 or UTF-32 code of a return value that satisfies
+ IS_UNICODE. */
+#define UNICODE_VALUE(p7_result) ((p7_result) - 0x100)
+
+
+static int
+phase7_getc ()
+{
+ int c, n, j;
+
+ /* Use phase 1, because phase 2 elides comments. */
+ c = phase1_getc ();
+
+ /* 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 = phase1_getc ();
+ switch (c)
+ {
+ default:
+ /* Unknown escape sequences really should be an error, but just
+ ignore them, and let the real compiler complain. */
+ phase1_ungetc (c);
+ return '\\';
+
+ case '"':
+ case '\'':
+ case '?':
+ case '\\':
+ return c;
+
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+
+ /* 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 = phase1_getc ();
+ switch (c)
+ {
+ default:
+ phase1_ungetc (c);
+ phase1_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;
+ }
+ n = 0;
+ for (;;)
+ {
+ switch (c)
+ {
+ default:
+ phase1_ungetc (c);
+ return n;
+
+ 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';
+ break;
+
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ n = n * 16 + 10 + c - 'A';
+ break;
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ n = n * 16 + 10 + c - 'a';
+ break;
+ }
+ c = phase1_getc ();
+ }
+ return n;
+
+ 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 = phase1_getc ();
+ switch (c)
+ {
+ default:
+ break;
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ continue;
+ }
+ break;
+ }
+ phase1_ungetc (c);
+ return n;
+
+ case 'U': case 'u':
+ {
+ unsigned char buf[8];
+
+ n = 0;
+ for (j = 0; j < (c == 'u' ? 4 : 8); j++)
+ {
+ int c1 = phase1_getc ();
+
+ if (c1 >= '0' && c1 <= '9')
+ n = (n << 4) + (c1 - '0');
+ else if (c1 >= 'A' && c1 <= 'F')
+ n = (n << 4) + (c1 - 'A' + 10);
+ else if (c1 >= 'a' && c1 <= 'f')
+ n = (n << 4) + (c1 - 'a' + 10);
+ else
+ {
+ phase1_ungetc (c1);
+ while (--j >= 0)
+ phase1_ungetc (buf[j]);
+ phase1_ungetc (c);
+ return '\\';
+ }
+
+ buf[j] = c1;
+ }
+
+ if (n < 0x110000)
+ return UNICODE (n);
+
+ error_with_progname = false;
+ error (0, 0, _("%s:%d: warning: invalid Unicode character"),
+ logical_file_name, line_number);
+ error_with_progname = true;
+
+ while (--j >= 0)
+ phase1_ungetc (buf[j]);
+ phase1_ungetc (c);
+ return '\\';
+ }
+ }
+}
+
+
+static void
+phase7_ungetc (int c)
+{
+ phase1_ungetc (c);
+}
+
+
/* 3. Parse each resulting logical line as preprocessing tokens and
white space. Preprocessing tokens and Vala tokens don't always
match. */
static char *buffer;
static int bufmax;
int bufpos;
- int last_was_backslash;
#undef APPEND
#define APPEND(c) \
return;
case '\'':
- last_was_backslash = false;
for (;;)
{
- c = phase2_getc ();
- if (last_was_backslash)
+ c = phase7_getc ();
+ if (c == P7_NEWLINE)
{
- 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;
- phase2_ungetc ('\n');
- break;
- case EOF: case '\'':
+ phase7_ungetc ('\n');
break;
}
- break;
+ if (c == EOF || c == P7_QUOTE)
+ break;
}
tp->type = last_token_type = token_type_character_constant;
return;
"""...""" (where ... can include newlines and double quotes)
String templates.
@"...", @"""..."""
-
+
Note that, with the current implementation string
templates are not subject to translation, because they are
inspected at compile time. For example, the following code
/* FALLTHROUGH */
case '"':
{
- int c2 = phase2_getc ();
+ struct mixed_string_buffer *bp;
+ int c2 = phase1_getc ();
if (c2 == '"')
{
- int c3 = phase2_getc ();
+ int c3 = phase1_getc ();
if (c3 == '"')
verbatim = true;
else
{
- phase2_ungetc (c3);
- phase2_ungetc (c2);
+ phase1_ungetc (c3);
+ phase1_ungetc (c2);
}
}
else
phase2_ungetc (c2);
+ /* Start accumulating the string. */
+ bp = mixed_string_buffer_alloc (lc_string,
+ logical_file_name,
+ line_number);
if (verbatim)
- {
- bufpos = 0;
- for (;;)
- {
- /* Use phase 1, because phase 2 elides comments. */
- c = phase1_getc ();
- if (c == EOF)
- break;
+ for (;;)
+ {
+ c = phase1_getc ();
- if (c == '"')
- {
- int c2 = phase1_getc ();
- if (c2 == '"')
- {
- int c3 = phase1_getc ();
- if (c3 == '"')
- break;
- phase1_ungetc (c3);
- }
- phase1_ungetc (c2);
- }
- APPEND (c);
- }
- }
+ /* Keep line_number in sync. */
+ bp->line_number = line_number;
+
+ if (c == '"')
+ {
+ int c2 = phase1_getc ();
+ if (c2 == '"')
+ {
+ int c3 = phase1_getc ();
+ if (c3 == '"')
+ break;
+ phase1_ungetc (c3);
+ }
+ phase1_ungetc (c2);
+ }
+ if (c == EOF)
+ break;
+ mixed_string_buffer_append_char (bp, c);
+ }
else
- {
- last_was_backslash = false;
- bufpos = 0;
- for (;;)
- {
- c = phase1_getc ();
- if (last_was_backslash)
- {
- last_was_backslash = false;
- APPEND (c);
- continue;
- }
-
- switch (c)
- {
- case '\\':
- last_was_backslash = true;
- /* FALLTHROUGH */
- default:
- APPEND (c);
- continue;
-
- case '\n':
- error_with_progname = false;
- error (0, 0, _("\
+ for (;;)
+ {
+ c = phase7_getc ();
+
+ /* Keep line_number in sync. */
+ bp->line_number = line_number;
+
+ 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;
- phase1_ungetc ('\n');
- break;
- case EOF: case '"':
- break;
- }
+ logical_file_name, line_number - 1);
+ error_with_progname = true;
+ phase7_ungetc ('\n');
+ break;
+ }
+ if (c == P7_QUOTES)
break;
- }
- }
- APPEND (0);
- tp->type = last_token_type = template
- ? token_type_string_template : token_type_string_literal;
- tp->string = xstrdup (buffer);
+ if (c == EOF)
+ break;
+ if (c == P7_QUOTE)
+ c = '\'';
+ if (IS_UNICODE (c))
+ {
+ assert (UNICODE_VALUE (c) >= 0
+ && UNICODE_VALUE (c) < 0x110000);
+ mixed_string_buffer_append_unicode (bp,
+ UNICODE_VALUE (c));
+ }
+ else
+ mixed_string_buffer_append_char (bp, c);
+ }
+ /* Done accumulating the string. */
+ tp->type = last_token_type =
+ template ? token_type_string_template : token_type_string_literal;
+ tp->string = mixed_string_buffer_done (bp);
tp->comment = add_reference (savable_comment);
- tp->escape = verbatim ? 0 : LET_ANSI_C | LET_UNICODE;
return;
}
}
return;
}
-
+
case '>':
case '<':
{
}
return;
}
-
+
case ',':
tp->type = last_token_type = token_type_comma;
return;
/* Context lookup table. */
static flag_context_list_table_ty *flag_context_list_table;
-/* Use the same literalstring_parser provided by the C scanner. */
-extern struct literalstring_parser literalstring_c;
/* The file is broken into tokens. Scan the token stream, looking for
a keyword, followed by a left paren, followed by a string. When we
arglist_parser_alloc (mlp,
state ? next_shapes : NULL)))
{
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
return true;
}
next_context_iter = null_context_list_iterator;
case token_type_rparen:
if (delim == token_type_rparen || delim == token_type_eof)
{
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
return false;
}
continue;
case token_type_eof:
+ xgettext_current_source_encoding = po_charset_utf8;
arglist_parser_done (argparser, arg);
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
return true;
case token_type_string_literal:
pos.file_name = logical_file_name;
pos.line_number = token.line_number;
+ xgettext_current_source_encoding = po_charset_utf8;
if (extract_all)
- {
- char *string;
- refcounted_string_list_ty *comment;
- const char *encoding;
-
- string = literalstring_c.parse (token.string, &pos,
- token.escape);
- free (token.string);
- token.string = string;
-
- if (token.comment != NULL)
- {
- comment = savable_comment_convert_encoding (token.comment,
- &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,
- &pos, NULL, token.comment);
- xgettext_current_source_encoding = encoding;
- }
+ remember_a_message (mlp, NULL, token.string, inner_context,
+ &pos, NULL, token.comment);
else
{
- /* A string immediately after a symbol means a
- function call. */
+ /* A string immediately after a symbol means a function call. */
if (state)
{
struct arglist_parser *tmp_argparser;
tmp_argparser = arglist_parser_alloc (mlp, next_shapes);
- arglist_parser_remember_literal (tmp_argparser, 1,
- token.string,
- inner_context,
- pos.file_name,
- pos.line_number,
- token.comment,
- token.escape);
+ arglist_parser_remember (tmp_argparser, 1, token.string,
+ inner_context, pos.file_name,
+ pos.line_number, token.comment);
arglist_parser_done (tmp_argparser, 1);
}
else
- arglist_parser_remember_literal (argparser, arg, token.string,
- inner_context, pos.file_name,
- pos.line_number,
- token.comment,
- token.escape);
+ arglist_parser_remember (argparser, arg, token.string,
+ inner_context, pos.file_name,
+ pos.line_number, token.comment);
}
+ xgettext_current_source_encoding = xgettext_global_source_encoding;
}
drop_reference (token.comment);
next_context_iter = null_context_list_iterator;
/* xgettext Vala backend.
- Copyright (C) 2002-2003, 2006, 2013, 2015-2016 Free Software Foundation,
- Inc.
+ Copyright (C) 2002-2003, 2006, 2013-2014, 2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{ "vala", "Vala" }, \
#define SCANNERS_VALA \
- { "Vala", extract_vala, \
- &flag_table_vala, &formatstring_c, NULL, &literalstring_c }, \
+ { "Vala", extract_vala, \
+ &flag_table_vala, &formatstring_c, NULL }, \
/* Scan a Vala file and add its translatable strings to mdlp. */
extern void extract_vala (FILE *fp, const char *real_filename,
/* xgettext YCP backend.
- Copyright (C) 2001-2003, 2006, 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2014, 2018 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
#define SCANNERS_YCP \
{ "YCP", extract_ycp, \
- &flag_table_ycp, &formatstring_ycp, NULL, NULL }, \
+ &flag_table_ycp, &formatstring_ycp, NULL }, \
/* Scan an YCP file and add its translatable strings to mdlp. */
extern void extract_ycp (FILE *fp, const char *real_filename,
struct formatstring_parser *formatstring_parser1;
struct formatstring_parser *formatstring_parser2;
struct formatstring_parser *formatstring_parser3;
- struct literalstring_parser *literalstring_parser;
};
}
}
-refcounted_string_list_ty *
-savable_comment_convert_encoding (refcounted_string_list_ty *comment,
- lex_pos_ty *pos)
-{
- refcounted_string_list_ty *result;
- size_t i;
-
- result = XMALLOC (refcounted_string_list_ty);
- result->refcount = 1;
- string_list_init (&result->contents);
-
- for (i = 0; i < comment->contents.nitems; i++)
- {
- const char *old_string = comment->contents.item[i];
- char *string = from_current_source_encoding (old_string,
- lc_comment,
- pos->file_name,
- pos->line_number);
- string_list_append (&result->contents, string);
- if (string != old_string)
- free (string);
- }
-
- return result;
-}
-
static FILE *
static struct formatstring_parser *current_formatstring_parser2;
static struct formatstring_parser *current_formatstring_parser3;
-static struct literalstring_parser *current_literalstring_parser;
static void
extract_from_file (const char *file_name, extractor_ty extractor,
current_formatstring_parser1 = extractor.formatstring_parser1;
current_formatstring_parser2 = extractor.formatstring_parser2;
current_formatstring_parser3 = extractor.formatstring_parser3;
- current_literalstring_parser = extractor.literalstring_parser;
extractor.func (fp, real_file_name, logical_file_name, extractor.flag_table,
mdlp);
ap->alternative[i].argtotal = shapes->shapes[i].argtotal;
ap->alternative[i].xcomments = shapes->shapes[i].xcomments;
ap->alternative[i].msgctxt = NULL;
- ap->alternative[i].msgctxt_escape = LET_NONE;
ap->alternative[i].msgctxt_pos.file_name = NULL;
ap->alternative[i].msgctxt_pos.line_number = (size_t)(-1);
ap->alternative[i].msgid = NULL;
- ap->alternative[i].msgid_escape = LET_NONE;
ap->alternative[i].msgid_context = null_context;
ap->alternative[i].msgid_pos.file_name = NULL;
ap->alternative[i].msgid_pos.line_number = (size_t)(-1);
ap->alternative[i].msgid_comment = NULL;
ap->alternative[i].msgid_plural = NULL;
- ap->alternative[i].msgid_plural_escape = LET_NONE;
ap->alternative[i].msgid_plural_context = null_context;
ap->alternative[i].msgid_plural_pos.file_name = NULL;
ap->alternative[i].msgid_plural_pos.line_number = (size_t)(-1);
ccp->argtotal = cp->argtotal;
ccp->xcomments = cp->xcomments;
ccp->msgctxt = (cp->msgctxt != NULL ? xstrdup (cp->msgctxt) : NULL);
- ccp->msgctxt_escape = cp->msgctxt_escape;
ccp->msgctxt_pos = cp->msgctxt_pos;
ccp->msgid = (cp->msgid != NULL ? xstrdup (cp->msgid) : NULL);
- ccp->msgid_escape = cp->msgid_escape;
ccp->msgid_context = cp->msgid_context;
ccp->msgid_pos = cp->msgctxt_pos;
ccp->msgid_comment = add_reference (cp->msgid_comment);
ccp->msgid_plural =
(cp->msgid_plural != NULL ? xstrdup (cp->msgid_plural) : NULL);
- ccp->msgid_plural_escape = cp->msgid_plural_escape;
ccp->msgid_plural_context = cp->msgid_plural_context;
ccp->msgid_plural_pos = cp->msgid_plural_pos;
}
void
-arglist_parser_remember_literal (struct arglist_parser *ap,
- int argnum, char *string,
- flag_context_ty context,
- char *file_name, size_t line_number,
- refcounted_string_list_ty *comment,
- enum literalstring_escape_type type)
+arglist_parser_remember (struct arglist_parser *ap,
+ int argnum, char *string,
+ flag_context_ty context,
+ char *file_name, size_t line_number,
+ refcounted_string_list_ty *comment)
{
bool stored_string = false;
size_t nalternatives = ap->nalternatives;
if (argnum == cp->argnumc)
{
cp->msgctxt = string;
- cp->msgctxt_escape = type;
cp->msgctxt_pos.file_name = file_name;
cp->msgctxt_pos.line_number = line_number;
stored_string = true;
if (argnum == cp->argnum1)
{
cp->msgid = string;
- cp->msgid_escape = type;
cp->msgid_context = context;
cp->msgid_pos.file_name = file_name;
cp->msgid_pos.line_number = line_number;
if (argnum == cp->argnum2)
{
cp->msgid_plural = string;
- cp->msgid_plural_escape = type;
cp->msgid_plural_context = context;
cp->msgid_plural_pos.file_name = file_name;
cp->msgid_plural_pos.line_number = line_number;
}
-void
-arglist_parser_remember (struct arglist_parser *ap,
- int argnum, char *string,
- flag_context_ty context,
- char *file_name, size_t line_number,
- refcounted_string_list_ty *comment)
-{
- arglist_parser_remember_literal (ap, argnum, string, context,
- file_name, line_number,
- comment, LET_NONE);
-}
-
-
void
arglist_parser_remember_msgctxt (struct arglist_parser *ap,
char *string,
struct partial_call *cp = &ap->alternative[i];
cp->msgctxt = string;
- cp->msgctxt_escape = LET_NONE;
cp->msgctxt_pos.file_name = file_name;
cp->msgctxt_pos.line_number = line_number;
stored_string = true;
{
flag_context_ty msgid_context = best_cp->msgid_context;
flag_context_ty msgid_plural_context = best_cp->msgid_plural_context;
- struct literalstring_parser *parser = current_literalstring_parser;
- const char *encoding;
/* Special support for the 3-argument tr operator in Qt:
When --qt and --keyword=tr:1,1,2c,3t are specified, add to the
msgid_plural_context.is_format3 = yes_according_to_context;
}
- if (best_cp->msgctxt != NULL)
- {
- if (parser != NULL && best_cp->msgctxt_escape != 0)
- {
- char *msgctxt =
- parser->parse (best_cp->msgctxt,
- &best_cp->msgctxt_pos,
- best_cp->msgctxt_escape);
- free (best_cp->msgctxt);
- best_cp->msgctxt = msgctxt;
- }
- else
- {
- lex_pos_ty *pos = &best_cp->msgctxt_pos;
- CONVERT_STRING (best_cp->msgctxt, lc_string);
- }
- }
-
- if (parser != NULL && best_cp->msgid_escape != 0)
- {
- char *msgid = parser->parse (best_cp->msgid,
- &best_cp->msgid_pos,
- best_cp->msgid_escape);
- if (best_cp->msgid_plural == best_cp->msgid)
- best_cp->msgid_plural = msgid;
- free (best_cp->msgid);
- best_cp->msgid = msgid;
- }
- else
- {
- lex_pos_ty *pos = &best_cp->msgid_pos;
- CONVERT_STRING (best_cp->msgid, lc_string);
- }
-
- if (best_cp->msgid_plural)
- {
- /* best_cp->msgid_plural may point to best_cp->msgid.
- In that case, it is already interpreted and converted. */
- if (best_cp->msgid_plural != best_cp->msgid)
- {
- if (parser != NULL
- && best_cp->msgid_plural_escape != 0)
- {
- char *msgid_plural =
- parser->parse (best_cp->msgid_plural,
- &best_cp->msgid_plural_pos,
- best_cp->msgid_plural_escape);
- free (best_cp->msgid_plural);
- best_cp->msgid_plural = msgid_plural;
- }
- else
- {
- lex_pos_ty *pos = &best_cp->msgid_plural_pos;
- CONVERT_STRING (best_cp->msgid_plural, lc_string);
- }
- }
-
- /* If best_cp->msgid_plural equals to best_cp->msgid,
- the ownership will be transferred to
- remember_a_message before it is passed to
- remember_a_message_plural.
-
- Make a copy of the string in that case. */
- if (best_cp->msgid_plural == best_cp->msgid)
- best_cp->msgid_plural = xstrdup (best_cp->msgid);
- }
-
- if (best_cp->msgid_comment != NULL)
- {
- refcounted_string_list_ty *msgid_comment =
- savable_comment_convert_encoding (best_cp->msgid_comment,
- &best_cp->msgid_pos);
- drop_reference (best_cp->msgid_comment);
- best_cp->msgid_comment = msgid_comment;
- }
-
- /* best_cp->msgctxt, best_cp->msgid, and best_cp->msgid_plural
- are already in UTF-8. Prevent further conversion in
- remember_a_message. */
- encoding = xgettext_current_source_encoding;
- xgettext_current_source_encoding = po_charset_utf8;
mp = remember_a_message (ap->mlp, best_cp->msgctxt, best_cp->msgid,
msgid_context,
&best_cp->msgid_pos,
NULL, best_cp->msgid_comment);
if (mp != NULL && best_cp->msgid_plural != NULL)
- remember_a_message_plural (mp,
- best_cp->msgid_plural,
+ remember_a_message_plural (mp, best_cp->msgid_plural,
msgid_plural_context,
&best_cp->msgid_plural_pos,
NULL);
- xgettext_current_source_encoding = encoding;
}
if (best_cp->xcomments.nitems > 0)
flag_context_list_table_ty *flag_table;
struct formatstring_parser *formatstring_parser1;
struct formatstring_parser *formatstring_parser2;
- struct literalstring_parser *literalstring_parser;
};
typedef struct table_ty table_ty;
result.formatstring_parser1 = tp->formatstring_parser1;
result.formatstring_parser2 = tp->formatstring_parser2;
result.formatstring_parser3 = NULL;
- result.literalstring_parser = tp->literalstring_parser;
/* Handle --qt. It's preferrable to handle this facility here rather
than through an option --language=C++/Qt because the latter would
extern void savable_comment_add (const char *str);
extern void savable_comment_reset (void);
-/* Convert character encoding of COMMENT according to the current
- source encoding. Returns a new refcounted_string_list_ty. */
-extern refcounted_string_list_ty *
- savable_comment_convert_encoding (refcounted_string_list_ty *comment,
- lex_pos_ty *pos);
-
-
-enum literalstring_escape_type
-{
- LET_NONE = 0,
- LET_ANSI_C = 1 << 0,
- LET_UNICODE = 1 << 1
-};
-
-struct literalstring_parser
-{
- char * (*parse) (const char *string, lex_pos_ty *pos,
- enum literalstring_escape_type type);
-};
/* Add a message to the list of extracted messages.
msgctxt must be either NULL or a malloc()ed string; its ownership is passed
lex_pos_ty *pos,
refcounted_string_list_ty *comment);
+
/* Represents the progressive parsing of an argument list w.r.t. a single
'struct callshape'. */
struct partial_call
int argtotal; /* total number of arguments, 0 if unspecified */
string_list_ty xcomments; /* auto-extracted comments */
char *msgctxt; /* context - owned string, or NULL */
- enum literalstring_escape_type msgctxt_escape;
lex_pos_ty msgctxt_pos;
char *msgid; /* msgid - owned string, or NULL */
- enum literalstring_escape_type msgid_escape;
flag_context_ty msgid_context;
lex_pos_ty msgid_pos;
refcounted_string_list_ty *msgid_comment;
char *msgid_plural; /* msgid_plural - owned string, or NULL */
- enum literalstring_escape_type msgid_plural_escape;
flag_context_ty msgid_plural_context;
lex_pos_ty msgid_plural_pos;
};
flag_context_ty context,
char *file_name, size_t line_number,
refcounted_string_list_ty *comment);
-/* Adds an uninterpreted string argument to an arglist_parser. ARGNUM
- must be > 0.
- STRING is must be malloc()ed string; its ownership is passed to the callee.
- FILE_NAME must be allocated with indefinite extent.
- COMMENT may be savable_comment, or it may be a saved copy of savable_comment
- (then add_reference must be used when saving it, and drop_reference while
- dropping it). Clear savable_comment. */
-extern void arglist_parser_remember_literal (struct arglist_parser *ap,
- int argnum, char *string,
- flag_context_ty context,
- char *file_name, size_t line_number,
- refcounted_string_list_ty *comment,
- enum literalstring_escape_type type);
/* Adds a string argument as msgctxt to an arglist_parser, without incrementing
the current argument number.
STRING must be malloc()ed string; its ownership is passed to the callee.