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 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 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 181 void printHex(UFILE *out, const int8_t *what) { 182 u_fprintf(out, "%02X", (uint8_t)*what); 183 } 184 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 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 356 void reportError(UErrorCode *status) { 357 u_fprintf(outerr, "Error %d(%s) : %U happened!\n", *status, u_errorName(*status), getErrorName(*status)); 358 } 359 360 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