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