• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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