Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <stdlib.h>
21 : : #include <stdio.h>
22 : : #include <fcntl.h>
23 : : #include <errno.h>
24 : : #include <string.h>
25 : : #include <unistd.h>
26 : : #include <ctype.h>
27 : : #include <sal/alloca.h>
28 : : #include <sal/macros.h>
29 : :
30 : : #include <rtl/ustring.hxx>
31 : :
32 : : #include <map>
33 : : #include <string>
34 : :
35 : : /*****************************************************************************
36 : : * typedefs
37 : : *****************************************************************************/
38 : :
39 : : typedef std::map< const std::string, rtl_TextEncoding > EncodingMap;
40 : :
41 : : struct _pair {
42 : : const char *key;
43 : : rtl_TextEncoding value;
44 : : };
45 : :
46 : : static int _pair_compare (const char *key, const _pair *pair);
47 : : static const _pair* _pair_search (const char *key, const _pair *base, unsigned int member );
48 : :
49 : :
50 : : const _pair _ms_encoding_list[] = {
51 : : { "0", RTL_TEXTENCODING_UTF8 },
52 : : { "1250", RTL_TEXTENCODING_MS_1250 },
53 : : { "1251", RTL_TEXTENCODING_MS_1251 },
54 : : { "1252", RTL_TEXTENCODING_MS_1252 },
55 : : { "1253", RTL_TEXTENCODING_MS_1253 },
56 : : { "1254", RTL_TEXTENCODING_MS_1254 },
57 : : { "1255", RTL_TEXTENCODING_MS_1255 },
58 : : { "1256", RTL_TEXTENCODING_MS_1256 },
59 : : { "1257", RTL_TEXTENCODING_MS_1257 },
60 : : { "1258", RTL_TEXTENCODING_MS_1258 },
61 : : { "874", RTL_TEXTENCODING_MS_874 },
62 : : { "932", RTL_TEXTENCODING_MS_932 },
63 : : { "936", RTL_TEXTENCODING_MS_936 },
64 : : { "949", RTL_TEXTENCODING_MS_949 },
65 : : { "950", RTL_TEXTENCODING_MS_950 }
66 : : };
67 : :
68 : :
69 : : /*****************************************************************************
70 : : * fgets that work with unix line ends on Windows
71 : : *****************************************************************************/
72 : :
73 : 0 : char * my_fgets(char *s, int n, FILE *fp)
74 : : {
75 : : int i;
76 [ # # ]: 0 : for( i=0; i < n-1; i++ )
77 : : {
78 : 0 : int c = getc(fp);
79 : :
80 [ # # ]: 0 : if( c == EOF )
81 : 0 : break;
82 : :
83 : 0 : s[i] = (char) c;
84 : :
85 [ # # ]: 0 : if( s[i] == '\n' )
86 : : {
87 : 0 : i++;
88 : 0 : break;
89 : : }
90 : : }
91 : :
92 [ # # ]: 0 : if( i>0 )
93 : : {
94 : 0 : s[i] = '\0';
95 : 0 : return s;
96 : : }
97 : : else
98 : : {
99 : 0 : return NULL;
100 : : }
101 : : }
102 : :
103 : : /*****************************************************************************
104 : : * compare function for binary search
105 : : *****************************************************************************/
106 : :
107 : : static int
108 : 0 : _pair_compare (const char *key, const _pair *pair)
109 : : {
110 : 0 : int result = rtl_str_compareIgnoreAsciiCase( key, pair->key );
111 : 0 : return result;
112 : : }
113 : :
114 : : /*****************************************************************************
115 : : * binary search on encoding tables
116 : : *****************************************************************************/
117 : :
118 : : static const _pair*
119 : 0 : _pair_search (const char *key, const _pair *base, unsigned int member )
120 : : {
121 : 0 : unsigned int lower = 0;
122 : 0 : unsigned int upper = member;
123 : : unsigned int current;
124 : : int comparison;
125 : :
126 : : /* check for validity of input */
127 [ # # ][ # # ]: 0 : if ( (key == NULL) || (base == NULL) || (member == 0) )
[ # # ]
128 : 0 : return NULL;
129 : :
130 : : /* binary search */
131 [ # # ]: 0 : while ( lower < upper )
132 : : {
133 : 0 : current = (lower + upper) / 2;
134 : 0 : comparison = _pair_compare( key, base + current );
135 [ # # ]: 0 : if (comparison < 0)
136 : 0 : upper = current;
137 : : else
138 [ # # ]: 0 : if (comparison > 0)
139 : 0 : lower = current + 1;
140 : : else
141 : 0 : return base + current;
142 : : }
143 : :
144 : 0 : return NULL;
145 : : }
146 : :
147 : :
148 : : /************************************************************************
149 : : * read_encoding_table
150 : : ************************************************************************/
151 : :
152 : 0 : void read_encoding_table(char * file, EncodingMap& aEncodingMap)
153 : : {
154 [ # # ]: 0 : FILE * fp = fopen(file, "r");
155 [ # # ]: 0 : if ( ! fp ) {
156 [ # # ]: 0 : fprintf(stderr, "ulfconv: %s %s\n", file, strerror(errno));
157 : 0 : exit(2);
158 : : }
159 : :
160 : : char buffer[512];
161 [ # # ][ # # ]: 0 : while ( NULL != my_fgets(buffer, sizeof(buffer), fp) ) {
162 : :
163 : : // strip comment lines
164 [ # # ]: 0 : if ( buffer[0] == '#' )
165 : 0 : continue;
166 : :
167 : : // find end of language string
168 : : char * cp;
169 [ # # ]: 0 : for ( cp = buffer; ! isspace(*cp); cp++ )
170 : : ;
171 : 0 : *cp = '\0';
172 : :
173 : : // find start of codepage string
174 [ # # ]: 0 : for ( ++cp; isspace(*cp); ++cp )
175 : : ;
176 : 0 : char * codepage = cp;
177 : :
178 : : // find end of codepage string
179 [ # # ]: 0 : for ( ++cp; ! isspace(*cp); ++cp )
180 : : ;
181 : 0 : *cp = '\0';
182 : :
183 : : // find the correct mapping for codepage
184 : 0 : const unsigned int members = SAL_N_ELEMENTS( _ms_encoding_list );
185 : 0 : const _pair *encoding = _pair_search( codepage, _ms_encoding_list, members );
186 : :
187 [ # # ]: 0 : if ( encoding != NULL ) {
188 [ # # ]: 0 : const std::string language(buffer);
189 [ # # ][ # # ]: 0 : aEncodingMap.insert( EncodingMap::value_type(language, encoding->value) );
190 : : }
191 : : }
192 : :
193 [ # # ]: 0 : fclose(fp);
194 : 0 : }
195 : :
196 : : /************************************************************************
197 : : * print_legacy_mixed
198 : : ************************************************************************/
199 : :
200 : 0 : void print_legacy_mixed(
201 : : FILE * ostream,
202 : : const rtl::OUString& aString,
203 : : const std::string& language,
204 : : EncodingMap& aEncodingMap)
205 : : {
206 [ # # ]: 0 : EncodingMap::iterator iter = aEncodingMap.find(language);
207 : :
208 [ # # ][ # # ]: 0 : if ( iter != aEncodingMap.end() ) {
209 [ # # ][ # # ]: 0 : fputs(OUStringToOString(aString, iter->second).getStr(), ostream);
[ # # ]
210 : : } else {
211 [ # # ]: 0 : fprintf(stderr, "ulfconv: WARNING: no legacy encoding found for %s\n", language.c_str());
212 : : }
213 : 0 : }
214 : :
215 : : /************************************************************************
216 : : * print_java_style
217 : : ************************************************************************/
218 : :
219 : 1167 : void print_java_style(FILE * ostream, const rtl::OUString& aString)
220 : : {
221 : 1167 : int imax = aString.getLength();
222 [ + + ]: 36419 : for (int i = 0; i < imax; i++) {
223 : 35252 : sal_Unicode uc = aString[i];
224 [ + + ]: 35252 : if ( uc < 128 ) {
225 : 35246 : fprintf(ostream, "%c", (char) uc);
226 : : } else {
227 : 6 : fprintf(ostream, "\\u%2.2x%2.2x", uc >> 8, uc & 0xFF );
228 : : }
229 : : }
230 : 1167 : }
231 : :
232 : : /************************************************************************
233 : : * main
234 : : ************************************************************************/
235 : :
236 : 27 : int main( int argc, char * const argv[] )
237 : : {
238 [ + - ]: 27 : EncodingMap aEncodingMap;
239 : :
240 : 27 : FILE *istream = stdin;
241 : 27 : FILE *ostream = stdout;
242 : :
243 : 27 : char *outfile = NULL;
244 : :
245 : 27 : int errflg = 0;
246 : : int argi;
247 : :
248 [ + - ]: 54 : for( argi=1; argi < argc; argi++ )
249 : : {
250 [ + + ][ + - ]: 54 : if( argv[argi][0] == '-' && argv[argi][2] == '\0' )
251 : : {
252 [ + - - ]: 54 : switch(argv[argi][1]) {
253 : : case 'o':
254 [ + - ][ - + ]: 27 : if (argi+1 >= argc || argv[argi+1][0] == '-')
255 : : {
256 [ # # ]: 0 : fprintf(stderr, "Option -%c requires an operand\n", argv[argi][1]);
257 : 0 : errflg++;
258 : 0 : break;
259 : : }
260 : :
261 : 27 : ++argi;
262 : 27 : outfile = argv[argi];
263 : 27 : break;
264 : : case 't':
265 [ # # ][ # # ]: 0 : if (argi+1 >= argc || argv[argi+1][0] == '-')
266 : : {
267 [ # # ]: 0 : fprintf(stderr, "Option -%c requires an operand\n", argv[argi][1]);
268 : 0 : errflg++;
269 : 0 : break;
270 : : }
271 : :
272 [ # # ]: 0 : read_encoding_table(argv[++argi], aEncodingMap);
273 : 0 : break;
274 : : default:
275 [ # # ]: 0 : fprintf(stderr, "Unrecognized option: -%c\n", argv[argi][1]);
276 : 0 : errflg++;
277 : : }
278 : : }
279 : : else
280 : : {
281 : 27 : break;
282 : : }
283 : : }
284 : :
285 [ - + ]: 27 : if (errflg) {
286 [ # # ]: 0 : fprintf(stderr, "Usage: ulfconv [-o <output file>] [-t <encoding table>] [<ulf file>]\n");
287 : 0 : exit(2);
288 : : }
289 : :
290 : : /* assign input file to stdin */
291 [ + - ]: 27 : if ( argi < argc )
292 : : {
293 [ + - ]: 27 : istream = fopen(argv[argi], "r");
294 [ - + ]: 27 : if ( istream == NULL ) {
295 [ # # ]: 0 : fprintf(stderr, "ulfconv: %s : %s\n", argv[argi], strerror(errno));
296 : 0 : exit(2);
297 : : }
298 : : }
299 : :
300 : : /* open output file if any */
301 [ + - ]: 27 : if ( outfile )
302 : : {
303 [ + - ]: 27 : ostream = fopen(outfile, "w");
304 [ - + ]: 27 : if ( ostream == NULL ) {
305 [ # # ]: 0 : fprintf(stderr, "ulfconv: %s : %s\n", outfile, strerror(errno));
306 [ # # ]: 0 : fclose(istream);
307 : 0 : exit(2);
308 : : }
309 : : }
310 : :
311 : : /* read line by line from stdin */
312 : : char buffer[65536];
313 [ + - ][ + + ]: 4151 : while ( NULL != fgets(buffer, sizeof(buffer), istream) ) {
314 : :
315 : : /* only handle lines containing " = " */
316 : 4124 : char * cp = strstr(buffer, " = \"");
317 [ + + ]: 4124 : if ( cp ) {
318 : 1167 : rtl::OUString aString;
319 : :
320 : : /* find end of lang string */
321 : : int n;
322 [ + + ]: 7002 : for ( n=0; ! isspace(buffer[n]); n++ )
323 : : ;
324 : :
325 [ + - ]: 1167 : std::string line = buffer;
326 [ + - ]: 1167 : std::string lang(line, 0, n);
327 : :
328 : 1167 : cp += 4;
329 : 1167 : rtl_string2UString( &aString.pData, cp, strrchr(cp, '\"') - cp,
330 : 1167 : RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS );
331 : :
332 [ + - ]: 1167 : fprintf(ostream, "%s = \"", lang.c_str());
333 : :
334 [ + - ]: 1167 : if ( aEncodingMap.empty() ) {
335 [ + - ]: 1167 : print_java_style(ostream, aString);
336 : : } else {
337 [ # # ]: 0 : print_legacy_mixed(ostream, aString, lang, aEncodingMap);
338 : : }
339 : :
340 [ + - ]: 1167 : fprintf(ostream, "\"\n");
341 : :
342 : :
343 : : } else {
344 [ + - ]: 2957 : fputs(buffer, ostream);
345 : : }
346 : : }
347 : :
348 [ + - ]: 27 : fclose(ostream);
349 [ + - ]: 27 : fclose(istream);
350 : 27 : }
351 : :
352 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|