]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/tools/genrb/wrtxml.cpp
ICU-400.37.tar.gz
[apple/icu.git] / icuSources / tools / genrb / wrtxml.cpp
... / ...
CommitLineData
1/*
2*******************************************************************************
3*
4* Copyright (C) 2002-2008, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
8*
9* File wrtxml.c
10*
11* Modification History:
12*
13* Date Name Description
14* 10/01/02 Ram Creation.
15* 02/07/08 Spieth Correct XLIFF generation on EBCDIC platform
16*
17*******************************************************************************
18*/
19#include "reslist.h"
20#include "unewdata.h"
21#include "unicode/ures.h"
22#include "errmsg.h"
23#include "filestrm.h"
24#include "cstring.h"
25#include "unicode/ucnv.h"
26#include "genrb.h"
27#include "rle.h"
28#include "ucol_tok.h"
29#include "uhash.h"
30#include "uresimp.h"
31#include "unicode/ustring.h"
32#include "unicode/uchar.h"
33#include "ustr.h"
34#include "prscmnts.h"
35#include "unicode/unistr.h"
36#include <time.h>
37
38U_NAMESPACE_USE
39
40static int tabCount = 0;
41
42static FileStream* out=NULL;
43static struct SRBRoot* srBundle ;
44static const char* outDir = NULL;
45static const char* enc ="";
46static UConverter* conv = NULL;
47
48const char* const* ISOLanguages;
49const char* const* ISOCountries;
50const char* textExt = ".txt";
51const char* xliffExt = ".xlf";
52
53static void write_utf8_file(UnicodeString outString, FileStream * outFile, UErrorCode *status){
54 char* dest = (char*)uprv_malloc((outString.length() * 3 /2));
55 int32_t len = 0;
56 u_strToUTF8(dest,outString.length() * 3 /2,&len,outString.getBuffer(),outString.length(),status);
57
58 T_FileStream_write(outFile, dest, len);
59 uprv_free(dest);
60}
61
62
63/*write indentation for formatting*/
64static void write_tabs(UnicodeString *Accumulator){
65 int i=0;
66 for(;i<=tabCount;i++){
67 Accumulator->append(UnicodeString(" "));
68 //FileStream_write(os," ",4);
69 }
70}
71
72/*get ID for each element. ID is globally unique.*/
73static char* getID(const char* id, char* curKey, char* result) {
74 if(curKey == NULL) {
75 result = (char *)uprv_malloc(sizeof(char)*uprv_strlen(id) + 1);
76 uprv_memset(result, 0, sizeof(char)*uprv_strlen(id) + 1);
77 uprv_strcpy(result, id);
78 } else {
79 result = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(id) + 1 + uprv_strlen(curKey)) + 1);
80 uprv_memset(result, 0, sizeof(char)*(uprv_strlen(id) + 1 + uprv_strlen(curKey)) + 1);
81 if(id[0]!='\0'){
82 uprv_strcpy(result, id);
83 uprv_strcat(result, "_");
84 }
85 uprv_strcat(result, curKey);
86 }
87 return result;
88}
89
90/*compute CRC for binary code*/
91/* The code is from http://www.theorem.com/java/CRC32.java
92 * Calculates the CRC32 - 32 bit Cyclical Redundancy Check
93 * <P> This check is used in numerous systems to verify the integrity
94 * of information. It's also used as a hashing function. Unlike a regular
95 * checksum, it's sensitive to the order of the characters.
96 * It produces a 32 bit
97 *
98 * @author Michael Lecuyer (mjl@theorem.com)
99 * @version 1.1 August 11, 1998
100 */
101
102/* ICU is not endian portable, because ICU data generated on big endian machines can be
103 * ported to big endian machines but not to little endian machines and vice versa. The
104 * conversion is not portable across platforms with different endianess.
105 */
106
107static uint32_t computeCRC(char *ptr, uint32_t len, uint32_t lastcrc){
108 int32_t crc;
109 uint32_t temp1;
110 uint32_t temp2;
111
112 int32_t crc_ta[256];
113 int i = 0;
114 int j = 0;
115 uint32_t crc2 = 0;
116
117#define CRC32_POLYNOMIAL 0xEDB88320
118
119 /*build crc table*/
120 for (i = 0; i <= 255; i++) {
121 crc2 = i;
122 for (j = 8; j > 0; j--) {
123 if ((crc2 & 1) == 1) {
124 crc2 = (crc2 >> 1) ^ CRC32_POLYNOMIAL;
125 } else {
126 crc2 >>= 1;
127 }
128 }
129 crc_ta[i] = crc2;
130 }
131
132 crc = lastcrc;
133 while(len--!=0) {
134 temp1 = (uint32_t)crc>>8;
135 temp2 = crc_ta[(crc^*ptr) & 0xFF];
136 crc = temp1^temp2;
137 ptr++;
138 }
139 return(crc);
140}
141
142static void strnrepchr(char* src, int32_t srcLen, char s, char r){
143 int32_t i = 0;
144 for(i=0;i<srcLen;i++){
145 if(src[i]==s){
146 src[i]=r;
147 }
148 }
149}
150/* Parse the filename, and get its language information.
151 * If it fails to get the language information from the filename,
152 * use "en" as the default value for language
153 */
154static char* parseFilename(const char* id, char* lang) {
155 int idLen = (int) uprv_strlen(id);
156 char* localeID = (char*) uprv_malloc(idLen);
157 int pos = 0;
158 int canonCapacity = 0;
159 char* canon = NULL;
160 int canonLen = 0;
161 /*int i;*/
162 UErrorCode status = U_ZERO_ERROR;
163 const char *ext = uprv_strchr(id, '.');
164
165 if(ext != NULL){
166 pos = (int) (ext - id);
167 } else {
168 pos = idLen;
169 }
170 uprv_memcpy(localeID, id, pos);
171 localeID[pos]=0; /* NUL terminate the string */
172
173 canonCapacity =pos*3;
174 canon = (char*) uprv_malloc(canonCapacity);
175 canonLen = uloc_canonicalize(localeID, canon, canonCapacity, &status);
176
177 if(U_FAILURE(status)){
178 fprintf(stderr, "Could not canonicalize the locale ID: %s. Error: %s\n", localeID, u_errorName(status));
179 exit(status);
180 }
181 strnrepchr(canon, canonLen, '_', '-');
182 return canon;
183}
184
185static const char* xmlHeader = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
186#if 0
187static const char* bundleStart = "<xliff version = \"1.2\" "
188 "xmlns='urn:oasis:names:tc:xliff:document:1.2' "
189 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
190 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'>\n";
191#else
192static const char* bundleStart = "<xliff version = \"1.1\" "
193 "xmlns='urn:oasis:names:tc:xliff:document:1.1' "
194 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
195 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd'>\n";
196#endif
197static const char* bundleEnd = "</xliff>\n";
198
199void res_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UBool isTopLevel, UErrorCode *status);
200
201static char* convertAndEscape(char** pDest, int32_t destCap, int32_t* destLength,
202 const UChar* src, int32_t srcLen, UErrorCode* status){
203 int32_t srcIndex=0;
204 char* dest=NULL;
205 char* temp=NULL;
206 int32_t destLen=0;
207 UChar32 c = 0;
208
209 if(status==NULL || U_FAILURE(*status) || pDest==NULL || srcLen==0 || src == NULL){
210 return NULL;
211 }
212 dest =*pDest;
213 if(dest==NULL || destCap <=0){
214 destCap = srcLen * 8;
215 dest = (char*) uprv_malloc(sizeof(char) * destCap);
216 if(dest==NULL){
217 *status=U_MEMORY_ALLOCATION_ERROR;
218 return NULL;
219 }
220 }
221
222 dest[0]=0;
223
224 while(srcIndex<srcLen){
225 U16_NEXT(src, srcIndex, srcLen, c);
226
227 if (U16_IS_LEAD(c) || U16_IS_TRAIL(c)) {
228 *status = U_ILLEGAL_CHAR_FOUND;
229 fprintf(stderr, "Illegal Surrogate! \n");
230 uprv_free(dest);
231 return NULL;
232 }
233
234 if((destLen+UTF8_CHAR_LENGTH(c)) < destCap){
235
236 /* ASCII Range */
237 if(c <=0x007F){
238 switch(c) {
239 case '\x26':
240 uprv_strcpy(dest+( destLen),"\x26\x61\x6d\x70\x3b"); /* &amp;*/
241 destLen+=(int32_t)uprv_strlen("\x26\x61\x6d\x70\x3b");
242 break;
243 case '\x3c':
244 uprv_strcpy(dest+(destLen),"\x26\x6c\x74\x3b"); /* &lt;*/
245 destLen+=(int32_t)uprv_strlen("\x26\x6c\x74\x3b");
246 break;
247 case '\x3e':
248 uprv_strcpy(dest+(destLen),"\x26\x67\x74\x3b"); /* &gt;*/
249 destLen+=(int32_t)uprv_strlen("\x26\x67\x74\x3b");
250 break;
251 case '\x22':
252 uprv_strcpy(dest+(destLen),"\x26\x71\x75\x6f\x74\x3b"); /* &quot;*/
253 destLen+=(int32_t)uprv_strlen("\x26\x71\x75\x6f\x74\x3b");
254 break;
255 case '\x27':
256 uprv_strcpy(dest+(destLen),"\x26\x61\x70\x6f\x73\x3b"); /* &apos; */
257 destLen+=(int32_t)uprv_strlen("\x26\x61\x70\x6f\x73\x3b");
258 break;
259
260 /* Disallow C0 controls except TAB, CR, LF*/
261 case 0x00:
262 case 0x01:
263 case 0x02:
264 case 0x03:
265 case 0x04:
266 case 0x05:
267 case 0x06:
268 case 0x07:
269 case 0x08:
270 /*case 0x09:*/
271 /*case 0x0A: */
272 case 0x0B:
273 case 0x0C:
274 /*case 0x0D:*/
275 case 0x0E:
276 case 0x0F:
277 case 0x10:
278 case 0x11:
279 case 0x12:
280 case 0x13:
281 case 0x14:
282 case 0x15:
283 case 0x16:
284 case 0x17:
285 case 0x18:
286 case 0x19:
287 case 0x1A:
288 case 0x1B:
289 case 0x1C:
290 case 0x1D:
291 case 0x1E:
292 case 0x1F:
293 *status = U_ILLEGAL_CHAR_FOUND;
294 fprintf(stderr, "Illegal Character \\u%04X!\n",(int)c);
295 uprv_free(dest);
296 return NULL;
297 default:
298 dest[destLen++]=(char)c;
299 }
300 }else{
301 UBool isError = FALSE;
302 U8_APPEND((unsigned char*)dest,destLen,destCap,c,isError);
303 if(isError){
304 *status = U_ILLEGAL_CHAR_FOUND;
305 fprintf(stderr, "Illegal Character \\U%08X!\n",(int)c);
306 uprv_free(dest);
307 return NULL;
308 }
309 }
310 }else{
311 destCap += destLen;
312
313 temp = (char*) uprv_malloc(sizeof(char)*destCap);
314 if(temp==NULL){
315 *status=U_MEMORY_ALLOCATION_ERROR;
316 uprv_free(dest);
317 return NULL;
318 }
319 uprv_memmove(temp,dest,destLen);
320 destLen=0;
321 uprv_free(dest);
322 dest=temp;
323 temp=NULL;
324 }
325
326 }
327 *destLength = destLen;
328 return dest;
329}
330
331#define ASTERISK 0x002A
332#define SPACE 0x0020
333#define CR 0x000A
334#define LF 0x000D
335#define AT_SIGN 0x0040
336
337static void
338trim(char **src, int32_t *len){
339
340 char *s = NULL;
341 int32_t i = 0;
342 if(src == NULL || *src == NULL){
343 return;
344 }
345 s = *src;
346 /* trim from the end */
347 for( i=(*len-1); i>= 0; i--){
348 switch(s[i]){
349 case ASTERISK:
350 case SPACE:
351 case CR:
352 case LF:
353 s[i] = 0;
354 continue;
355 default:
356 break;
357 }
358 break;
359
360 }
361 *len = i+1;
362}
363
364static void
365print(UnicodeString *Accumulator, UChar* src, int32_t srcLen,const char *tagStart,const char *tagEnd, UErrorCode *status){
366 int32_t bufCapacity = srcLen*4;
367 char *buf = NULL;
368 int32_t bufLen = 0;
369
370 if(U_FAILURE(*status)){
371 return;
372 }
373
374 buf = (char*) (uprv_malloc(bufCapacity));
375 if(buf==0){
376 fprintf(stderr, "Could not allocate memory!!");
377 exit(U_MEMORY_ALLOCATION_ERROR);
378 }
379 buf = convertAndEscape(&buf, bufCapacity, &bufLen, src, srcLen,status);
380 if(U_SUCCESS(*status)){
381 trim(&buf,&bufLen);
382 Accumulator->append(UnicodeString(tagStart));
383 Accumulator->append(UnicodeString(buf, bufLen, "UTF-8"));
384 Accumulator->append(UnicodeString(tagEnd));
385 Accumulator->append(UnicodeString("\n"));
386 //T_FileStream_write(out,tagStart, (int32_t)uprv_strlen(tagStart));
387 //T_FileStream_write(out, buf, bufLen);
388 //T_FileStream_write(out,tagEnd, (int32_t)uprv_strlen(tagEnd));
389 //T_FileStream_write(out,"\n",1);
390
391 }
392}
393static void
394printNoteElements(UnicodeString *Accumulator, struct UString *src, UErrorCode *status){
395
396#if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
397
398 int32_t capacity = 0;
399 UChar* note = NULL;
400 int32_t noteLen = 0;
401 int32_t count = 0,i;
402
403 if(src == NULL){
404 return;
405 }
406
407 capacity = src->fLength;
408 note = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * capacity);
409
410 count = getCount(src->fChars,src->fLength, UPC_NOTE, status);
411 if(U_FAILURE(*status)){
412 uprv_free(note);
413 return;
414 }
415 for(i=0; i < count; i++){
416 noteLen = getAt(src->fChars,src->fLength, &note, capacity, i, UPC_NOTE, status);
417 if(U_FAILURE(*status)){
418 uprv_free(note);
419 return;
420 }
421 if(noteLen > 0){
422 write_tabs(Accumulator);
423 print(Accumulator, note, noteLen,"<note>", "</note>", status);
424 }
425 }
426 uprv_free(note);
427#else
428
429 fprintf(stderr, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
430
431#endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
432
433}
434
435static void printAttribute(UnicodeString *Accumulator, const char *name, const char *value, int32_t len)
436{
437 Accumulator->append(UnicodeString(" "));
438 Accumulator->append(UnicodeString(name));
439 Accumulator->append(UnicodeString(" = \""));
440 Accumulator->append(UnicodeString(value));
441 Accumulator->append(UnicodeString("\""));
442 //T_FileStream_write(out, " ", 1);
443 //T_FileStream_write(out, name, (int32_t) uprv_strlen(name));
444 //T_FileStream_write(out, " = \"", 4);
445 //T_FileStream_write(out, value, (int32_t) len);
446 //T_FileStream_write(out, "\"", 1);
447}
448
449static void printAttribute(UnicodeString *Accumulator, const char *name, const UnicodeString value, int32_t len)
450{
451 Accumulator->append(UnicodeString(" "));
452 Accumulator->append(UnicodeString(name));
453 Accumulator->append(UnicodeString(" = \""));
454 Accumulator->append(value);
455 Accumulator->append(UnicodeString("\""));
456 //T_FileStream_write(out, " ", 1);
457 //T_FileStream_write(out, name, (int32_t) uprv_strlen(name));
458 //T_FileStream_write(out, " = \"", 4);
459 //T_FileStream_write(out, value, (int32_t) len);
460 //T_FileStream_write(out, "\"", 1);
461}
462
463static void
464printComments(UnicodeString *Accumulator, struct UString *src, const char *resName, UBool printTranslate, UErrorCode *status){
465
466#if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
467
468 if(status==NULL || U_FAILURE(*status)){
469 return;
470 }
471
472 int32_t capacity = src->fLength + 1;
473 char* buf = NULL;
474 int32_t bufLen = 0;
475 UChar* desc = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * capacity);
476 UChar* trans = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * capacity);
477
478 int32_t descLen = 0, transLen=0;
479 if(desc==NULL || trans==NULL){
480 *status = U_MEMORY_ALLOCATION_ERROR;
481 uprv_free(desc);
482 uprv_free(trans);
483 return;
484 }
485 src->fLength = removeCmtText(src->fChars, src->fLength, status);
486 descLen = getDescription(src->fChars,src->fLength, &desc, capacity, status);
487 transLen = getTranslate(src->fChars,src->fLength, &trans, capacity, status);
488
489 /* first print translate attribute */
490 if(transLen > 0){
491 if(printTranslate){
492 /* print translate attribute */
493 buf = convertAndEscape(&buf, 0, &bufLen, trans, transLen, status);
494 if(U_SUCCESS(*status)){
495 printAttribute(Accumulator, "translate", UnicodeString(buf, bufLen, "UTF-8"), bufLen);
496 Accumulator->append(UnicodeString(">\n"));
497 //T_FileStream_write(out,">\n", 2);
498 }
499 }else if(getShowWarning()){
500 fprintf(stderr, "Warning: Tranlate attribute for resource %s cannot be set. XLIFF prohibits it.\n", resName);
501 /* no translate attribute .. just close the tag */
502 Accumulator->append(UnicodeString(">\n"));
503 //T_FileStream_write(out,">\n", 2);
504 }
505 }else{
506 /* no translate attribute .. just close the tag */
507 Accumulator->append(UnicodeString(">\n"));
508 //T_FileStream_write(out,">\n", 2);
509 }
510
511 if(descLen > 0){
512 write_tabs(Accumulator);
513 print(Accumulator, desc, descLen, "<!--", "-->", status);
514 }
515
516 uprv_free(desc);
517 uprv_free(trans);
518#else
519
520 fprintf(stderr, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
521
522#endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
523
524}
525
526/*
527 * Print out a containing element, like:
528 * <trans-unit id = "blah" resname = "blah" restype = "x-id-alias" translate = "no">
529 * <group id "calendar_gregorian" resname = "gregorian" restype = "x-icu-array">
530 */
531static char *printContainer(UnicodeString *Accumulator, struct SResource *res, const char *container, const char *restype, const char *mimetype, const char *id, UErrorCode *status)
532{
533 char *resname = NULL;
534 char *sid = NULL;
535
536 write_tabs(Accumulator);
537
538 if (res->fKey >= 0 && uprv_strcmp(srBundle->fKeys + res->fKey, "") != 0) {
539 resname = srBundle->fKeys + res->fKey;
540 sid = getID(id, resname, sid);
541 } else {
542 sid = getID(id, NULL, sid);
543 }
544
545 Accumulator->append(UnicodeString("<"));
546 Accumulator->append(UnicodeString(container));
547 //T_FileStream_write(out, "<", 1);
548 //T_FileStream_write(out, container, (int32_t) uprv_strlen(container));
549 printAttribute(Accumulator, "id", sid, (int32_t) uprv_strlen(sid));
550
551 if (resname != NULL) {
552 printAttribute(Accumulator,"resname", resname, (int32_t) uprv_strlen(resname));
553 }
554
555 if (mimetype != NULL) {
556 printAttribute(Accumulator,"mime-type", mimetype, (int32_t) uprv_strlen(mimetype));
557 }
558
559 if (restype != NULL) {
560 printAttribute(Accumulator,"restype", restype, (int32_t) uprv_strlen(restype));
561 }
562
563 tabCount += 1;
564 if (res->fComment.fLength > 0) {
565 /* printComments will print the closing ">\n" */
566 printComments(Accumulator, &res->fComment, resname, TRUE, status);
567 } else {
568 Accumulator->append(UnicodeString(">\n"));
569 //T_FileStream_write(out, ">\n", 2);
570 }
571
572 return sid;
573}
574
575/* Writing Functions */
576
577static const char *trans_unit = "trans-unit";
578static const char *close_trans_unit = "</trans-unit>\n";
579static const char *source = "<source>";
580static const char *close_source = "</source>\n";
581static const char *group = "group";
582static const char *close_group = "</group>\n";
583
584static const char *bin_unit = "bin-unit";
585static const char *close_bin_unit = "</bin-unit>\n";
586static const char *bin_source = "<bin-source>\n";
587static const char *close_bin_source = "</bin-source>\n";
588static const char *external_file = "<external-file";
589/*static const char *close_external_file = "</external-file>\n";*/
590static const char *internal_file = "<internal-file";
591static const char *close_internal_file = "</internal-file>\n";
592
593static const char *application_mimetype = "application"; /* add "/octet-stream"? */
594
595static const char *alias_restype = "x-icu-alias";
596static const char *array_restype = "x-icu-array";
597static const char *binary_restype = "x-icu-binary";
598static const char *integer_restype = "x-icu-integer";
599static const char *intvector_restype = "x-icu-intvector";
600static const char *table_restype = "x-icu-table";
601
602static void
603string_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
604
605 char *sid = NULL;
606 char* buf = NULL;
607 int32_t bufLen = 0;
608
609 if(status==NULL || U_FAILURE(*status)){
610 return;
611 }
612
613 sid = printContainer(Accumulator, res, trans_unit, NULL, NULL, id, status);
614
615 write_tabs(Accumulator);
616
617 Accumulator->append(UnicodeString(source));
618 //T_FileStream_write(out, source, (int32_t) uprv_strlen(source));
619
620 buf = convertAndEscape(&buf, 0, &bufLen, res->u.fString.fChars, res->u.fString.fLength, status);
621
622 if (U_FAILURE(*status)) {
623 return;
624 }
625
626 Accumulator->append(UnicodeString(buf, bufLen, "UTF-8"));
627 Accumulator->append(UnicodeString(close_source));
628 //T_FileStream_write(out, buf, bufLen);
629 //T_FileStream_write(out, close_source, (int32_t) uprv_strlen(close_source));
630
631 printNoteElements(Accumulator, &res->fComment, status);
632
633 tabCount -= 1;
634 write_tabs(Accumulator);
635
636 Accumulator->append(UnicodeString(close_trans_unit));
637 //T_FileStream_write(out, close_trans_unit, (int32_t) uprv_strlen(close_trans_unit));
638
639 uprv_free(buf);
640 uprv_free(sid);
641}
642
643static void
644alias_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
645 char *sid = NULL;
646 char* buf = NULL;
647 int32_t bufLen=0;
648
649 sid = printContainer(Accumulator, res, trans_unit, alias_restype, NULL, id, status);
650
651 write_tabs(Accumulator);
652
653 Accumulator->append(UnicodeString(source));
654 //T_FileStream_write(out, source, (int32_t) uprv_strlen(source));
655
656 buf = convertAndEscape(&buf, 0, &bufLen, res->u.fString.fChars, res->u.fString.fLength, status);
657
658 if(U_FAILURE(*status)){
659 return;
660 }
661 Accumulator->append(UnicodeString(buf, bufLen, "UTF-8"));
662 //T_FileStream_write(out, buf, bufLen);
663 Accumulator->append(UnicodeString(close_source));
664 //T_FileStream_write(out, close_source, (int32_t)uprv_strlen(close_source));
665
666 printNoteElements(Accumulator, &res->fComment, status);
667
668 tabCount -= 1;
669 write_tabs(Accumulator);
670
671 Accumulator->append(UnicodeString(close_trans_unit));
672 //T_FileStream_write(out, close_trans_unit, (int32_t)uprv_strlen(close_trans_unit));
673
674 uprv_free(buf);
675 uprv_free(sid);
676}
677
678static void
679array_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
680 char* sid = NULL;
681 int index = 0;
682
683 struct SResource *current = NULL;
684 struct SResource *first =NULL;
685
686 sid = printContainer(Accumulator, res, group, array_restype, NULL, id, status);
687
688 current = res->u.fArray.fFirst;
689 first=current;
690
691 while (current != NULL) {
692 char c[256] = {0};
693 char* subId = NULL;
694
695 itostr(c, index, 10, 0);
696 index += 1;
697 subId = getID(sid, c, subId);
698
699 res_write_xml(Accumulator, current, subId, language, FALSE, status);
700 uprv_free(subId);
701 subId = NULL;
702
703 if(U_FAILURE(*status)){
704 return;
705 }
706
707 current = current->fNext;
708 }
709
710 tabCount -= 1;
711 write_tabs(Accumulator);
712 Accumulator->append(UnicodeString(close_group));
713 //T_FileStream_write(out, close_group, (int32_t) uprv_strlen(close_group));
714
715 uprv_free(sid);
716}
717
718static void
719intvector_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
720 char* sid = NULL;
721 char* ivd = NULL;
722 uint32_t i=0;
723 uint32_t len=0;
724 char buf[256] = {'0'};
725
726 sid = printContainer(Accumulator, res, group, intvector_restype, NULL, id, status);
727
728 for(i = 0; i < res->u.fIntVector.fCount; i += 1) {
729 char c[256] = {0};
730
731 itostr(c, i, 10, 0);
732 ivd = getID(sid, c, ivd);
733 len = itostr(buf, res->u.fIntVector.fArray[i], 10, 0);
734
735 write_tabs(Accumulator);
736 Accumulator->append(UnicodeString("<"));
737 //T_FileStream_write(out, "<", 1);
738 Accumulator->append(UnicodeString(trans_unit));
739 //T_FileStream_write(out, trans_unit, (int32_t)uprv_strlen(trans_unit));
740
741 printAttribute(Accumulator, "id", ivd, (int32_t)uprv_strlen(ivd));
742 printAttribute(Accumulator, "restype", integer_restype, (int32_t) strlen(integer_restype));
743
744 Accumulator->append(UnicodeString(">\n"));
745 //T_FileStream_write(out,">\n", 2);
746
747 tabCount += 1;
748 write_tabs(Accumulator);
749 Accumulator->append(UnicodeString(source));
750 //T_FileStream_write(out, source, (int32_t)uprv_strlen(source));
751
752 Accumulator->append(UnicodeString(buf, len));
753 //T_FileStream_write(out, buf, len);
754
755 Accumulator->append(UnicodeString(close_source));
756 //T_FileStream_write(out, close_source, (int32_t)uprv_strlen(close_source));
757 tabCount -= 1;
758 write_tabs(Accumulator);
759 Accumulator->append(UnicodeString(close_trans_unit));
760 //T_FileStream_write(out, close_trans_unit, (int32_t)uprv_strlen(close_trans_unit));
761
762 uprv_free(ivd);
763 ivd = NULL;
764 }
765
766 tabCount -= 1;
767 write_tabs(Accumulator);
768
769 Accumulator->append(UnicodeString(close_group));
770 //T_FileStream_write(out, close_group, (int32_t)uprv_strlen(close_group));
771 uprv_free(sid);
772 sid = NULL;
773}
774
775static void
776int_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
777 char* sid = NULL;
778 char buf[256] = {0};
779 uint32_t len = 0;
780
781 sid = printContainer(Accumulator, res, trans_unit, integer_restype, NULL, id, status);
782
783 write_tabs(Accumulator);
784
785 Accumulator->append(UnicodeString(source));
786 //T_FileStream_write(out, source, (int32_t) uprv_strlen(source));
787
788 len = itostr(buf, res->u.fIntValue.fValue, 10, 0);
789 Accumulator->append(UnicodeString(buf, len));
790 //T_FileStream_write(out, buf, len);
791
792 Accumulator->append(UnicodeString(close_source));
793 //T_FileStream_write(out, close_source, (int32_t)uprv_strlen(close_source));
794
795 printNoteElements(Accumulator, &res->fComment, status);
796
797 tabCount -= 1;
798 write_tabs(Accumulator);
799
800 Accumulator->append(UnicodeString(close_trans_unit));
801 //T_FileStream_write(out, close_trans_unit, (int32_t)uprv_strlen(close_trans_unit));
802
803 uprv_free(sid);
804 sid = NULL;
805}
806
807static void
808bin_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UErrorCode *status) {
809 const char* m_type = application_mimetype;
810 char* sid = NULL;
811 uint32_t crc = 0xFFFFFFFF;
812
813 char fileName[1024] ={0};
814 int32_t tLen = ( outDir == NULL) ? 0 :(int32_t)uprv_strlen(outDir);
815 char* fn = (char*) uprv_malloc(sizeof(char) * (tLen+1024 +
816 (res->u.fBinaryValue.fFileName !=NULL ?
817 uprv_strlen(res->u.fBinaryValue.fFileName) :0)));
818 const char* ext = NULL;
819
820 char* f = NULL;
821
822 fn[0]=0;
823
824 if(res->u.fBinaryValue.fFileName != NULL){
825 uprv_strcpy(fileName, res->u.fBinaryValue.fFileName);
826 f = uprv_strrchr(fileName, '\\');
827
828 if (f != NULL) {
829 f++;
830 } else {
831 f = fileName;
832 }
833
834 ext = uprv_strrchr(fileName, '.');
835
836 if (ext == NULL) {
837 fprintf(stderr, "Error: %s is an unknown binary filename type.\n", fileName);
838 exit(U_ILLEGAL_ARGUMENT_ERROR);
839 }
840
841 if(uprv_strcmp(ext, ".jpg")==0 || uprv_strcmp(ext, ".jpeg")==0 || uprv_strcmp(ext, ".gif")==0 ){
842 m_type = "image";
843 } else if(uprv_strcmp(ext, ".wav")==0 || uprv_strcmp(ext, ".au")==0 ){
844 m_type = "audio";
845 } else if(uprv_strcmp(ext, ".avi")==0 || uprv_strcmp(ext, ".mpg")==0 || uprv_strcmp(ext, ".mpeg")==0){
846 m_type = "video";
847 } else if(uprv_strcmp(ext, ".txt")==0 || uprv_strcmp(ext, ".text")==0){
848 m_type = "text";
849 }
850
851 sid = printContainer(Accumulator, res, bin_unit, binary_restype, m_type, id, status);
852
853 write_tabs(Accumulator);
854
855 Accumulator->append(UnicodeString(bin_source));
856 //T_FileStream_write(out, bin_source, (int32_t)uprv_strlen(bin_source));
857
858 tabCount+= 1;
859 write_tabs(Accumulator);
860
861 Accumulator->append(UnicodeString(external_file));
862 //T_FileStream_write(out, external_file, (int32_t)uprv_strlen(external_file));
863 printAttribute(Accumulator, "href", f, (int32_t)uprv_strlen(f));
864 Accumulator->append(UnicodeString("/>\n"));
865 //T_FileStream_write(out, "/>\n", 3);
866 tabCount -= 1;
867 write_tabs(Accumulator);
868
869 Accumulator->append(UnicodeString(close_bin_source));
870 //T_FileStream_write(out, close_bin_source, (int32_t)uprv_strlen(close_bin_source));
871
872 printNoteElements(Accumulator, &res->fComment, status);
873 tabCount -= 1;
874 write_tabs(Accumulator);
875 Accumulator->append(UnicodeString(close_bin_unit));
876 //T_FileStream_write(out, close_bin_unit, (int32_t)uprv_strlen(close_bin_unit));
877 } else {
878 char temp[256] = {0};
879 uint32_t i = 0;
880 int32_t len=0;
881
882 sid = printContainer(Accumulator, res, bin_unit, binary_restype, m_type, id, status);
883
884 write_tabs(Accumulator);
885 Accumulator->append(UnicodeString(bin_source));
886 //T_FileStream_write(out, bin_source, (int32_t)uprv_strlen(bin_source));
887
888 tabCount += 1;
889 write_tabs(Accumulator);
890
891 Accumulator->append(UnicodeString(internal_file));
892 //T_FileStream_write(out, internal_file, (int32_t)uprv_strlen(internal_file));
893 printAttribute(Accumulator, "form", application_mimetype, (int32_t) uprv_strlen(application_mimetype));
894
895 while(i <res->u.fBinaryValue.fLength){
896 len = itostr(temp, res->u.fBinaryValue.fData[i], 16, 2);
897 crc = computeCRC(temp, len, crc);
898 i++;
899 }
900
901 len = itostr(temp, crc, 10, 0);
902 printAttribute(Accumulator, "crc", temp, len);
903
904 Accumulator->append(UnicodeString(">"));
905 //T_FileStream_write(out, ">", 1);
906
907 i = 0;
908 while(i <res->u.fBinaryValue.fLength){
909 len = itostr(temp, res->u.fBinaryValue.fData[i], 16, 2);
910 Accumulator->append(UnicodeString(temp));
911 //T_FileStream_write(out ,temp ,len);
912 i += 1;
913 }
914
915 Accumulator->append(UnicodeString(close_internal_file));
916 //T_FileStream_write(out, close_internal_file, (int32_t)uprv_strlen(close_internal_file));
917
918 tabCount -= 2;
919 write_tabs(Accumulator);
920
921 Accumulator->append(UnicodeString(close_bin_source));
922 //T_FileStream_write(out, close_bin_source, (int32_t)uprv_strlen(close_bin_source));
923 printNoteElements(Accumulator, &res->fComment, status);
924
925 tabCount -= 1;
926 write_tabs(Accumulator);
927 Accumulator->append(UnicodeString(close_bin_unit));
928 //T_FileStream_write(out, close_bin_unit, (int32_t)uprv_strlen(close_bin_unit));
929
930 uprv_free(sid);
931 sid = NULL;
932 }
933
934 uprv_free(fn);
935}
936
937
938
939static void
940table_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UBool isTopLevel, UErrorCode *status) {
941
942 uint32_t i = 0;
943
944 struct SResource *current = NULL;
945 struct SResource *save = NULL;
946 char* sid = NULL;
947
948 if (U_FAILURE(*status)) {
949 return ;
950 }
951
952 sid = printContainer(Accumulator, res, group, table_restype, NULL, id, status);
953
954 if(isTopLevel) {
955 sid[0] = '\0';
956 }
957
958 save = current = res->u.fTable.fFirst;
959 i = 0;
960
961 while (current != NULL) {
962 res_write_xml(Accumulator, current, sid, language, FALSE, status);
963
964 if(U_FAILURE(*status)){
965 return;
966 }
967
968 i += 1;
969 current = current->fNext;
970 }
971
972 tabCount -= 1;
973 write_tabs(Accumulator);
974
975 Accumulator->append(UnicodeString(close_group));
976 //T_FileStream_write(out, close_group,(int32_t)uprv_strlen(close_group));
977
978 uprv_free(sid);
979 sid = NULL;
980}
981
982void
983res_write_xml(UnicodeString *Accumulator, struct SResource *res, const char* id, const char* language, UBool isTopLevel, UErrorCode *status) {
984
985 if (U_FAILURE(*status)) {
986 return ;
987 }
988
989 if (res != NULL) {
990 switch (res->fType) {
991 case URES_STRING:
992 string_write_xml (Accumulator, res, id, language, status);
993 return;
994
995 case URES_ALIAS:
996 alias_write_xml (Accumulator, res, id, language, status);
997 return;
998
999 case URES_INT_VECTOR:
1000 intvector_write_xml (Accumulator, res, id, language, status);
1001 return;
1002
1003 case URES_BINARY:
1004 bin_write_xml (Accumulator, res, id, language, status);
1005 return;
1006
1007 case URES_INT:
1008 int_write_xml (Accumulator, res, id, language, status);
1009 return;
1010
1011 case URES_ARRAY:
1012 array_write_xml (Accumulator, res, id, language, status);
1013 return;
1014
1015 case URES_TABLE:
1016 case URES_TABLE32:
1017 table_write_xml (Accumulator, res, id, language, isTopLevel, status);
1018 return;
1019
1020 default:
1021 break;
1022 }
1023 }
1024
1025 *status = U_INTERNAL_PROGRAM_ERROR;
1026}
1027
1028void
1029bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, const char* filename,
1030 char *writtenFilename, int writtenFilenameLen,
1031 const char* language, const char* outFileName, UErrorCode *status) {
1032
1033 UnicodeString Accumulator;
1034 char* xmlfileName = NULL;
1035 char* outputFileName = NULL;
1036 char* originalFileName = NULL;
1037 const char* fileStart = "<file xml:space = \"preserve\" source-language = \"";
1038 const char* file1 = "\" datatype = \"x-icu-resource-bundle\" ";
1039 const char* file2 = "original = \"";
1040 const char* file4 = "\" date = \"";
1041 const char* fileEnd = "</file>\n";
1042 const char* headerStart = "<header>\n";
1043 const char* headerEnd = "</header>\n";
1044 const char* bodyStart = "<body>\n";
1045 const char* bodyEnd = "</body>\n";
1046
1047 const char *tool_start = "<tool";
1048 const char *tool_id = "genrb-" GENRB_VERSION "-icu-" U_ICU_VERSION;
1049 const char *tool_name = "genrb";
1050
1051 char* temp = NULL;
1052 char* lang = NULL;
1053 const char* pos = NULL;
1054 int32_t first, index;
1055 time_t currTime;
1056 char timeBuf[128];
1057
1058 outDir = outputDir;
1059
1060 srBundle = bundle;
1061
1062 pos = uprv_strrchr(filename, '\\');
1063 if(pos != NULL) {
1064 first = (int32_t)(pos - filename + 1);
1065 } else {
1066 first = 0;
1067 }
1068 index = (int32_t)(uprv_strlen(filename) - uprv_strlen(textExt) - first);
1069 originalFileName = (char *)uprv_malloc(sizeof(char)*index+1);
1070 uprv_memset(originalFileName, 0, sizeof(char)*index+1);
1071 uprv_strncpy(originalFileName, filename + first, index);
1072
1073 if(uprv_strcmp(originalFileName, srBundle->fLocale) != 0) {
1074 fprintf(stdout, "Warning: The file name is not same as the resource name!\n");
1075 }
1076
1077 temp = originalFileName;
1078 originalFileName = (char *)uprv_malloc(sizeof(char)* (uprv_strlen(temp)+uprv_strlen(textExt)) + 1);
1079 uprv_memset(originalFileName, 0, sizeof(char)* (uprv_strlen(temp)+uprv_strlen(textExt)) + 1);
1080 uprv_strcat(originalFileName, temp);
1081 uprv_strcat(originalFileName, textExt);
1082 uprv_free(temp);
1083 temp = NULL;
1084
1085
1086 if (language == NULL) {
1087/* lang = parseFilename(filename, lang);
1088 if (lang == NULL) {*/
1089 /* now check if locale name is valid or not
1090 * this is to cater for situation where
1091 * pegasusServer.txt contains
1092 *
1093 * en{
1094 * ..
1095 * }
1096 */
1097 lang = parseFilename(srBundle->fLocale, lang);
1098 /*
1099 * Neither the file name nor the table name inside the
1100 * txt file contain a valid country and language codes
1101 * throw an error.
1102 * pegasusServer.txt contains
1103 *
1104 * testelements{
1105 * ....
1106 * }
1107 */
1108 if(lang==NULL){
1109 fprintf(stderr, "Error: The file name and table name do not contain a valid language code. Please use -l option to specify it.\n");
1110 exit(U_ILLEGAL_ARGUMENT_ERROR);
1111 }
1112 /* }*/
1113 } else {
1114 lang = (char *)uprv_malloc(sizeof(char)*uprv_strlen(language) +1);
1115 uprv_memset(lang, 0, sizeof(char)*uprv_strlen(language) +1);
1116 uprv_strcpy(lang, language);
1117 }
1118
1119 if(outFileName) {
1120 outputFileName = (char *)uprv_malloc(sizeof(char)*uprv_strlen(outFileName) + 1);
1121 uprv_memset(outputFileName, 0, sizeof(char)*uprv_strlen(outFileName) + 1);
1122 uprv_strcpy(outputFileName,outFileName);
1123 } else {
1124 outputFileName = (char *)uprv_malloc(sizeof(char)*uprv_strlen(srBundle->fLocale) + 1);
1125 uprv_memset(outputFileName, 0, sizeof(char)*uprv_strlen(srBundle->fLocale) + 1);
1126 uprv_strcpy(outputFileName,srBundle->fLocale);
1127 }
1128
1129 if(outputDir) {
1130 xmlfileName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputDir) + uprv_strlen(outputFileName) + uprv_strlen(xliffExt) + 1) +1);
1131 uprv_memset(xmlfileName, 0, sizeof(char)*(uprv_strlen(outputDir)+ uprv_strlen(outputFileName) + uprv_strlen(xliffExt) + 1) +1);
1132 } else {
1133 xmlfileName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputFileName) + uprv_strlen(xliffExt)) +1);
1134 uprv_memset(xmlfileName, 0, sizeof(char)*(uprv_strlen(outputFileName) + uprv_strlen(xliffExt)) +1);
1135 }
1136
1137 if(outputDir){
1138 uprv_strcpy(xmlfileName, outputDir);
1139 if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){
1140 uprv_strcat(xmlfileName,U_FILE_SEP_STRING);
1141 }
1142 }
1143 uprv_strcat(xmlfileName,outputFileName);
1144 uprv_strcat(xmlfileName,xliffExt);
1145
1146 if (writtenFilename) {
1147 uprv_strncpy(writtenFilename, xmlfileName, writtenFilenameLen);
1148 }
1149
1150 if (U_FAILURE(*status)) {
1151 goto cleanup_bundle_write_xml;
1152 }
1153
1154 out= T_FileStream_open(xmlfileName,"w");
1155
1156 if(out==NULL){
1157 *status = U_FILE_ACCESS_ERROR;
1158 goto cleanup_bundle_write_xml;
1159 }
1160 Accumulator.append(xmlHeader);
1161 //T_FileStream_write(out,xmlHeader, (int32_t)uprv_strlen(xmlHeader));
1162
1163 if(outputEnc && *outputEnc!='\0'){
1164 /* store the output encoding */
1165 enc = outputEnc;
1166 conv=ucnv_open(enc,status);
1167 if(U_FAILURE(*status)){
1168 goto cleanup_bundle_write_xml;
1169 }
1170 }
1171 Accumulator.append(bundleStart);
1172 //T_FileStream_write(out,bundleStart, (int32_t)uprv_strlen(bundleStart));
1173 write_tabs(&Accumulator);
1174 Accumulator.append(fileStart);
1175 //T_FileStream_write(out, fileStart, (int32_t)uprv_strlen(fileStart));
1176 /* check if lang and language are the same */
1177 if(language != NULL && uprv_strcmp(lang, srBundle->fLocale)!=0){
1178 fprintf(stderr,"Warning: The top level tag in the resource and language specified are not the same. Please check the input.\n");
1179 }
1180 Accumulator.append(UnicodeString(lang));
1181 //T_FileStream_write(out,lang, (int32_t)uprv_strlen(lang));
1182 Accumulator.append(UnicodeString(file1));
1183 //T_FileStream_write(out,file1, (int32_t)uprv_strlen(file1));
1184 Accumulator.append(UnicodeString(file2));
1185 //T_FileStream_write(out,file2, (int32_t)uprv_strlen(file2));
1186 Accumulator.append(UnicodeString(originalFileName));
1187 //T_FileStream_write(out,originalFileName, (int32_t)uprv_strlen(originalFileName));
1188 Accumulator.append(UnicodeString(file4));
1189 //T_FileStream_write(out,file4, (int32_t)uprv_strlen(file4));
1190
1191 time(&currTime);
1192 strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currTime));
1193
1194 Accumulator.append(UnicodeString(timeBuf));
1195 Accumulator.append(UnicodeString("\">\n"));
1196 //T_FileStream_write(out,timeBuf, (int32_t)uprv_strlen(timeBuf));
1197
1198 //T_FileStream_write(out,"\">\n", 3);
1199
1200 tabCount += 1;
1201 write_tabs(&Accumulator);
1202 Accumulator.append(headerStart);
1203 //T_FileStream_write(out,headerStart, (int32_t)uprv_strlen(headerStart));
1204
1205 tabCount += 1;
1206 write_tabs(&Accumulator);
1207
1208 Accumulator.append(tool_start);
1209 //T_FileStream_write(out, tool_start, (int32_t) uprv_strlen(tool_start));
1210 printAttribute(&Accumulator, "tool-id", tool_id, (int32_t) uprv_strlen(tool_id));
1211 printAttribute(&Accumulator, "tool-name", tool_name, (int32_t) uprv_strlen(tool_name));
1212
1213 Accumulator.append(UnicodeString("/>\n"));
1214 //T_FileStream_write(out, "/>\n", 3);
1215
1216 tabCount -= 1;
1217 write_tabs(&Accumulator);
1218
1219 Accumulator.append(UnicodeString(headerEnd));
1220 //T_FileStream_write(out,headerEnd, (int32_t)uprv_strlen(headerEnd));
1221
1222 write_tabs(&Accumulator);
1223 tabCount += 1;
1224
1225 Accumulator.append(UnicodeString(bodyStart));
1226 //T_FileStream_write(out,bodyStart, (int32_t)uprv_strlen(bodyStart));
1227
1228
1229 res_write_xml(&Accumulator, bundle->fRoot, bundle->fLocale, lang, TRUE, status);
1230
1231 tabCount -= 1;
1232 write_tabs(&Accumulator);
1233
1234 Accumulator.append(UnicodeString(bodyEnd));
1235 //T_FileStream_write(out,bodyEnd, (int32_t)uprv_strlen(bodyEnd));
1236 tabCount--;
1237 write_tabs(&Accumulator);
1238
1239 Accumulator.append(UnicodeString(fileEnd));
1240 //T_FileStream_write(out,fileEnd, (int32_t)uprv_strlen(fileEnd));
1241 tabCount--;
1242 write_tabs(&Accumulator);
1243 Accumulator.append(UnicodeString(bundleEnd));
1244 //T_FileStream_write(out,bundleEnd,(int32_t)uprv_strlen(bundleEnd));
1245
1246 write_utf8_file(Accumulator, out, status);
1247 T_FileStream_close(out);
1248
1249 ucnv_close(conv);
1250
1251cleanup_bundle_write_xml:
1252 uprv_free(originalFileName);
1253 uprv_free(lang);
1254 if(xmlfileName != NULL) {
1255 uprv_free(xmlfileName);
1256 }
1257 if(outputFileName != NULL){
1258 uprv_free(outputFileName);
1259 }
1260}
1261