• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 1999-2007, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *   file name:  uresb.c
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2000sep6
14 *   created by: Vladimir Weinstein
15 */
16 
17 /******************************************************************************
18  * This program prints out resource bundles - example for
19  * ICU workshop
20  * TODO: make a complete i18n layout for this program.
21  ******************************************************************************/
22 
23 #include "unicode/putil.h"
24 #include "unicode/ures.h"
25 #include "unicode/ustdio.h"
26 #include "unicode/uloc.h"
27 #include "unicode/ustring.h"
28 #include "uoptions.h"
29 #include "toolutil.h"
30 
31 #include <string.h>
32 #include <stdlib.h>
33 #ifdef WIN32
34 #include <direct.h>
35 #else
36 #include <unistd.h>
37 #endif
38 
39 #define URESB_DEFAULTTRUNC 40
40 
41 static char *currdir = NULL;
42 /*--locale sr_YU and --encoding cp855
43  * are interesting on Win32
44  */
45 
46 static const char *locale = NULL;
47 static const char *encoding = NULL;
48 static const char *resPath = NULL;
49 static const int32_t indentsize = 4;
50 static UFILE *outerr = NULL;
51 static int32_t truncsize = URESB_DEFAULTTRUNC;
52 static UBool trunc = FALSE;
53 
54 const UChar baderror[] = { 0x0042, 0x0041, 0x0044, 0x0000 };
55 
56 const UChar *getErrorName(UErrorCode errorNumber);
57 void reportError(UErrorCode *status);
58 static UChar *quotedString(const UChar *string);
59 void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, UErrorCode *status);
60 void printIndent(UFILE *out, int32_t indent);
61 void printHex(UFILE *out, const int8_t *what);
62 
63 static UOption options[]={
64     UOPTION_HELP_H,
65     UOPTION_HELP_QUESTION_MARK,
66     { "locale", NULL, NULL, NULL, 'l', UOPT_REQUIRES_ARG, 0 },
67     UOPTION_ENCODING,
68     { "path", NULL, NULL, NULL, 'p', UOPT_OPTIONAL_ARG, 0 },
69     { "truncate", NULL, NULL, NULL, 't', UOPT_OPTIONAL_ARG, 0 },
70     UOPTION_VERBOSE
71 };
72 
73 static UBool VERBOSE = FALSE;
74 
75 extern int
main(int argc,char * argv[])76 main(int argc, char* argv[]) {
77 
78     UResourceBundle *bundle = NULL;
79     UErrorCode status = U_ZERO_ERROR;
80     UFILE *out = NULL;
81     int32_t i = 0;
82     const char* arg;
83     char resPathBuffer[1024];
84 #ifdef WIN32
85     currdir = _getcwd(NULL, 0);
86 #else
87     currdir = getcwd(NULL, 0);
88 #endif
89 
90     argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
91 
92     /* error handling, printing usage message */
93     if(argc<0) {
94         fprintf(stderr,
95             "error in command line argument \"%s\"\n",
96             argv[-argc]);
97     }
98     if(argc<2 || options[0].doesOccur || options[1].doesOccur) {
99         fprintf(stderr,
100             "usage: %s [-options] locale(s)\n",
101             argv[0]);
102         return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
103     }
104 
105     if(options[2].doesOccur) {
106         locale = options[2].value;
107     } else {
108         locale = 0;
109     }
110 
111     if(options[3].doesOccur) {
112         encoding = options[3].value;
113     } else {
114         encoding = NULL;
115     }
116 
117     if(options[4].doesOccur) {
118         if(options[4].value != NULL) {
119             resPath = options[4].value; /* we'll use users resources */
120         } else {
121             resPath = NULL; /* we'll use ICU system resources for dumping */
122         }
123     } else {
124         strcpy(resPathBuffer, currdir);
125         /*strcat(resPathBuffer, U_FILE_SEP_STRING);
126         strcat(resPathBuffer, "uresb");*/
127         resPath = resPathBuffer; /* we'll just dump uresb samples resources */
128     }
129 
130     if(options[5].doesOccur) {
131         trunc = TRUE;
132         if(options[5].value != NULL) {
133             truncsize = atoi(options[5].value); /* user defined printable size */
134         } else {
135             truncsize = URESB_DEFAULTTRUNC; /* we'll use default omitting size */
136         }
137     } else {
138         trunc = FALSE;
139     }
140 
141     if(options[6].doesOccur) {
142         VERBOSE = TRUE;
143     }
144 
145     outerr = u_finit(stderr, locale, encoding);
146     out = u_finit(stdout, locale, encoding);
147 
148     for(i = 1; i < argc; ++i) {
149         status = U_ZERO_ERROR;
150         arg = getLongPathname(argv[i]);
151 
152         u_fprintf(out, "uresb: processing file \"%s\" in path \"%s\"\n", arg, resPath);
153         bundle = ures_open(resPath, arg, &status);
154         if(U_SUCCESS(status)) {
155             u_fprintf(out, "%s\n", arg);
156             printOutBundle(out, bundle, 0, &status);
157         } else {
158             reportError(&status);
159         }
160 
161         ures_close(bundle);
162     }
163 
164 
165 
166     u_fclose(out);
167     u_fclose(outerr);
168     return 0;
169 }
170 
printIndent(UFILE * out,int32_t indent)171 void printIndent(UFILE *out, int32_t indent) {
172     char inchar[256];
173     int32_t i = 0;
174     for(i = 0; i<indent; i++) {
175         inchar[i] = ' ';
176     }
177     inchar[indent] = '\0';
178     u_fprintf(out, "%s", inchar);
179 }
180 
printHex(UFILE * out,const int8_t * what)181 void printHex(UFILE *out, const int8_t *what) {
182   u_fprintf(out, "%02X", (uint8_t)*what);
183 }
184 
quotedString(const UChar * string)185 static UChar *quotedString(const UChar *string) {
186     int len = u_strlen(string);
187     int alen = len;
188     const UChar *sp;
189     UChar *newstr, *np;
190 
191     for (sp = string; *sp; ++sp) {
192         switch (*sp) {
193             case '\n':
194             case 0x0022:
195                 ++alen;
196                 break;
197         }
198     }
199 
200     newstr = (UChar *) malloc((1 + alen) * sizeof(*newstr));
201     for (sp = string, np = newstr; *sp; ++sp) {
202         switch (*sp) {
203             case '\n':
204                 *np++ = 0x005C;
205                 *np++ = 0x006E;
206                 break;
207 
208             case 0x0022:
209                 *np++ = 0x005C;
210 
211             default:
212                 *np++ = *sp;
213                 break;
214         }
215     }
216     *np = 0;
217 
218     return newstr;
219 }
220 
printOutBundle(UFILE * out,UResourceBundle * resource,int32_t indent,UErrorCode * status)221 void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, UErrorCode *status) {
222     int32_t i = 0;
223     const char *key = ures_getKey(resource);
224 
225     switch(ures_getType(resource)) {
226     case URES_STRING :
227         {
228             int32_t len=0;
229             const UChar*thestr = ures_getString(resource, &len, status);
230             UChar *string = quotedString(thestr);
231 
232             /* TODO: String truncation */
233             /*
234             if(trunc && len > truncsize) {
235                 printIndent(out, indent);
236                 u_fprintf(out, "// WARNING: this string, size %d is truncated to %d\n", len, truncsize/2);
237                 len = truncsize/2;
238             }
239             */
240             printIndent(out, indent);
241             if(key != NULL) {
242                 u_fprintf(out, "%s { \"%S\" } ", key, string);
243             } else {
244                 u_fprintf(out, "\"%S\",", string);
245             }
246             if(VERBOSE) {
247                 u_fprintf(out, " // STRING");
248             }
249             u_fprintf(out, "\n");
250             free(string);
251         }
252         break;
253     case URES_INT :
254         printIndent(out, indent);
255         if(key != NULL) {
256             u_fprintf(out, "%s", key);
257         }
258         u_fprintf(out, ":int { %li } ", ures_getInt(resource, status));
259 
260         if(VERBOSE) {
261             u_fprintf(out, " // INT");
262         }
263         u_fprintf(out, "\n");
264         break;
265     case URES_BINARY :
266         {
267             int32_t len = 0;
268             const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status);
269             if(trunc && len > truncsize) {
270                 printIndent(out, indent);
271                 u_fprintf(out, "// WARNING: this resource, size %li is truncated to %li\n", len, truncsize/2);
272                 len = truncsize/2;
273             }
274             if(U_SUCCESS(*status)) {
275                 printIndent(out, indent);
276                 if(key != NULL) {
277                     u_fprintf(out, "%s", key);
278                 }
279                 u_fprintf(out, ":binary { ");
280                 for(i = 0; i<len; i++) {
281                     printHex(out, data++);
282                 }
283                 u_fprintf(out, " }");
284                 if(VERBOSE) {
285                     u_fprintf(out, " // BINARY");
286                 }
287                 u_fprintf(out, "\n");
288 
289             } else {
290                 reportError(status);
291             }
292         }
293         break;
294     case URES_INT_VECTOR :
295       {
296           int32_t len = 0;
297           const int32_t *data = ures_getIntVector(resource, &len, status);
298           if(U_SUCCESS(*status)) {
299               printIndent(out, indent);
300               if(key != NULL) {
301                   u_fprintf(out, "%s", key);
302               }
303               u_fprintf(out, ":intvector { ");
304               for(i = 0; i<len-1; i++) {
305                   u_fprintf(out, "%d, ", data[i]);
306               }
307               if(len > 0) {
308                   u_fprintf(out, "%d ", data[len-1]);
309               }
310               u_fprintf(out, "}");
311               if(VERBOSE) {
312                   u_fprintf(out, " // INTVECTOR");
313               }
314               u_fprintf(out, "\n");
315 
316           } else {
317               reportError(status);
318           }
319       }
320       break;
321     case URES_TABLE :
322     case URES_ARRAY :
323         {
324             UResourceBundle *t = NULL;
325             ures_resetIterator(resource);
326             printIndent(out, indent);
327             if(key != NULL) {
328                 u_fprintf(out, "%s ", key);
329             }
330             u_fprintf(out, "{");
331             if(VERBOSE) {
332                 if(ures_getType(resource) == URES_TABLE) {
333                     u_fprintf(out, " // TABLE");
334                 } else {
335                     u_fprintf(out, " // ARRAY");
336                 }
337             }
338             u_fprintf(out, "\n");
339 
340             while(ures_hasNext(resource)) {
341                 t = ures_getNextResource(resource, t, status);
342                 printOutBundle(out, t, indent+indentsize, status);
343             }
344 
345             printIndent(out, indent);
346             u_fprintf(out, "}\n");
347             ures_close(t);
348         }
349         break;
350     default:
351         break;
352     }
353 
354 }
355 
reportError(UErrorCode * status)356 void reportError(UErrorCode *status) {
357     u_fprintf(outerr, "Error %d(%s) : %U happened!\n", *status, u_errorName(*status), getErrorName(*status));
358 }
359 
360 
getErrorName(UErrorCode errorNumber)361 const UChar *getErrorName(UErrorCode errorNumber) {
362     UErrorCode status = U_ZERO_ERROR;
363     int32_t len = 0;
364 
365     UResourceBundle *error = ures_open(currdir, locale, &status);
366 
367     UResourceBundle *errorcodes = ures_getByKey(error, "errorcodes", NULL, &status);
368 
369     const UChar *result = ures_getStringByIndex(errorcodes, errorNumber, &len, &status);
370 
371     ures_close(errorcodes);
372     ures_close(error);
373 
374     if(U_SUCCESS(status)) {
375         return result;
376     } else {
377         return baderror;
378     }
379 
380 }
381