2 *******************************************************************************
4 * Copyright (C) 2002-2009, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 10/01/02 Ram Creation.
15 * 02/07/08 Spieth Correct XLIFF generation on EBCDIC platform
17 *******************************************************************************
21 #include "unicode/ures.h"
25 #include "unicode/ucnv.h"
31 #include "unicode/ustring.h"
32 #include "unicode/uchar.h"
35 #include "unicode/unistr.h"
40 static int tabCount
= 0;
42 static FileStream
* out
=NULL
;
43 static struct SRBRoot
* srBundle
;
44 static const char* outDir
= NULL
;
45 static const char* enc
="";
46 static UConverter
* conv
= NULL
;
48 const char* const* ISOLanguages
;
49 const char* const* ISOCountries
;
50 const char* textExt
= ".txt";
51 const char* xliffExt
= ".xlf";
53 static int32_t write_utf8_file(FileStream
* fileStream
, UnicodeString outString
)
55 UErrorCode status
= U_ZERO_ERROR
;
58 // preflight to get the destination buffer size
62 outString
.getBuffer(),
66 // allocate the buffer
67 char* dest
= (char*)uprv_malloc(len
);
68 status
= U_ZERO_ERROR
;
74 outString
.getBuffer(),
78 // write data to out file
79 int32_t ret
= T_FileStream_write(fileStream
, dest
, len
);
84 /*write indentation for formatting*/
85 static void write_tabs(FileStream
* os
){
87 for(;i
<=tabCount
;i
++){
88 write_utf8_file(os
,UnicodeString(" "));
92 /*get ID for each element. ID is globally unique.*/
93 static char* getID(const char* id
, const char* curKey
, char* result
) {
95 result
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(id
) + 1);
96 uprv_memset(result
, 0, sizeof(char)*uprv_strlen(id
) + 1);
97 uprv_strcpy(result
, id
);
99 result
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
100 uprv_memset(result
, 0, sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
102 uprv_strcpy(result
, id
);
103 uprv_strcat(result
, "_");
105 uprv_strcat(result
, curKey
);
110 /*compute CRC for binary code*/
111 /* The code is from http://www.theorem.com/java/CRC32.java
112 * Calculates the CRC32 - 32 bit Cyclical Redundancy Check
113 * <P> This check is used in numerous systems to verify the integrity
114 * of information. It's also used as a hashing function. Unlike a regular
115 * checksum, it's sensitive to the order of the characters.
116 * It produces a 32 bit
118 * @author Michael Lecuyer (mjl@theorem.com)
119 * @version 1.1 August 11, 1998
122 /* ICU is not endian portable, because ICU data generated on big endian machines can be
123 * ported to big endian machines but not to little endian machines and vice versa. The
124 * conversion is not portable across platforms with different endianess.
127 uint32_t computeCRC(char *ptr
, uint32_t len
, uint32_t lastcrc
){
137 #define CRC32_POLYNOMIAL 0xEDB88320
140 for (i
= 0; i
<= 255; i
++) {
142 for (j
= 8; j
> 0; j
--) {
143 if ((crc2
& 1) == 1) {
144 crc2
= (crc2
>> 1) ^ CRC32_POLYNOMIAL
;
154 temp1
= (uint32_t)crc
>>8;
155 temp2
= crc_ta
[(crc
^*ptr
) & 0xFF];
162 static void strnrepchr(char* src
, int32_t srcLen
, char s
, char r
){
164 for(i
=0;i
<srcLen
;i
++){
170 /* Parse the filename, and get its language information.
171 * If it fails to get the language information from the filename,
172 * use "en" as the default value for language
174 static char* parseFilename(const char* id
, char* /*lang*/) {
175 int idLen
= (int) uprv_strlen(id
);
176 char* localeID
= (char*) uprv_malloc(idLen
);
178 int canonCapacity
= 0;
182 UErrorCode status
= U_ZERO_ERROR
;
183 const char *ext
= uprv_strchr(id
, '.');
186 pos
= (int) (ext
- id
);
190 uprv_memcpy(localeID
, id
, pos
);
191 localeID
[pos
]=0; /* NUL terminate the string */
193 canonCapacity
=pos
*3;
194 canon
= (char*) uprv_malloc(canonCapacity
);
195 canonLen
= uloc_canonicalize(localeID
, canon
, canonCapacity
, &status
);
197 if(U_FAILURE(status
)){
198 fprintf(stderr
, "Could not canonicalize the locale ID: %s. Error: %s\n", localeID
, u_errorName(status
));
201 strnrepchr(canon
, canonLen
, '_', '-');
205 static const char* xmlHeader
= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
207 static const char* bundleStart
= "<xliff version = \"1.2\" "
208 "xmlns='urn:oasis:names:tc:xliff:document:1.2' "
209 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
210 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'>\n";
212 static const char* bundleStart
= "<xliff version = \"1.1\" "
213 "xmlns='urn:oasis:names:tc:xliff:document:1.1' "
214 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
215 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd'>\n";
217 static const char* bundleEnd
= "</xliff>\n";
219 void res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
);
221 static char* convertAndEscape(char** pDest
, int32_t destCap
, int32_t* destLength
,
222 const UChar
* src
, int32_t srcLen
, UErrorCode
* status
){
229 if(status
==NULL
|| U_FAILURE(*status
) || pDest
==NULL
|| srcLen
==0 || src
== NULL
){
233 if(dest
==NULL
|| destCap
<=0){
234 destCap
= srcLen
* 8;
235 dest
= (char*) uprv_malloc(sizeof(char) * destCap
);
237 *status
=U_MEMORY_ALLOCATION_ERROR
;
244 while(srcIndex
<srcLen
){
245 U16_NEXT(src
, srcIndex
, srcLen
, c
);
247 if (U16_IS_LEAD(c
) || U16_IS_TRAIL(c
)) {
248 *status
= U_ILLEGAL_CHAR_FOUND
;
249 fprintf(stderr
, "Illegal Surrogate! \n");
254 if((destLen
+UTF8_CHAR_LENGTH(c
)) < destCap
){
260 uprv_strcpy(dest
+( destLen
),"\x26\x61\x6d\x70\x3b"); /* &*/
261 destLen
+=(int32_t)uprv_strlen("\x26\x61\x6d\x70\x3b");
264 uprv_strcpy(dest
+(destLen
),"\x26\x6c\x74\x3b"); /* <*/
265 destLen
+=(int32_t)uprv_strlen("\x26\x6c\x74\x3b");
268 uprv_strcpy(dest
+(destLen
),"\x26\x67\x74\x3b"); /* >*/
269 destLen
+=(int32_t)uprv_strlen("\x26\x67\x74\x3b");
272 uprv_strcpy(dest
+(destLen
),"\x26\x71\x75\x6f\x74\x3b"); /* "*/
273 destLen
+=(int32_t)uprv_strlen("\x26\x71\x75\x6f\x74\x3b");
276 uprv_strcpy(dest
+(destLen
),"\x26\x61\x70\x6f\x73\x3b"); /* ' */
277 destLen
+=(int32_t)uprv_strlen("\x26\x61\x70\x6f\x73\x3b");
280 /* Disallow C0 controls except TAB, CR, LF*/
313 *status
= U_ILLEGAL_CHAR_FOUND
;
314 fprintf(stderr
, "Illegal Character \\u%04X!\n",(int)c
);
318 dest
[destLen
++]=(char)c
;
321 UBool isError
= FALSE
;
322 U8_APPEND((unsigned char*)dest
,destLen
,destCap
,c
,isError
);
324 *status
= U_ILLEGAL_CHAR_FOUND
;
325 fprintf(stderr
, "Illegal Character \\U%08X!\n",(int)c
);
333 temp
= (char*) uprv_malloc(sizeof(char)*destCap
);
335 *status
=U_MEMORY_ALLOCATION_ERROR
;
339 uprv_memmove(temp
,dest
,destLen
);
347 *destLength
= destLen
;
351 #define ASTERISK 0x002A
355 #define AT_SIGN 0x0040
358 trim(char **src
, int32_t *len
){
362 if(src
== NULL
|| *src
== NULL
){
366 /* trim from the end */
367 for( i
=(*len
-1); i
>= 0; i
--){
385 print(UChar
* src
, int32_t srcLen
,const char *tagStart
,const char *tagEnd
, UErrorCode
*status
){
386 int32_t bufCapacity
= srcLen
*4;
390 if(U_FAILURE(*status
)){
394 buf
= (char*) (uprv_malloc(bufCapacity
));
396 fprintf(stderr
, "Could not allocate memory!!");
397 exit(U_MEMORY_ALLOCATION_ERROR
);
399 buf
= convertAndEscape(&buf
, bufCapacity
, &bufLen
, src
, srcLen
,status
);
400 if(U_SUCCESS(*status
)){
402 write_utf8_file(out
,UnicodeString(tagStart
));
403 write_utf8_file(out
,UnicodeString(buf
, bufLen
, "UTF-8"));
404 write_utf8_file(out
,UnicodeString(tagEnd
));
405 write_utf8_file(out
,UnicodeString("\n"));
410 printNoteElements(struct UString
*src
, UErrorCode
*status
){
412 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
414 int32_t capacity
= 0;
423 capacity
= src
->fLength
;
424 note
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
426 count
= getCount(src
->fChars
,src
->fLength
, UPC_NOTE
, status
);
427 if(U_FAILURE(*status
)){
431 for(i
=0; i
< count
; i
++){
432 noteLen
= getAt(src
->fChars
,src
->fLength
, ¬e
, capacity
, i
, UPC_NOTE
, status
);
433 if(U_FAILURE(*status
)){
439 print(note
, noteLen
,"<note>", "</note>", status
);
445 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
447 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
451 static void printAttribute(const char *name
, const char *value
, int32_t /*len*/)
453 write_utf8_file(out
, UnicodeString(" "));
454 write_utf8_file(out
, UnicodeString(name
));
455 write_utf8_file(out
, UnicodeString(" = \""));
456 write_utf8_file(out
, UnicodeString(value
));
457 write_utf8_file(out
, UnicodeString("\""));
460 static void printAttribute(const char *name
, const UnicodeString value
, int32_t /*len*/)
462 write_utf8_file(out
, UnicodeString(" "));
463 write_utf8_file(out
, UnicodeString(name
));
464 write_utf8_file(out
, UnicodeString(" = \""));
465 write_utf8_file(out
, value
);
466 write_utf8_file(out
, UnicodeString("\""));
470 printComments(struct UString
*src
, const char *resName
, UBool printTranslate
, UErrorCode
*status
){
472 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
474 if(status
==NULL
|| U_FAILURE(*status
)){
478 int32_t capacity
= src
->fLength
+ 1;
481 UChar
* desc
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
482 UChar
* trans
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
484 int32_t descLen
= 0, transLen
=0;
485 if(desc
==NULL
|| trans
==NULL
){
486 *status
= U_MEMORY_ALLOCATION_ERROR
;
491 src
->fLength
= removeCmtText(src
->fChars
, src
->fLength
, status
);
492 descLen
= getDescription(src
->fChars
,src
->fLength
, &desc
, capacity
, status
);
493 transLen
= getTranslate(src
->fChars
,src
->fLength
, &trans
, capacity
, status
);
495 /* first print translate attribute */
498 /* print translate attribute */
499 buf
= convertAndEscape(&buf
, 0, &bufLen
, trans
, transLen
, status
);
500 if(U_SUCCESS(*status
)){
501 printAttribute("translate", UnicodeString(buf
, bufLen
, "UTF-8"), bufLen
);
502 write_utf8_file(out
,UnicodeString(">\n"));
504 }else if(getShowWarning()){
505 fprintf(stderr
, "Warning: Tranlate attribute for resource %s cannot be set. XLIFF prohibits it.\n", resName
);
506 /* no translate attribute .. just close the tag */
507 write_utf8_file(out
,UnicodeString(">\n"));
510 /* no translate attribute .. just close the tag */
511 write_utf8_file(out
,UnicodeString(">\n"));
516 print(desc
, descLen
, "<!--", "-->", status
);
523 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
525 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
530 * Print out a containing element, like:
531 * <trans-unit id = "blah" resname = "blah" restype = "x-id-alias" translate = "no">
532 * <group id "calendar_gregorian" resname = "gregorian" restype = "x-icu-array">
534 static char *printContainer(struct SResource
*res
, const char *container
, const char *restype
, const char *mimetype
, const char *id
, UErrorCode
*status
)
536 char resKeyBuffer
[8];
537 const char *resname
= NULL
;
542 resname
= res_getKeyString(srBundle
, res
, resKeyBuffer
);
543 if (resname
!= NULL
&& *resname
!= 0) {
544 sid
= getID(id
, resname
, sid
);
546 sid
= getID(id
, NULL
, sid
);
549 write_utf8_file(out
, UnicodeString("<"));
550 write_utf8_file(out
, UnicodeString(container
));
551 printAttribute("id", sid
, (int32_t) uprv_strlen(sid
));
553 if (resname
!= NULL
) {
554 printAttribute("resname", resname
, (int32_t) uprv_strlen(resname
));
557 if (mimetype
!= NULL
) {
558 printAttribute("mime-type", mimetype
, (int32_t) uprv_strlen(mimetype
));
561 if (restype
!= NULL
) {
562 printAttribute("restype", restype
, (int32_t) uprv_strlen(restype
));
566 if (res
->fComment
.fLength
> 0) {
567 /* printComments will print the closing ">\n" */
568 printComments(&res
->fComment
, resname
, TRUE
, status
);
570 write_utf8_file(out
, UnicodeString(">\n"));
576 /* Writing Functions */
578 static const char *trans_unit
= "trans-unit";
579 static const char *close_trans_unit
= "</trans-unit>\n";
580 static const char *source
= "<source>";
581 static const char *close_source
= "</source>\n";
582 static const char *group
= "group";
583 static const char *close_group
= "</group>\n";
585 static const char *bin_unit
= "bin-unit";
586 static const char *close_bin_unit
= "</bin-unit>\n";
587 static const char *bin_source
= "<bin-source>\n";
588 static const char *close_bin_source
= "</bin-source>\n";
589 static const char *external_file
= "<external-file";
590 /*static const char *close_external_file = "</external-file>\n";*/
591 static const char *internal_file
= "<internal-file";
592 static const char *close_internal_file
= "</internal-file>\n";
594 static const char *application_mimetype
= "application"; /* add "/octet-stream"? */
596 static const char *alias_restype
= "x-icu-alias";
597 static const char *array_restype
= "x-icu-array";
598 static const char *binary_restype
= "x-icu-binary";
599 static const char *integer_restype
= "x-icu-integer";
600 static const char *intvector_restype
= "x-icu-intvector";
601 static const char *table_restype
= "x-icu-table";
604 string_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
610 if(status
==NULL
|| U_FAILURE(*status
)){
614 sid
= printContainer(res
, trans_unit
, NULL
, NULL
, id
, status
);
618 write_utf8_file(out
, UnicodeString(source
));
620 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
, status
);
622 if (U_FAILURE(*status
)) {
626 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
627 write_utf8_file(out
, UnicodeString(close_source
));
629 printNoteElements(&res
->fComment
, status
);
634 write_utf8_file(out
, UnicodeString(close_trans_unit
));
641 alias_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
646 sid
= printContainer(res
, trans_unit
, alias_restype
, NULL
, id
, status
);
650 write_utf8_file(out
, UnicodeString(source
));
652 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
, status
);
654 if(U_FAILURE(*status
)){
657 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
658 write_utf8_file(out
, UnicodeString(close_source
));
660 printNoteElements(&res
->fComment
, status
);
665 write_utf8_file(out
, UnicodeString(close_trans_unit
));
672 array_write_xml(struct SResource
*res
, const char* id
, const char* language
, UErrorCode
*status
) {
676 struct SResource
*current
= NULL
;
677 struct SResource
*first
=NULL
;
679 sid
= printContainer(res
, group
, array_restype
, NULL
, id
, status
);
681 current
= res
->u
.fArray
.fFirst
;
684 while (current
!= NULL
) {
688 itostr(c
, index
, 10, 0);
690 subId
= getID(sid
, c
, subId
);
692 res_write_xml(current
, subId
, language
, FALSE
, status
);
696 if(U_FAILURE(*status
)){
700 current
= current
->fNext
;
705 write_utf8_file(out
, UnicodeString(close_group
));
711 intvector_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
716 char buf
[256] = {'0'};
718 sid
= printContainer(res
, group
, intvector_restype
, NULL
, id
, status
);
720 for(i
= 0; i
< res
->u
.fIntVector
.fCount
; i
+= 1) {
724 ivd
= getID(sid
, c
, ivd
);
725 len
= itostr(buf
, res
->u
.fIntVector
.fArray
[i
], 10, 0);
728 write_utf8_file(out
, UnicodeString("<"));
729 write_utf8_file(out
, UnicodeString(trans_unit
));
731 printAttribute("id", ivd
, (int32_t)uprv_strlen(ivd
));
732 printAttribute("restype", integer_restype
, (int32_t) strlen(integer_restype
));
734 write_utf8_file(out
, UnicodeString(">\n"));
738 write_utf8_file(out
, UnicodeString(source
));
740 write_utf8_file(out
, UnicodeString(buf
, len
));
742 write_utf8_file(out
, UnicodeString(close_source
));
745 write_utf8_file(out
, UnicodeString(close_trans_unit
));
754 write_utf8_file(out
, UnicodeString(close_group
));
760 int_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
765 sid
= printContainer(res
, trans_unit
, integer_restype
, NULL
, id
, status
);
769 write_utf8_file(out
, UnicodeString(source
));
771 len
= itostr(buf
, res
->u
.fIntValue
.fValue
, 10, 0);
772 write_utf8_file(out
, UnicodeString(buf
, len
));
774 write_utf8_file(out
, UnicodeString(close_source
));
776 printNoteElements(&res
->fComment
, status
);
781 write_utf8_file(out
, UnicodeString(close_trans_unit
));
788 bin_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
789 const char* m_type
= application_mimetype
;
791 uint32_t crc
= 0xFFFFFFFF;
793 char fileName
[1024] ={0};
794 int32_t tLen
= ( outDir
== NULL
) ? 0 :(int32_t)uprv_strlen(outDir
);
795 char* fn
= (char*) uprv_malloc(sizeof(char) * (tLen
+1024 +
796 (res
->u
.fBinaryValue
.fFileName
!=NULL
?
797 uprv_strlen(res
->u
.fBinaryValue
.fFileName
) :0)));
798 const char* ext
= NULL
;
804 if(res
->u
.fBinaryValue
.fFileName
!= NULL
){
805 uprv_strcpy(fileName
, res
->u
.fBinaryValue
.fFileName
);
806 f
= uprv_strrchr(fileName
, '\\');
814 ext
= uprv_strrchr(fileName
, '.');
817 fprintf(stderr
, "Error: %s is an unknown binary filename type.\n", fileName
);
818 exit(U_ILLEGAL_ARGUMENT_ERROR
);
821 if(uprv_strcmp(ext
, ".jpg")==0 || uprv_strcmp(ext
, ".jpeg")==0 || uprv_strcmp(ext
, ".gif")==0 ){
823 } else if(uprv_strcmp(ext
, ".wav")==0 || uprv_strcmp(ext
, ".au")==0 ){
825 } else if(uprv_strcmp(ext
, ".avi")==0 || uprv_strcmp(ext
, ".mpg")==0 || uprv_strcmp(ext
, ".mpeg")==0){
827 } else if(uprv_strcmp(ext
, ".txt")==0 || uprv_strcmp(ext
, ".text")==0){
831 sid
= printContainer(res
, bin_unit
, binary_restype
, m_type
, id
, status
);
835 write_utf8_file(out
, UnicodeString(bin_source
));
840 write_utf8_file(out
, UnicodeString(external_file
));
841 printAttribute("href", f
, (int32_t)uprv_strlen(f
));
842 write_utf8_file(out
, UnicodeString("/>\n"));
846 write_utf8_file(out
, UnicodeString(close_bin_source
));
848 printNoteElements(&res
->fComment
, status
);
851 write_utf8_file(out
, UnicodeString(close_bin_unit
));
853 char temp
[256] = {0};
857 sid
= printContainer(res
, bin_unit
, binary_restype
, m_type
, id
, status
);
860 write_utf8_file(out
, UnicodeString(bin_source
));
865 write_utf8_file(out
, UnicodeString(internal_file
));
866 printAttribute("form", application_mimetype
, (int32_t) uprv_strlen(application_mimetype
));
868 while(i
<res
->u
.fBinaryValue
.fLength
){
869 len
= itostr(temp
, res
->u
.fBinaryValue
.fData
[i
], 16, 2);
870 crc
= computeCRC(temp
, len
, crc
);
874 len
= itostr(temp
, crc
, 10, 0);
875 printAttribute("crc", temp
, len
);
877 write_utf8_file(out
, UnicodeString(">"));
880 while(i
<res
->u
.fBinaryValue
.fLength
){
881 len
= itostr(temp
, res
->u
.fBinaryValue
.fData
[i
], 16, 2);
882 write_utf8_file(out
, UnicodeString(temp
));
886 write_utf8_file(out
, UnicodeString(close_internal_file
));
891 write_utf8_file(out
, UnicodeString(close_bin_source
));
892 printNoteElements(&res
->fComment
, status
);
896 write_utf8_file(out
, UnicodeString(close_bin_unit
));
908 table_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
) {
912 struct SResource
*current
= NULL
;
913 struct SResource
*save
= NULL
;
916 if (U_FAILURE(*status
)) {
920 sid
= printContainer(res
, group
, table_restype
, NULL
, id
, status
);
926 save
= current
= res
->u
.fTable
.fFirst
;
929 while (current
!= NULL
) {
930 res_write_xml(current
, sid
, language
, FALSE
, status
);
932 if(U_FAILURE(*status
)){
937 current
= current
->fNext
;
943 write_utf8_file(out
, UnicodeString(close_group
));
950 res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
) {
952 if (U_FAILURE(*status
)) {
957 switch (res
->fType
) {
959 string_write_xml (res
, id
, language
, status
);
963 alias_write_xml (res
, id
, language
, status
);
966 case URES_INT_VECTOR
:
967 intvector_write_xml (res
, id
, language
, status
);
971 bin_write_xml (res
, id
, language
, status
);
975 int_write_xml (res
, id
, language
, status
);
979 array_write_xml (res
, id
, language
, status
);
983 table_write_xml (res
, id
, language
, isTopLevel
, status
);
991 *status
= U_INTERNAL_PROGRAM_ERROR
;
995 bundle_write_xml(struct SRBRoot
*bundle
, const char *outputDir
,const char* outputEnc
, const char* filename
,
996 char *writtenFilename
, int writtenFilenameLen
,
997 const char* language
, const char* outFileName
, UErrorCode
*status
) {
999 char* xmlfileName
= NULL
;
1000 char* outputFileName
= NULL
;
1001 char* originalFileName
= NULL
;
1002 const char* fileStart
= "<file xml:space = \"preserve\" source-language = \"";
1003 const char* file1
= "\" datatype = \"x-icu-resource-bundle\" ";
1004 const char* file2
= "original = \"";
1005 const char* file4
= "\" date = \"";
1006 const char* fileEnd
= "</file>\n";
1007 const char* headerStart
= "<header>\n";
1008 const char* headerEnd
= "</header>\n";
1009 const char* bodyStart
= "<body>\n";
1010 const char* bodyEnd
= "</body>\n";
1012 const char *tool_start
= "<tool";
1013 const char *tool_id
= "genrb-" GENRB_VERSION
"-icu-" U_ICU_VERSION
;
1014 const char *tool_name
= "genrb";
1018 const char* pos
= NULL
;
1019 int32_t first
, index
;
1027 pos
= uprv_strrchr(filename
, '\\');
1029 first
= (int32_t)(pos
- filename
+ 1);
1033 index
= (int32_t)(uprv_strlen(filename
) - uprv_strlen(textExt
) - first
);
1034 originalFileName
= (char *)uprv_malloc(sizeof(char)*index
+1);
1035 uprv_memset(originalFileName
, 0, sizeof(char)*index
+1);
1036 uprv_strncpy(originalFileName
, filename
+ first
, index
);
1038 if(uprv_strcmp(originalFileName
, srBundle
->fLocale
) != 0) {
1039 fprintf(stdout
, "Warning: The file name is not same as the resource name!\n");
1042 temp
= originalFileName
;
1043 originalFileName
= (char *)uprv_malloc(sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1044 uprv_memset(originalFileName
, 0, sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1045 uprv_strcat(originalFileName
, temp
);
1046 uprv_strcat(originalFileName
, textExt
);
1051 if (language
== NULL
) {
1052 /* lang = parseFilename(filename, lang);
1053 if (lang == NULL) {*/
1054 /* now check if locale name is valid or not
1055 * this is to cater for situation where
1056 * pegasusServer.txt contains
1062 lang
= parseFilename(srBundle
->fLocale
, lang
);
1064 * Neither the file name nor the table name inside the
1065 * txt file contain a valid country and language codes
1067 * pegasusServer.txt contains
1074 fprintf(stderr
, "Error: The file name and table name do not contain a valid language code. Please use -l option to specify it.\n");
1075 exit(U_ILLEGAL_ARGUMENT_ERROR
);
1079 lang
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(language
) +1);
1080 uprv_memset(lang
, 0, sizeof(char)*uprv_strlen(language
) +1);
1081 uprv_strcpy(lang
, language
);
1085 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(outFileName
) + 1);
1086 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(outFileName
) + 1);
1087 uprv_strcpy(outputFileName
,outFileName
);
1089 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1090 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1091 uprv_strcpy(outputFileName
,srBundle
->fLocale
);
1095 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputDir
) + uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1096 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputDir
)+ uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1098 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1099 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1103 uprv_strcpy(xmlfileName
, outputDir
);
1104 if(outputDir
[uprv_strlen(outputDir
)-1] !=U_FILE_SEP_CHAR
){
1105 uprv_strcat(xmlfileName
,U_FILE_SEP_STRING
);
1108 uprv_strcat(xmlfileName
,outputFileName
);
1109 uprv_strcat(xmlfileName
,xliffExt
);
1111 if (writtenFilename
) {
1112 uprv_strncpy(writtenFilename
, xmlfileName
, writtenFilenameLen
);
1115 if (U_FAILURE(*status
)) {
1116 goto cleanup_bundle_write_xml
;
1119 out
= T_FileStream_open(xmlfileName
,"w");
1122 *status
= U_FILE_ACCESS_ERROR
;
1123 goto cleanup_bundle_write_xml
;
1125 write_utf8_file(out
, xmlHeader
);
1127 if(outputEnc
&& *outputEnc
!='\0'){
1128 /* store the output encoding */
1130 conv
=ucnv_open(enc
,status
);
1131 if(U_FAILURE(*status
)){
1132 goto cleanup_bundle_write_xml
;
1135 write_utf8_file(out
, bundleStart
);
1137 write_utf8_file(out
, fileStart
);
1138 /* check if lang and language are the same */
1139 if(language
!= NULL
&& uprv_strcmp(lang
, srBundle
->fLocale
)!=0){
1140 fprintf(stderr
,"Warning: The top level tag in the resource and language specified are not the same. Please check the input.\n");
1142 write_utf8_file(out
, UnicodeString(lang
));
1143 write_utf8_file(out
, UnicodeString(file1
));
1144 write_utf8_file(out
, UnicodeString(file2
));
1145 write_utf8_file(out
, UnicodeString(originalFileName
));
1146 write_utf8_file(out
, UnicodeString(file4
));
1149 strftime(timeBuf
, sizeof(timeBuf
), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currTime
));
1150 write_utf8_file(out
, UnicodeString(timeBuf
));
1151 write_utf8_file(out
, UnicodeString("\">\n"));
1155 write_utf8_file(out
, headerStart
);
1160 write_utf8_file(out
, tool_start
);
1161 printAttribute("tool-id", tool_id
, (int32_t) uprv_strlen(tool_id
));
1162 printAttribute("tool-name", tool_name
, (int32_t) uprv_strlen(tool_name
));
1163 write_utf8_file(out
, UnicodeString("/>\n"));
1168 write_utf8_file(out
, UnicodeString(headerEnd
));
1173 write_utf8_file(out
, UnicodeString(bodyStart
));
1176 res_write_xml(bundle
->fRoot
, bundle
->fLocale
, lang
, TRUE
, status
);
1181 write_utf8_file(out
, UnicodeString(bodyEnd
));
1184 write_utf8_file(out
, UnicodeString(fileEnd
));
1187 write_utf8_file(out
, UnicodeString(bundleEnd
));
1188 T_FileStream_close(out
);
1192 cleanup_bundle_write_xml
:
1193 uprv_free(originalFileName
);
1195 if(xmlfileName
!= NULL
) {
1196 uprv_free(xmlfileName
);
1198 if(outputFileName
!= NULL
){
1199 uprv_free(outputFileName
);