]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
3 | * | |
374ca955 | 4 | * Copyright (C) 1999-2004, International Business Machines |
b75a7d8f A |
5 | * Corporation and others. All Rights Reserved. |
6 | * | |
7 | ******************************************************************************* | |
8 | * file name: derb.c | |
9 | * encoding: US-ASCII | |
10 | * tab size: 8 (not used) | |
11 | * indentation:4 | |
12 | * | |
13 | * created on: 2000sep6 | |
14 | * created by: Vladimir Weinstein as an ICU workshop example | |
15 | * maintained by: Yves Arrouye <yves@realnames.com> | |
16 | */ | |
17 | ||
18 | #include "unicode/ucnv.h" | |
19 | #include "unicode/ustring.h" | |
374ca955 | 20 | #include "unicode/putil.h" |
b75a7d8f A |
21 | |
22 | #include "uresimp.h" | |
23 | #include "cmemory.h" | |
24 | #include "cstring.h" | |
25 | #include "uoptions.h" | |
26 | #include "toolutil.h" | |
27 | #include "ustrfmt.h" | |
28 | ||
29 | #include <stdlib.h> | |
30 | #include <stdio.h> | |
31 | #include <ctype.h> | |
32 | ||
374ca955 | 33 | #if defined(WIN32) || defined(U_CYGWIN) |
b75a7d8f A |
34 | #include <io.h> |
35 | #include <fcntl.h> | |
36 | #endif | |
37 | ||
38 | #define DERB_VERSION "1.0" | |
39 | ||
40 | #define DERB_DEFAULT_TRUNC 80 | |
41 | ||
42 | static UConverter *defaultConverter = 0; | |
43 | ||
44 | static const int32_t indentsize = 4; | |
45 | static int32_t truncsize = DERB_DEFAULT_TRUNC; | |
46 | static UBool trunc = FALSE; | |
47 | ||
48 | static const UChar baderror[] = { 0x0042, 0x0041, 0x0044, 0x0000 }; | |
49 | ||
50 | static const char *getEncodingName(const char *encoding); | |
51 | static void reportError(const char *pname, UErrorCode *status, const char *when); | |
52 | static UChar *quotedString(const UChar *string); | |
53 | static void printOutBundle(FILE *out, UConverter *converter, UResourceBundle *resource, int32_t indent, const char *pname, UErrorCode *status); | |
54 | static void printString(FILE *out, UConverter *converter, const UChar *str, int32_t len); | |
55 | static void printCString(FILE *out, UConverter *converter, const char *str, int32_t len); | |
56 | static void printIndent(FILE *out, UConverter *converter, int32_t indent); | |
57 | static void printHex(FILE *out, UConverter *converter, uint8_t what); | |
58 | ||
59 | static UOption options[]={ | |
60 | UOPTION_HELP_H, | |
61 | UOPTION_HELP_QUESTION_MARK, | |
62 | /* 2 */ UOPTION_ENCODING, | |
63 | /* 3 */ { "to-stdout", NULL, NULL, NULL, 'c', UOPT_NO_ARG, 0 } , | |
64 | /* 4 */ { "truncate", NULL, NULL, NULL, 't', UOPT_OPTIONAL_ARG, 0 }, | |
65 | /* 5 */ UOPTION_VERBOSE, | |
66 | /* 6 */ UOPTION_DESTDIR, | |
67 | /* 7 */ UOPTION_SOURCEDIR, | |
68 | /* 8 */ { "bom", NULL, NULL, NULL, 0, UOPT_NO_ARG, 0 }, | |
69 | /* 9 */ UOPTION_ICUDATADIR, | |
70 | /* 10 */ UOPTION_VERSION, | |
71 | /* 11 */ { "suppressAliases", NULL, NULL, NULL, 'A', UOPT_NO_ARG, 0 } | |
72 | }; | |
73 | ||
74 | static UBool verbose = FALSE; | |
75 | static UBool suppressAliases = FALSE; | |
76 | ||
77 | extern int | |
78 | main(int argc, char* argv[]) { | |
79 | const char *encoding = NULL; | |
80 | const char *outputDir = NULL; /* NULL = no output directory, use current */ | |
81 | const char *inputDir = "."; | |
82 | int tostdout = 0; | |
83 | int prbom = 0; | |
84 | ||
85 | const char *pname; | |
86 | ||
87 | UResourceBundle *bundle = NULL; | |
88 | UErrorCode status = U_ZERO_ERROR; | |
89 | int32_t i = 0; | |
90 | ||
91 | UConverter *converter; | |
92 | ||
93 | const char* arg; | |
94 | ||
95 | /* Get the name of tool. */ | |
96 | pname = uprv_strrchr(*argv, U_FILE_SEP_CHAR); | |
97 | #ifdef WIN32 | |
98 | if (!pname) { | |
99 | pname = uprv_strrchr(*argv, '/'); | |
100 | } | |
101 | #endif | |
102 | if (!pname) { | |
103 | pname = *argv; | |
104 | } else { | |
105 | ++pname; | |
106 | } | |
107 | ||
108 | /* error handling, printing usage message */ | |
109 | argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); | |
110 | ||
111 | /* error handling, printing usage message */ | |
112 | if(argc<0) { | |
113 | fprintf(stderr, | |
114 | "%s: error in command line argument \"%s\"\n", pname, | |
115 | argv[-argc]); | |
116 | } | |
117 | if(argc<0 || options[0].doesOccur || options[1].doesOccur) { | |
118 | fprintf(argc < 0 ? stderr : stdout, | |
119 | "%csage: %s [ -h, -?, --help ] [ -V, --version ]\n" | |
120 | " [ -v, --verbose ] [ -e, --encoding encoding ] [ --bom ]\n" | |
121 | " [ -t, --truncate [ size ] ]\n" | |
122 | " [ -s, --sourcedir source ] [ -d, --destdir destination ]\n" | |
123 | " [ -i, --icudatadir directory ] [ -c, --to-stdout ]\n" | |
124 | " [ -A, --suppressAliases]\n" | |
125 | " bundle ...\n", argc < 0 ? 'u' : 'U', | |
126 | pname); | |
127 | return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; | |
128 | } | |
129 | ||
130 | if(options[10].doesOccur) { | |
131 | fprintf(stderr, | |
132 | "%s version %s (ICU version %s).\n" | |
133 | "%s\n", | |
134 | pname, DERB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING); | |
135 | return U_ZERO_ERROR; | |
136 | } | |
137 | if(options[2].doesOccur) { | |
138 | encoding = options[2].value; | |
139 | } | |
140 | ||
141 | if (options[3].doesOccur) { | |
142 | tostdout = 1; | |
143 | } | |
144 | ||
145 | if(options[4].doesOccur) { | |
146 | trunc = TRUE; | |
147 | if(options[4].value != NULL) { | |
148 | truncsize = atoi(options[4].value); /* user defined printable size */ | |
149 | } else { | |
150 | truncsize = DERB_DEFAULT_TRUNC; /* we'll use default omitting size */ | |
151 | } | |
152 | } else { | |
153 | trunc = FALSE; | |
154 | } | |
155 | ||
156 | if(options[5].doesOccur) { | |
157 | verbose = TRUE; | |
158 | } | |
159 | ||
160 | if (options[6].doesOccur) { | |
161 | outputDir = options[6].value; | |
162 | } | |
163 | ||
164 | if(options[7].doesOccur) { | |
165 | inputDir = options[7].value; /* we'll use users resources */ | |
166 | } | |
167 | ||
168 | if (options[8].doesOccur) { | |
169 | prbom = 1; | |
170 | } | |
171 | ||
172 | if (options[9].doesOccur) { | |
173 | u_setDataDirectory(options[9].value); | |
174 | } | |
175 | ||
176 | if (options[11].doesOccur) { | |
177 | suppressAliases = TRUE; | |
178 | } | |
179 | ||
180 | converter = ucnv_open(encoding, &status); | |
181 | if (U_FAILURE(status)) { | |
182 | fprintf(stderr, "%s: couldn't create %s converter for encoding\n", pname, encoding ? encoding : ucnv_getDefaultName()); | |
183 | return 2; | |
184 | } | |
185 | ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_C, 0, 0, &status); | |
186 | if (U_FAILURE(status)) { | |
187 | fprintf(stderr, "%s: couldn't configure converter for encoding\n", pname); | |
188 | return 3; | |
189 | } | |
190 | ||
191 | defaultConverter = ucnv_open(0, &status); | |
192 | if (U_FAILURE(status)) { | |
193 | fprintf(stderr, "%s: couldn't create %s converter for encoding\n", ucnv_getDefaultName(), pname); | |
194 | return 2; | |
195 | } | |
196 | ||
197 | for (i = 1; i < argc; ++i) { | |
198 | static const UChar sp[] = { 0x0020 }; /* " " */ | |
199 | char infile[4096]; /* XXX Sloppy. */ | |
200 | char locale[64]; | |
201 | const char *thename = 0, *p, *q; | |
202 | UBool fromICUData = FALSE; | |
203 | ||
204 | arg = getLongPathname(argv[i]); | |
205 | ||
206 | if (verbose) { | |
207 | printf("processing bundle \"%s\"\n", argv[i]); | |
208 | } | |
209 | ||
210 | p = uprv_strrchr(arg, U_FILE_SEP_CHAR); | |
211 | if (!p) { | |
212 | p = arg; | |
213 | } else { | |
214 | p++; | |
215 | } | |
216 | q = uprv_strrchr(p, '.'); | |
217 | if (!q) { | |
218 | for (q = p; *q; ++q); | |
219 | } | |
220 | uprv_strncpy(locale, p, q - p); | |
221 | locale[q - p] = 0; | |
222 | ||
223 | if (!(fromICUData = !uprv_strcmp(inputDir, "-"))) { | |
224 | UBool absfilename = *arg == U_FILE_SEP_CHAR; | |
225 | #ifdef WIN32 | |
226 | if (!absfilename) { | |
227 | absfilename = (uprv_strlen(arg) > 2 && isalpha(arg[0]) | |
228 | && arg[1] == ':' && arg[2] == U_FILE_SEP_CHAR); | |
229 | } | |
230 | #endif | |
231 | if (absfilename) { | |
232 | thename = arg; | |
233 | } else { | |
234 | q = uprv_strrchr(arg, U_FILE_SEP_CHAR); | |
235 | uprv_strcpy(infile, inputDir); | |
236 | if(q != NULL) { | |
237 | uprv_strcat(infile, U_FILE_SEP_STRING), | |
238 | strncat(infile, arg, q-arg); | |
239 | } | |
240 | thename = infile; | |
241 | } | |
242 | } | |
243 | status = U_ZERO_ERROR; | |
244 | if (thename) { | |
245 | bundle = ures_openDirect(thename, locale, &status); | |
246 | } else { | |
247 | bundle = ures_open(fromICUData ? 0 : inputDir, locale, &status); | |
248 | } | |
249 | if (status == U_ZERO_ERROR) { | |
250 | FILE *out; | |
251 | ||
252 | const char *filename = 0; | |
253 | const char *ext = 0; | |
254 | ||
255 | if (!locale || !tostdout) { | |
256 | filename = uprv_strrchr(arg, U_FILE_SEP_CHAR); | |
257 | ||
258 | #ifdef WIN32 | |
259 | if (!filename) { | |
260 | filename = uprv_strrchr(arg, '/'); | |
261 | } | |
262 | #endif | |
263 | if (!filename) { | |
264 | filename = arg; | |
265 | } else { | |
266 | ++filename; | |
267 | } | |
268 | ext = uprv_strrchr(arg, '.'); | |
269 | if (!ext) { | |
270 | ext = filename + uprv_strlen(filename); | |
271 | } | |
272 | } | |
273 | ||
274 | if (tostdout) { | |
275 | out = stdout; | |
374ca955 | 276 | #if defined(WIN32) || defined(U_CYGWIN) |
b75a7d8f | 277 | if (_setmode(_fileno(out), _O_BINARY) == -1) { |
374ca955 | 278 | fprintf(stderr, "%s: couldn't set standard output to binary mode\n", pname); |
b75a7d8f A |
279 | return 4; |
280 | } | |
281 | #endif | |
282 | } else { | |
283 | char thefile[4096], *tp; | |
284 | int32_t len; | |
285 | ||
286 | if (outputDir) { | |
287 | uprv_strcpy(thefile, outputDir); | |
288 | uprv_strcat(thefile, U_FILE_SEP_STRING); | |
289 | } else { | |
290 | *thefile = 0; | |
291 | } | |
292 | uprv_strcat(thefile, filename); | |
293 | tp = thefile + uprv_strlen(thefile); | |
294 | len = (int32_t)uprv_strlen(ext); | |
295 | if (len) { | |
296 | tp -= len - 1; | |
297 | } else { | |
298 | *tp++ = '.'; | |
299 | } | |
300 | uprv_strcpy(tp, "txt"); | |
301 | ||
302 | out = fopen(thefile, "w"); | |
303 | if (!out) { | |
304 | fprintf(stderr, "%s: couldn't create %s\n", pname, thefile); | |
305 | return 4; | |
306 | } | |
307 | } | |
308 | ||
309 | if (prbom) { /* XXX: Should be done only for UTFs */ | |
310 | static const UChar bom[] = { 0xFEFF }; | |
311 | printString(out, converter, bom, (int32_t)(sizeof(bom)/sizeof(*bom))); | |
312 | } | |
313 | ||
314 | printCString(out, converter, "// -*- Coding: ", -1); | |
315 | printCString(out, converter, encoding ? encoding : getEncodingName(ucnv_getDefaultName()), -1); | |
316 | printCString(out, converter, "; -*-\n//\n", -1); | |
317 | printCString(out, converter, "// This file was dumped by derb(8) from ", -1); | |
318 | if (thename) { | |
319 | printCString(out, converter, thename, -1); | |
320 | } else if (fromICUData) { | |
321 | printCString(out, converter, "the ICU internal ", -1); | |
322 | printCString(out, converter, locale, -1); | |
323 | printCString(out, converter, " locale", -1); | |
324 | } | |
325 | ||
326 | printCString(out, converter, "\n// derb(8) by Vladimir Weinstein and Yves Arrouye\n\n", -1); | |
327 | ||
328 | if (locale) { | |
329 | printCString(out, converter, locale, -1); | |
330 | } else { | |
374ca955 | 331 | printCString(out, converter, filename, (int32_t)(ext - filename)); |
b75a7d8f A |
332 | printString(out, converter, sp, (int32_t)(sizeof(sp)/sizeof(*sp))); |
333 | } | |
334 | printOutBundle(out, converter, bundle, 0, pname, &status); | |
335 | ||
336 | if (out != stdout) { | |
337 | fclose(out); | |
338 | } | |
339 | } else { | |
340 | reportError(pname, &status, "opening resource file"); | |
341 | } | |
342 | ||
343 | ures_close(bundle); | |
344 | } | |
345 | ||
346 | ucnv_close(defaultConverter); | |
347 | ucnv_close(converter); | |
348 | ||
349 | return 0; | |
350 | } | |
351 | ||
352 | static UChar *quotedString(const UChar *string) { | |
353 | int len = u_strlen(string); | |
354 | int alen = len; | |
355 | const UChar *sp; | |
356 | UChar *newstr, *np; | |
357 | ||
358 | for (sp = string; *sp; ++sp) { | |
359 | switch (*sp) { | |
360 | case '\n': | |
361 | case 0x0022: | |
362 | ++alen; | |
363 | break; | |
364 | } | |
365 | } | |
366 | ||
367 | newstr = (UChar *) uprv_malloc((1 + alen) * sizeof(*newstr)); | |
368 | for (sp = string, np = newstr; *sp; ++sp) { | |
369 | switch (*sp) { | |
370 | case '\n': | |
371 | *np++ = 0x005C; | |
372 | *np++ = 0x006E; | |
373 | break; | |
374 | ||
375 | case 0x0022: | |
376 | *np++ = 0x005C; | |
377 | ||
378 | default: | |
379 | *np++ = *sp; | |
380 | break; | |
381 | } | |
382 | } | |
383 | *np = 0; | |
384 | ||
385 | return newstr; | |
386 | } | |
387 | ||
388 | ||
389 | static void printString(FILE *out, UConverter *converter, const UChar *str, int32_t len) { | |
390 | char buf[256]; | |
391 | const UChar *strEnd; | |
392 | ||
393 | if (len < 0) { | |
394 | len = u_strlen(str); | |
395 | } | |
396 | strEnd = str + len; | |
397 | ||
398 | do { | |
399 | UErrorCode err = U_ZERO_ERROR; | |
400 | char *bufp = buf, *bufend = buf + sizeof(buf) - 1 ; | |
401 | ||
402 | ucnv_fromUnicode(converter, &bufp, bufend, &str, strEnd, 0, 0, &err); | |
403 | *bufp = 0; | |
404 | ||
405 | fprintf(out, "%s", buf); | |
406 | } while (str < strEnd); | |
407 | } | |
408 | ||
409 | static void printCString(FILE *out, UConverter *converter, const char *str, int32_t len) { | |
410 | UChar buf[256]; | |
411 | const char *strEnd; | |
412 | ||
413 | if (len < 0) { | |
414 | len = (int32_t)uprv_strlen(str); | |
415 | } | |
416 | strEnd = str + len; | |
417 | ||
418 | do { | |
419 | UErrorCode err = U_ZERO_ERROR; | |
420 | UChar *bufp = buf, *bufend = buf + (sizeof(buf)/sizeof(buf[0])) - 1 ; | |
421 | ||
422 | ucnv_toUnicode(defaultConverter, &bufp, bufend, &str, strEnd, 0, 0, &err); | |
423 | *bufp = 0; | |
424 | ||
374ca955 | 425 | printString(out, converter, buf, (int32_t)(bufp - buf)); |
b75a7d8f A |
426 | } while (str < strEnd); |
427 | } | |
428 | ||
429 | static void printIndent(FILE *out, UConverter *converter, int32_t indent) { | |
430 | UChar inchar[256]; | |
431 | int32_t i = 0; | |
432 | for(i = 0; i<indent; i++) { | |
433 | inchar[i] = 0x0020; | |
434 | } | |
435 | inchar[indent] = 0; | |
436 | ||
437 | printString(out, converter, inchar, indent); | |
438 | } | |
439 | ||
440 | static void printHex(FILE *out, UConverter *converter, uint8_t what) { | |
441 | static const char map[] = "0123456789ABCDEF"; | |
442 | UChar hex[2]; | |
443 | ||
444 | hex[0] = map[what >> 4]; | |
445 | hex[1] = map[what & 0xf]; | |
446 | ||
447 | printString(out, converter, hex, (int32_t)(sizeof(hex)/sizeof(*hex))); | |
448 | } | |
449 | static const UChar * | |
450 | derb_getString(const ResourceData *pResData, const Resource res, int32_t *pLength) { | |
451 | if(res!=RES_BOGUS) { | |
452 | int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res); | |
453 | if (pLength) { | |
454 | *pLength=*p; | |
455 | } | |
456 | return (UChar *)++p; | |
457 | } else { | |
458 | if (pLength) { | |
459 | *pLength=0; | |
460 | } | |
461 | return NULL; | |
462 | } | |
463 | } | |
464 | ||
465 | static const char * | |
466 | derb_getTableKey(const Resource *pRoot, const Resource res, uint16_t indexS) { | |
467 | uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res); | |
468 | if(indexS<*p) { | |
469 | return ((const char *)(pRoot)+(p[indexS+1])); /*RES_GET_KEY(pRoot, p[indexS+1]);*/ | |
470 | } else { | |
471 | return NULL; /* indexS>itemCount */ | |
472 | } | |
473 | } | |
474 | ||
475 | static Resource | |
476 | derb_getArrayItem(Resource *pRoot, Resource res, int32_t indexR) { | |
477 | int32_t *p=(int32_t *)RES_GET_POINTER(pRoot, res); | |
478 | if(indexR<*p) { | |
479 | return ((Resource *)(p))[1+indexR]; | |
480 | } else { | |
481 | return RES_BOGUS; /* indexR>itemCount */ | |
482 | } | |
483 | } | |
484 | ||
485 | static Resource | |
486 | derb_getTableItem(const Resource *pRoot, const Resource res, uint16_t indexR) { | |
487 | uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res); | |
488 | uint16_t count=*p; | |
489 | if(indexR<count) { | |
490 | return ((Resource *)(p+1+count+(~count&1)))[indexR]; | |
491 | } else { | |
492 | return RES_BOGUS; /* indexR>itemCount */ | |
493 | } | |
494 | } | |
495 | ||
496 | ||
497 | static void printOutAlias(FILE *out, UConverter *converter, UResourceBundle *parent, Resource r, const char *key, int32_t indent, const char *pname, UErrorCode *status) { | |
498 | static const UChar cr[] = { '\n' }; | |
499 | int32_t len = 0; | |
500 | const UChar* thestr = derb_getString(&(parent->fResData), r, &len); | |
501 | UChar *string = quotedString(thestr); | |
502 | if(trunc && len > truncsize) { | |
503 | char msg[128]; | |
504 | printIndent(out, converter, indent); | |
505 | sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", | |
506 | (long)len, (long)truncsize/2); | |
507 | printCString(out, converter, msg, -1); | |
508 | len = truncsize; | |
509 | } | |
510 | if(U_SUCCESS(*status)) { | |
374ca955 A |
511 | static const UChar openStr[] = { 0x003A, 0x0061, 0x006C, 0x0069, 0x0061, 0x0073, 0x0020, 0x007B, 0x0020, 0x0022 }; /* ":alias { \"" */ |
512 | static const UChar closeStr[] = { 0x0022, 0x0020, 0x007D, 0x0020 }; /* "\" } " */ | |
b75a7d8f A |
513 | printIndent(out, converter, indent); |
514 | if(key != NULL) { | |
515 | printCString(out, converter, key, -1); | |
516 | } | |
374ca955 | 517 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f | 518 | printString(out, converter, string, len); |
374ca955 | 519 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
520 | if(verbose) { |
521 | printCString(out, converter, " // ALIAS", -1); | |
522 | } | |
523 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
524 | } else { | |
525 | reportError(pname, status, "getting binary value"); | |
526 | } | |
527 | } | |
528 | ||
529 | static void printOutBundle(FILE *out, UConverter *converter, UResourceBundle *resource, int32_t indent, const char *pname, UErrorCode *status) | |
530 | { | |
531 | static const UChar cr[] = { '\n' }; | |
532 | ||
533 | /* int32_t noOfElements = ures_getSize(resource);*/ | |
534 | int32_t i = 0; | |
535 | const char *key = ures_getKey(resource); | |
536 | ||
537 | switch(ures_getType(resource)) { | |
538 | case RES_STRING : | |
539 | { | |
540 | int32_t len=0; | |
541 | const UChar* thestr = ures_getString(resource, &len, status); | |
542 | UChar *string = quotedString(thestr); | |
543 | ||
544 | /* TODO: String truncation */ | |
545 | if(trunc && len > truncsize) { | |
546 | char msg[128]; | |
547 | printIndent(out, converter, indent); | |
548 | sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", | |
549 | (long)len, (long)(truncsize/2)); | |
550 | printCString(out, converter, msg, -1); | |
551 | len = truncsize/2; | |
552 | } | |
553 | printIndent(out, converter, indent); | |
554 | if(key != NULL) { | |
374ca955 A |
555 | static const UChar openStr[] = { 0x0020, 0x007B, 0x0020, 0x0022 }; /* " { \"" */ |
556 | static const UChar closeStr[] = { 0x0022, 0x0020, 0x007D }; /* "\" }" */ | |
b75a7d8f | 557 | printCString(out, converter, key, (int32_t)uprv_strlen(key)); |
374ca955 | 558 | printString(out, converter, openStr, (int32_t)(sizeof(openStr)/sizeof(*openStr))); |
b75a7d8f | 559 | printString(out, converter, string, len); |
374ca955 | 560 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f | 561 | } else { |
374ca955 A |
562 | static const UChar openStr[] = { 0x0022 }; /* "\"" */ |
563 | static const UChar closeStr[] = { 0x0022, 0x002C }; /* "\"," */ | |
b75a7d8f | 564 | |
374ca955 | 565 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f | 566 | printString(out, converter, string, (int32_t)(u_strlen(string))); |
374ca955 | 567 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
568 | } |
569 | ||
570 | if(verbose) { | |
571 | printCString(out, converter, "// STRING", -1); | |
572 | } | |
573 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
574 | ||
575 | uprv_free(string); | |
576 | } | |
577 | break; | |
578 | ||
579 | case RES_INT : | |
580 | { | |
374ca955 A |
581 | static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0020, 0x007B, 0x0020 }; /* ":int { " */ |
582 | static const UChar closeStr[] = { 0x0020, 0x007D }; /* " }" */ | |
b75a7d8f A |
583 | UChar num[20]; |
584 | ||
585 | printIndent(out, converter, indent); | |
586 | if(key != NULL) { | |
587 | printCString(out, converter, key, -1); | |
588 | } | |
374ca955 | 589 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f A |
590 | uprv_itou(num, 20, ures_getInt(resource, status), 10, 0); |
591 | printString(out, converter, num, u_strlen(num)); | |
374ca955 | 592 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
593 | |
594 | if(verbose) { | |
595 | printCString(out, converter, "// INT", -1); | |
596 | } | |
597 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
598 | break; | |
599 | } | |
600 | case RES_BINARY : | |
601 | { | |
602 | int32_t len = 0; | |
603 | const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status); | |
604 | if(trunc && len > truncsize) { | |
605 | char msg[128]; | |
606 | printIndent(out, converter, indent); | |
607 | sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", | |
608 | (long)len, (long)(truncsize/2)); | |
609 | printCString(out, converter, msg, -1); | |
610 | len = truncsize; | |
611 | } | |
612 | if(U_SUCCESS(*status)) { | |
374ca955 A |
613 | static const UChar openStr[] = { 0x003A, 0x0062, 0x0069, 0x006E, 0x0061, 0x0072, 0x0079, 0x0020, 0x007B, 0x0020 }; /* ":binary { " */ |
614 | static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ | |
b75a7d8f A |
615 | printIndent(out, converter, indent); |
616 | if(key != NULL) { | |
617 | printCString(out, converter, key, -1); | |
618 | } | |
374ca955 | 619 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f A |
620 | for(i = 0; i<len; i++) { |
621 | printHex(out, converter, *data++); | |
622 | } | |
374ca955 | 623 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
624 | if(verbose) { |
625 | printCString(out, converter, " // BINARY", -1); | |
626 | } | |
627 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
628 | } else { | |
629 | reportError(pname, status, "getting binary value"); | |
630 | } | |
631 | } | |
632 | break; | |
633 | case RES_INT_VECTOR : | |
634 | { | |
635 | int32_t len = 0; | |
636 | const int32_t *data = ures_getIntVector(resource, &len, status); | |
637 | if(U_SUCCESS(*status)) { | |
374ca955 A |
638 | static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0076, 0x0065, 0x0063, 0x0074, 0x006F, 0x0072, 0x0020, 0x007B, 0x0020 }; /* ":intvector { " */ |
639 | static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ | |
b75a7d8f A |
640 | UChar num[20]; |
641 | ||
642 | printIndent(out, converter, indent); | |
643 | if(key != NULL) { | |
644 | printCString(out, converter, key, -1); | |
645 | } | |
374ca955 | 646 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f A |
647 | for(i = 0; i < len - 1; i++) { |
648 | int32_t numLen = uprv_itou(num, 20, data[i], 10, 0); | |
649 | num[numLen++] = 0x002C; /* ',' */ | |
650 | num[numLen++] = 0x0020; /* ' ' */ | |
651 | num[numLen] = 0; | |
652 | printString(out, converter, num, u_strlen(num)); | |
653 | } | |
654 | if(len > 0) { | |
655 | uprv_itou(num, 20, data[len - 1], 10, 0); | |
656 | printString(out, converter, num, u_strlen(num)); | |
657 | } | |
374ca955 | 658 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
659 | if(verbose) { |
660 | printCString(out, converter, "// INTVECTOR", -1); | |
661 | } | |
662 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
663 | } else { | |
664 | reportError(pname, status, "getting int vector"); | |
665 | } | |
666 | } | |
667 | break; | |
668 | case RES_TABLE : | |
669 | case RES_ARRAY : | |
670 | { | |
374ca955 A |
671 | static const UChar openStr[] = { 0x007B }; /* "{" */ |
672 | static const UChar closeStr[] = { 0x007D, '\n' }; /* "}\n" */ | |
b75a7d8f A |
673 | |
674 | UResourceBundle *t = NULL; | |
675 | ures_resetIterator(resource); | |
676 | printIndent(out, converter, indent); | |
677 | if(key != NULL) { | |
678 | printCString(out, converter, key, -1); | |
679 | } | |
374ca955 | 680 | printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); |
b75a7d8f A |
681 | if(verbose) { |
682 | if(ures_getType(resource) == RES_TABLE) { | |
683 | printCString(out, converter, "// TABLE", -1); | |
684 | } else { | |
685 | printCString(out, converter, "// ARRAY", -1); | |
686 | } | |
687 | } | |
688 | printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); | |
689 | ||
690 | if(suppressAliases == FALSE) { | |
691 | while(U_SUCCESS(*status) && ures_hasNext(resource)) { | |
692 | t = ures_getNextResource(resource, t, status); | |
693 | if(U_SUCCESS(*status)) { | |
694 | printOutBundle(out, converter, t, indent+indentsize, pname, status); | |
695 | } else { | |
696 | reportError(pname, status, "While processing table"); | |
697 | *status = U_ZERO_ERROR; | |
698 | } | |
699 | } | |
700 | } else { /* we have to use low level access to do this */ | |
701 | Resource r = RES_BOGUS; | |
702 | for(i = 0; i < ures_getSize(resource); i++) { | |
703 | /* need to know if it's an alias */ | |
704 | if(ures_getType(resource) == RES_TABLE) { | |
705 | r = derb_getTableItem(resource->fResData.pRoot, resource->fRes, (int16_t)i); | |
706 | key = derb_getTableKey(resource->fResData.pRoot, resource->fRes, (int16_t)i); | |
707 | } else { | |
708 | r = derb_getArrayItem(resource->fResData.pRoot, resource->fRes, i); | |
709 | } | |
710 | if(U_SUCCESS(*status)) { | |
711 | if(RES_GET_TYPE(r) == RES_ALIAS) { | |
712 | printOutAlias(out, converter, resource, r, key, indent+indentsize, pname, status); | |
713 | } else { | |
714 | t = ures_getByIndex(resource, i, t, status); | |
715 | printOutBundle(out, converter, t, indent+indentsize, pname, status); | |
716 | } | |
717 | } else { | |
718 | reportError(pname, status, "While processing table"); | |
719 | *status = U_ZERO_ERROR; | |
720 | } | |
721 | } | |
722 | } | |
723 | ||
724 | printIndent(out, converter, indent); | |
374ca955 | 725 | printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); |
b75a7d8f A |
726 | ures_close(t); |
727 | } | |
728 | break; | |
729 | default: | |
730 | break; | |
731 | } | |
732 | ||
733 | } | |
734 | ||
735 | static const char *getEncodingName(const char *encoding) { | |
736 | UErrorCode err; | |
737 | const char *enc; | |
738 | ||
739 | err = U_ZERO_ERROR; | |
740 | if (!(enc = ucnv_getStandardName(encoding, "MIME", &err))) { | |
741 | err = U_ZERO_ERROR; | |
742 | if (!(enc = ucnv_getStandardName(encoding, "IANA", &err))) { | |
743 | ; | |
744 | } | |
745 | } | |
746 | ||
747 | return enc; | |
748 | } | |
749 | ||
750 | static void reportError(const char *pname, UErrorCode *status, const char *when) { | |
751 | fprintf(stderr, "%s: error %d while %s: %s\n", pname, *status, when, u_errorName(*status)); | |
752 | } | |
753 | ||
754 | /* | |
755 | * Local Variables: | |
756 | * indent-tabs-mode: nil | |
757 | * End: | |
758 | */ | |
759 | ||
760 |