2 *******************************************************************************
4 * Copyright (C) 2002-2012, 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"
36 #include "unicode/utf8.h"
37 #include "unicode/utf16.h"
42 static int tabCount
= 0;
44 static FileStream
* out
=NULL
;
45 static struct SRBRoot
* srBundle
;
46 static const char* outDir
= NULL
;
47 static const char* enc
="";
48 static UConverter
* conv
= NULL
;
50 const char* const* ISOLanguages
;
51 const char* const* ISOCountries
;
52 const char* textExt
= ".txt";
53 const char* xliffExt
= ".xlf";
55 static int32_t write_utf8_file(FileStream
* fileStream
, UnicodeString outString
)
57 UErrorCode status
= U_ZERO_ERROR
;
60 // preflight to get the destination buffer size
64 outString
.getBuffer(),
68 // allocate the buffer
69 char* dest
= (char*)uprv_malloc(len
);
70 status
= U_ZERO_ERROR
;
76 outString
.getBuffer(),
80 // write data to out file
81 int32_t ret
= T_FileStream_write(fileStream
, dest
, len
);
86 /*write indentation for formatting*/
87 static void write_tabs(FileStream
* os
){
89 for(;i
<=tabCount
;i
++){
90 write_utf8_file(os
,UnicodeString(" "));
94 /*get ID for each element. ID is globally unique.*/
95 static char* getID(const char* id
, const char* curKey
, char* result
) {
97 result
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(id
) + 1);
98 uprv_memset(result
, 0, sizeof(char)*uprv_strlen(id
) + 1);
99 uprv_strcpy(result
, id
);
101 result
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
102 uprv_memset(result
, 0, sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
104 uprv_strcpy(result
, id
);
105 uprv_strcat(result
, "_");
107 uprv_strcat(result
, curKey
);
112 /*compute CRC for binary code*/
113 /* The code is from http://www.theorem.com/java/CRC32.java
114 * Calculates the CRC32 - 32 bit Cyclical Redundancy Check
115 * <P> This check is used in numerous systems to verify the integrity
116 * of information. It's also used as a hashing function. Unlike a regular
117 * checksum, it's sensitive to the order of the characters.
118 * It produces a 32 bit
120 * @author Michael Lecuyer (mjl@theorem.com)
121 * @version 1.1 August 11, 1998
124 /* ICU is not endian portable, because ICU data generated on big endian machines can be
125 * ported to big endian machines but not to little endian machines and vice versa. The
126 * conversion is not portable across platforms with different endianess.
129 uint32_t computeCRC(char *ptr
, uint32_t len
, uint32_t lastcrc
){
139 #define CRC32_POLYNOMIAL 0xEDB88320
142 for (i
= 0; i
<= 255; i
++) {
144 for (j
= 8; j
> 0; j
--) {
145 if ((crc2
& 1) == 1) {
146 crc2
= (crc2
>> 1) ^ CRC32_POLYNOMIAL
;
156 temp1
= (uint32_t)crc
>>8;
157 temp2
= crc_ta
[(crc
^*ptr
) & 0xFF];
164 static void strnrepchr(char* src
, int32_t srcLen
, char s
, char r
){
166 for(i
=0;i
<srcLen
;i
++){
172 /* Parse the filename, and get its language information.
173 * If it fails to get the language information from the filename,
174 * use "en" as the default value for language
176 static char* parseFilename(const char* id
, char* /*lang*/) {
177 int idLen
= (int) uprv_strlen(id
);
178 char* localeID
= (char*) uprv_malloc(idLen
);
180 int canonCapacity
= 0;
184 UErrorCode status
= U_ZERO_ERROR
;
185 const char *ext
= uprv_strchr(id
, '.');
188 pos
= (int) (ext
- id
);
192 uprv_memcpy(localeID
, id
, pos
);
193 localeID
[pos
]=0; /* NUL terminate the string */
195 canonCapacity
=pos
*3;
196 canon
= (char*) uprv_malloc(canonCapacity
);
197 canonLen
= uloc_canonicalize(localeID
, canon
, canonCapacity
, &status
);
199 if(U_FAILURE(status
)){
200 fprintf(stderr
, "Could not canonicalize the locale ID: %s. Error: %s\n", localeID
, u_errorName(status
));
203 strnrepchr(canon
, canonLen
, '_', '-');
207 static const char* xmlHeader
= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
209 static const char* bundleStart
= "<xliff version = \"1.2\" "
210 "xmlns='urn:oasis:names:tc:xliff:document:1.2' "
211 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
212 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'>\n";
214 static const char* bundleStart
= "<xliff version = \"1.1\" "
215 "xmlns='urn:oasis:names:tc:xliff:document:1.1' "
216 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
217 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd'>\n";
219 static const char* bundleEnd
= "</xliff>\n";
221 void res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
);
223 static char* convertAndEscape(char** pDest
, int32_t destCap
, int32_t* destLength
,
224 const UChar
* src
, int32_t srcLen
, UErrorCode
* status
){
231 if(status
==NULL
|| U_FAILURE(*status
) || pDest
==NULL
|| srcLen
==0 || src
== NULL
){
235 if(dest
==NULL
|| destCap
<=0){
236 destCap
= srcLen
* 8;
237 dest
= (char*) uprv_malloc(sizeof(char) * destCap
);
239 *status
=U_MEMORY_ALLOCATION_ERROR
;
246 while(srcIndex
<srcLen
){
247 U16_NEXT(src
, srcIndex
, srcLen
, c
);
249 if (U16_IS_LEAD(c
) || U16_IS_TRAIL(c
)) {
250 *status
= U_ILLEGAL_CHAR_FOUND
;
251 fprintf(stderr
, "Illegal Surrogate! \n");
256 if((destLen
+U8_LENGTH(c
)) < destCap
){
262 uprv_strcpy(dest
+( destLen
),"\x26\x61\x6d\x70\x3b"); /* &*/
263 destLen
+=(int32_t)uprv_strlen("\x26\x61\x6d\x70\x3b");
266 uprv_strcpy(dest
+(destLen
),"\x26\x6c\x74\x3b"); /* <*/
267 destLen
+=(int32_t)uprv_strlen("\x26\x6c\x74\x3b");
270 uprv_strcpy(dest
+(destLen
),"\x26\x67\x74\x3b"); /* >*/
271 destLen
+=(int32_t)uprv_strlen("\x26\x67\x74\x3b");
274 uprv_strcpy(dest
+(destLen
),"\x26\x71\x75\x6f\x74\x3b"); /* "*/
275 destLen
+=(int32_t)uprv_strlen("\x26\x71\x75\x6f\x74\x3b");
278 uprv_strcpy(dest
+(destLen
),"\x26\x61\x70\x6f\x73\x3b"); /* ' */
279 destLen
+=(int32_t)uprv_strlen("\x26\x61\x70\x6f\x73\x3b");
282 /* Disallow C0 controls except TAB, CR, LF*/
315 *status
= U_ILLEGAL_CHAR_FOUND
;
316 fprintf(stderr
, "Illegal Character \\u%04X!\n",(int)c
);
320 dest
[destLen
++]=(char)c
;
323 UBool isError
= FALSE
;
324 U8_APPEND((unsigned char*)dest
,destLen
,destCap
,c
,isError
);
326 *status
= U_ILLEGAL_CHAR_FOUND
;
327 fprintf(stderr
, "Illegal Character \\U%08X!\n",(int)c
);
335 temp
= (char*) uprv_malloc(sizeof(char)*destCap
);
337 *status
=U_MEMORY_ALLOCATION_ERROR
;
341 uprv_memmove(temp
,dest
,destLen
);
349 *destLength
= destLen
;
353 #define ASTERISK 0x002A
357 #define AT_SIGN 0x0040
360 trim(char **src
, int32_t *len
){
364 if(src
== NULL
|| *src
== NULL
){
368 /* trim from the end */
369 for( i
=(*len
-1); i
>= 0; i
--){
387 print(UChar
* src
, int32_t srcLen
,const char *tagStart
,const char *tagEnd
, UErrorCode
*status
){
388 int32_t bufCapacity
= srcLen
*4;
392 if(U_FAILURE(*status
)){
396 buf
= (char*) (uprv_malloc(bufCapacity
));
398 fprintf(stderr
, "Could not allocate memory!!");
399 exit(U_MEMORY_ALLOCATION_ERROR
);
401 buf
= convertAndEscape(&buf
, bufCapacity
, &bufLen
, src
, srcLen
,status
);
402 if(U_SUCCESS(*status
)){
404 write_utf8_file(out
,UnicodeString(tagStart
));
405 write_utf8_file(out
,UnicodeString(buf
, bufLen
, "UTF-8"));
406 write_utf8_file(out
,UnicodeString(tagEnd
));
407 write_utf8_file(out
,UnicodeString("\n"));
412 printNoteElements(struct UString
*src
, UErrorCode
*status
){
414 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
416 int32_t capacity
= 0;
425 capacity
= src
->fLength
;
426 note
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
428 count
= getCount(src
->fChars
,src
->fLength
, UPC_NOTE
, status
);
429 if(U_FAILURE(*status
)){
433 for(i
=0; i
< count
; i
++){
434 noteLen
= getAt(src
->fChars
,src
->fLength
, ¬e
, capacity
, i
, UPC_NOTE
, status
);
435 if(U_FAILURE(*status
)){
441 print(note
, noteLen
,"<note>", "</note>", status
);
447 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
449 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
453 static void printAttribute(const char *name
, const char *value
, int32_t /*len*/)
455 write_utf8_file(out
, UnicodeString(" "));
456 write_utf8_file(out
, UnicodeString(name
));
457 write_utf8_file(out
, UnicodeString(" = \""));
458 write_utf8_file(out
, UnicodeString(value
));
459 write_utf8_file(out
, UnicodeString("\""));
462 static void printAttribute(const char *name
, const UnicodeString value
, int32_t /*len*/)
464 write_utf8_file(out
, UnicodeString(" "));
465 write_utf8_file(out
, UnicodeString(name
));
466 write_utf8_file(out
, UnicodeString(" = \""));
467 write_utf8_file(out
, value
);
468 write_utf8_file(out
, UnicodeString("\""));
472 printComments(struct UString
*src
, const char *resName
, UBool printTranslate
, UErrorCode
*status
){
474 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
476 if(status
==NULL
|| U_FAILURE(*status
)){
480 int32_t capacity
= src
->fLength
+ 1;
483 UChar
* desc
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
484 UChar
* trans
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
486 int32_t descLen
= 0, transLen
=0;
487 if(desc
==NULL
|| trans
==NULL
){
488 *status
= U_MEMORY_ALLOCATION_ERROR
;
493 src
->fLength
= removeCmtText(src
->fChars
, src
->fLength
, status
);
494 descLen
= getDescription(src
->fChars
,src
->fLength
, &desc
, capacity
, status
);
495 transLen
= getTranslate(src
->fChars
,src
->fLength
, &trans
, capacity
, status
);
497 /* first print translate attribute */
500 /* print translate attribute */
501 buf
= convertAndEscape(&buf
, 0, &bufLen
, trans
, transLen
, status
);
502 if(U_SUCCESS(*status
)){
503 printAttribute("translate", UnicodeString(buf
, bufLen
, "UTF-8"), bufLen
);
504 write_utf8_file(out
,UnicodeString(">\n"));
506 }else if(getShowWarning()){
507 fprintf(stderr
, "Warning: Tranlate attribute for resource %s cannot be set. XLIFF prohibits it.\n", resName
);
508 /* no translate attribute .. just close the tag */
509 write_utf8_file(out
,UnicodeString(">\n"));
512 /* no translate attribute .. just close the tag */
513 write_utf8_file(out
,UnicodeString(">\n"));
518 print(desc
, descLen
, "<!--", "-->", status
);
525 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
527 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
532 * Print out a containing element, like:
533 * <trans-unit id = "blah" resname = "blah" restype = "x-id-alias" translate = "no">
534 * <group id "calendar_gregorian" resname = "gregorian" restype = "x-icu-array">
536 static char *printContainer(struct SResource
*res
, const char *container
, const char *restype
, const char *mimetype
, const char *id
, UErrorCode
*status
)
538 char resKeyBuffer
[8];
539 const char *resname
= NULL
;
544 resname
= res_getKeyString(srBundle
, res
, resKeyBuffer
);
545 if (resname
!= NULL
&& *resname
!= 0) {
546 sid
= getID(id
, resname
, sid
);
548 sid
= getID(id
, NULL
, sid
);
551 write_utf8_file(out
, UnicodeString("<"));
552 write_utf8_file(out
, UnicodeString(container
));
553 printAttribute("id", sid
, (int32_t) uprv_strlen(sid
));
555 if (resname
!= NULL
) {
556 printAttribute("resname", resname
, (int32_t) uprv_strlen(resname
));
559 if (mimetype
!= NULL
) {
560 printAttribute("mime-type", mimetype
, (int32_t) uprv_strlen(mimetype
));
563 if (restype
!= NULL
) {
564 printAttribute("restype", restype
, (int32_t) uprv_strlen(restype
));
568 if (res
->fComment
.fLength
> 0) {
569 /* printComments will print the closing ">\n" */
570 printComments(&res
->fComment
, resname
, TRUE
, status
);
572 write_utf8_file(out
, UnicodeString(">\n"));
578 /* Writing Functions */
580 static const char *trans_unit
= "trans-unit";
581 static const char *close_trans_unit
= "</trans-unit>\n";
582 static const char *source
= "<source>";
583 static const char *close_source
= "</source>\n";
584 static const char *group
= "group";
585 static const char *close_group
= "</group>\n";
587 static const char *bin_unit
= "bin-unit";
588 static const char *close_bin_unit
= "</bin-unit>\n";
589 static const char *bin_source
= "<bin-source>\n";
590 static const char *close_bin_source
= "</bin-source>\n";
591 static const char *external_file
= "<external-file";
592 /*static const char *close_external_file = "</external-file>\n";*/
593 static const char *internal_file
= "<internal-file";
594 static const char *close_internal_file
= "</internal-file>\n";
596 static const char *application_mimetype
= "application"; /* add "/octet-stream"? */
598 static const char *alias_restype
= "x-icu-alias";
599 static const char *array_restype
= "x-icu-array";
600 static const char *binary_restype
= "x-icu-binary";
601 static const char *integer_restype
= "x-icu-integer";
602 static const char *intvector_restype
= "x-icu-intvector";
603 static const char *table_restype
= "x-icu-table";
606 string_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
612 if(status
==NULL
|| U_FAILURE(*status
)){
616 sid
= printContainer(res
, trans_unit
, NULL
, NULL
, id
, status
);
620 write_utf8_file(out
, UnicodeString(source
));
622 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
, status
);
624 if (U_FAILURE(*status
)) {
628 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
629 write_utf8_file(out
, UnicodeString(close_source
));
631 printNoteElements(&res
->fComment
, status
);
636 write_utf8_file(out
, UnicodeString(close_trans_unit
));
643 alias_write_xml(struct SResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
648 sid
= printContainer(res
, trans_unit
, alias_restype
, NULL
, id
, status
);
652 write_utf8_file(out
, UnicodeString(source
));
654 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
, status
);
656 if(U_FAILURE(*status
)){
659 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
660 write_utf8_file(out
, UnicodeString(close_source
));
662 printNoteElements(&res
->fComment
, status
);
667 write_utf8_file(out
, UnicodeString(close_trans_unit
));
674 array_write_xml(struct SResource
*res
, const char* id
, const char* language
, UErrorCode
*status
) {
678 struct SResource
*current
= NULL
;
680 sid
= printContainer(res
, group
, array_restype
, NULL
, id
, status
);
682 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
;
915 if (U_FAILURE(*status
)) {
919 sid
= printContainer(res
, group
, table_restype
, NULL
, id
, status
);
925 current
= res
->u
.fTable
.fFirst
;
928 while (current
!= NULL
) {
929 res_write_xml(current
, sid
, language
, FALSE
, status
);
931 if(U_FAILURE(*status
)){
936 current
= current
->fNext
;
942 write_utf8_file(out
, UnicodeString(close_group
));
949 res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
) {
951 if (U_FAILURE(*status
)) {
956 switch (res
->fType
) {
958 string_write_xml (res
, id
, language
, status
);
962 alias_write_xml (res
, id
, language
, status
);
965 case URES_INT_VECTOR
:
966 intvector_write_xml (res
, id
, language
, status
);
970 bin_write_xml (res
, id
, language
, status
);
974 int_write_xml (res
, id
, language
, status
);
978 array_write_xml (res
, id
, language
, status
);
982 table_write_xml (res
, id
, language
, isTopLevel
, status
);
990 *status
= U_INTERNAL_PROGRAM_ERROR
;
994 bundle_write_xml(struct SRBRoot
*bundle
, const char *outputDir
,const char* outputEnc
, const char* filename
,
995 char *writtenFilename
, int writtenFilenameLen
,
996 const char* language
, const char* outFileName
, UErrorCode
*status
) {
998 char* xmlfileName
= NULL
;
999 char* outputFileName
= NULL
;
1000 char* originalFileName
= NULL
;
1001 const char* fileStart
= "<file xml:space = \"preserve\" source-language = \"";
1002 const char* file1
= "\" datatype = \"x-icu-resource-bundle\" ";
1003 const char* file2
= "original = \"";
1004 const char* file4
= "\" date = \"";
1005 const char* fileEnd
= "</file>\n";
1006 const char* headerStart
= "<header>\n";
1007 const char* headerEnd
= "</header>\n";
1008 const char* bodyStart
= "<body>\n";
1009 const char* bodyEnd
= "</body>\n";
1011 const char *tool_start
= "<tool";
1012 const char *tool_id
= "genrb-" GENRB_VERSION
"-icu-" U_ICU_VERSION
;
1013 const char *tool_name
= "genrb";
1017 const char* pos
= NULL
;
1018 int32_t first
, index
;
1026 pos
= uprv_strrchr(filename
, '\\');
1028 first
= (int32_t)(pos
- filename
+ 1);
1032 index
= (int32_t)(uprv_strlen(filename
) - uprv_strlen(textExt
) - first
);
1033 originalFileName
= (char *)uprv_malloc(sizeof(char)*index
+1);
1034 uprv_memset(originalFileName
, 0, sizeof(char)*index
+1);
1035 uprv_strncpy(originalFileName
, filename
+ first
, index
);
1037 if(uprv_strcmp(originalFileName
, srBundle
->fLocale
) != 0) {
1038 fprintf(stdout
, "Warning: The file name is not same as the resource name!\n");
1041 temp
= originalFileName
;
1042 originalFileName
= (char *)uprv_malloc(sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1043 uprv_memset(originalFileName
, 0, sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1044 uprv_strcat(originalFileName
, temp
);
1045 uprv_strcat(originalFileName
, textExt
);
1050 if (language
== NULL
) {
1051 /* lang = parseFilename(filename, lang);
1052 if (lang == NULL) {*/
1053 /* now check if locale name is valid or not
1054 * this is to cater for situation where
1055 * pegasusServer.txt contains
1061 lang
= parseFilename(srBundle
->fLocale
, lang
);
1063 * Neither the file name nor the table name inside the
1064 * txt file contain a valid country and language codes
1066 * pegasusServer.txt contains
1073 fprintf(stderr
, "Error: The file name and table name do not contain a valid language code. Please use -l option to specify it.\n");
1074 exit(U_ILLEGAL_ARGUMENT_ERROR
);
1078 lang
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(language
) +1);
1079 uprv_memset(lang
, 0, sizeof(char)*uprv_strlen(language
) +1);
1080 uprv_strcpy(lang
, language
);
1084 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(outFileName
) + 1);
1085 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(outFileName
) + 1);
1086 uprv_strcpy(outputFileName
,outFileName
);
1088 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1089 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1090 uprv_strcpy(outputFileName
,srBundle
->fLocale
);
1094 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputDir
) + uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1095 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputDir
)+ uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1097 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1098 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1102 uprv_strcpy(xmlfileName
, outputDir
);
1103 if(outputDir
[uprv_strlen(outputDir
)-1] !=U_FILE_SEP_CHAR
){
1104 uprv_strcat(xmlfileName
,U_FILE_SEP_STRING
);
1107 uprv_strcat(xmlfileName
,outputFileName
);
1108 uprv_strcat(xmlfileName
,xliffExt
);
1110 if (writtenFilename
) {
1111 uprv_strncpy(writtenFilename
, xmlfileName
, writtenFilenameLen
);
1114 if (U_FAILURE(*status
)) {
1115 goto cleanup_bundle_write_xml
;
1118 out
= T_FileStream_open(xmlfileName
,"w");
1121 *status
= U_FILE_ACCESS_ERROR
;
1122 goto cleanup_bundle_write_xml
;
1124 write_utf8_file(out
, xmlHeader
);
1126 if(outputEnc
&& *outputEnc
!='\0'){
1127 /* store the output encoding */
1129 conv
=ucnv_open(enc
,status
);
1130 if(U_FAILURE(*status
)){
1131 goto cleanup_bundle_write_xml
;
1134 write_utf8_file(out
, bundleStart
);
1136 write_utf8_file(out
, fileStart
);
1137 /* check if lang and language are the same */
1138 if(language
!= NULL
&& uprv_strcmp(lang
, srBundle
->fLocale
)!=0){
1139 fprintf(stderr
,"Warning: The top level tag in the resource and language specified are not the same. Please check the input.\n");
1141 write_utf8_file(out
, UnicodeString(lang
));
1142 write_utf8_file(out
, UnicodeString(file1
));
1143 write_utf8_file(out
, UnicodeString(file2
));
1144 write_utf8_file(out
, UnicodeString(originalFileName
));
1145 write_utf8_file(out
, UnicodeString(file4
));
1148 strftime(timeBuf
, sizeof(timeBuf
), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currTime
));
1149 write_utf8_file(out
, UnicodeString(timeBuf
));
1150 write_utf8_file(out
, UnicodeString("\">\n"));
1154 write_utf8_file(out
, headerStart
);
1159 write_utf8_file(out
, tool_start
);
1160 printAttribute("tool-id", tool_id
, (int32_t) uprv_strlen(tool_id
));
1161 printAttribute("tool-name", tool_name
, (int32_t) uprv_strlen(tool_name
));
1162 write_utf8_file(out
, UnicodeString("/>\n"));
1167 write_utf8_file(out
, UnicodeString(headerEnd
));
1172 write_utf8_file(out
, UnicodeString(bodyStart
));
1175 res_write_xml(bundle
->fRoot
, bundle
->fLocale
, lang
, TRUE
, status
);
1180 write_utf8_file(out
, UnicodeString(bodyEnd
));
1183 write_utf8_file(out
, UnicodeString(fileEnd
));
1186 write_utf8_file(out
, UnicodeString(bundleEnd
));
1187 T_FileStream_close(out
);
1191 cleanup_bundle_write_xml
:
1192 uprv_free(originalFileName
);
1194 if(xmlfileName
!= NULL
) {
1195 uprv_free(xmlfileName
);
1197 if(outputFileName
!= NULL
){
1198 uprv_free(outputFileName
);