1 /* Keeping track of the encoding of strings to be extracted.
2 Copyright (C) 2001-2019 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 /* Specification. */
22 #include "xg-encoding.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "msgl-ascii.h"
28 #include "msgl-iconv.h"
29 #include "po-charset.h"
30 #include "xalloc.h"
31 #include "xerror.h"
32 #include "xvasprintf.h"
33
34 #include "gettext.h"
35 #define _(str) gettext (str)
36
37
38 /* Canonicalized encoding name for all input files.
39 It can be NULL when the --from-code option has not been specified. In this
40 case, the default (ASCII or UTF-8) depends on the programming language. */
41 const char *xgettext_global_source_encoding;
42
43 #if HAVE_ICONV
44 /* Converter from xgettext_global_source_encoding to UTF-8 (except from
45 ASCII or UTF-8, when this conversion is a no-op). */
46 iconv_t xgettext_global_source_iconv;
47 #endif
48
49 /* Canonicalized encoding name for the current input file. */
50 const char *xgettext_current_source_encoding;
51
52 #if HAVE_ICONV
53 /* Converter from xgettext_current_source_encoding to UTF-8 (except from
54 ASCII or UTF-8, when this conversion is a no-op). */
55 iconv_t xgettext_current_source_iconv;
56 #endif
57
58
59 /* Error message about non-ASCII character in a specific lexical context. */
60 char *
non_ascii_error_message(lexical_context_ty lcontext,const char * file_name,size_t line_number)61 non_ascii_error_message (lexical_context_ty lcontext,
62 const char *file_name, size_t line_number)
63 {
64 char buffer[21];
65 char *errmsg;
66
67 if (line_number == (size_t)(-1))
68 buffer[0] = '\0';
69 else
70 sprintf (buffer, ":%ld", (long) line_number);
71
72 switch (lcontext)
73 {
74 case lc_outside:
75 errmsg =
76 xasprintf (_("Non-ASCII character at %s%s."), file_name, buffer);
77 break;
78 case lc_comment:
79 errmsg =
80 xasprintf (_("Non-ASCII comment at or before %s%s."),
81 file_name, buffer);
82 break;
83 case lc_string:
84 errmsg =
85 xasprintf (_("Non-ASCII string at %s%s."), file_name, buffer);
86 break;
87 default:
88 abort ();
89 }
90 return errmsg;
91 }
92
93 /* Convert the given string from xgettext_current_source_encoding to
94 the output file encoding (i.e. ASCII or UTF-8).
95 The resulting string is either the argument string, or freshly allocated.
96 The file_name and line_number are only used for error message purposes. */
97 char *
from_current_source_encoding(const char * string,lexical_context_ty lcontext,const char * file_name,size_t line_number)98 from_current_source_encoding (const char *string,
99 lexical_context_ty lcontext,
100 const char *file_name, size_t line_number)
101 {
102 if (xgettext_current_source_encoding == po_charset_ascii)
103 {
104 if (!is_ascii_string (string))
105 {
106 multiline_error (xstrdup (""),
107 xasprintf ("%s\n%s\n",
108 non_ascii_error_message (lcontext,
109 file_name,
110 line_number),
111 _("Please specify the source encoding through --from-code.")));
112 exit (EXIT_FAILURE);
113 }
114 }
115 else if (xgettext_current_source_encoding != po_charset_utf8)
116 {
117 #if HAVE_ICONV
118 struct conversion_context context;
119
120 context.from_code = xgettext_current_source_encoding;
121 context.to_code = po_charset_utf8;
122 context.from_filename = file_name;
123 context.message = NULL;
124
125 string = convert_string_directly (xgettext_current_source_iconv, string,
126 &context);
127 #else
128 /* If we don't have iconv(), the only supported values for
129 xgettext_global_source_encoding and thus also for
130 xgettext_current_source_encoding are ASCII and UTF-8.
131 convert_string_directly() should not be called in this case. */
132 abort ();
133 #endif
134 }
135
136 return (char *) string;
137 }
138