1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2002-2015, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
13 * Modification History:
15 * Date Name Description
16 * 10/01/02 Ram Creation.
17 * 02/07/08 Spieth Correct XLIFF generation on EBCDIC platform
19 *******************************************************************************
22 // Safer use of UnicodeString.
23 #ifndef UNISTR_FROM_CHAR_EXPLICIT
24 # define UNISTR_FROM_CHAR_EXPLICIT explicit
27 // Less important, but still a good idea.
28 #ifndef UNISTR_FROM_STRING_EXPLICIT
29 # define UNISTR_FROM_STRING_EXPLICIT explicit
34 #include "unicode/ures.h"
38 #include "unicode/ucnv.h"
43 #include "unicode/ustring.h"
44 #include "unicode/uchar.h"
47 #include "unicode/unistr.h"
48 #include "unicode/utf8.h"
49 #include "unicode/utf16.h"
54 static int tabCount
= 0;
56 static FileStream
* out
=NULL
;
57 static struct SRBRoot
* srBundle
;
58 static const char* outDir
= NULL
;
59 static const char* enc
="";
60 static UConverter
* conv
= NULL
;
62 const char* const* ISOLanguages
;
63 const char* const* ISOCountries
;
64 const char* textExt
= ".txt";
65 const char* xliffExt
= ".xlf";
67 static int32_t write_utf8_file(FileStream
* fileStream
, UnicodeString outString
)
69 UErrorCode status
= U_ZERO_ERROR
;
72 // preflight to get the destination buffer size
76 toUCharPtr(outString
.getBuffer()),
80 // allocate the buffer
81 char* dest
= (char*)uprv_malloc(len
);
82 status
= U_ZERO_ERROR
;
88 toUCharPtr(outString
.getBuffer()),
92 // write data to out file
93 int32_t ret
= T_FileStream_write(fileStream
, dest
, len
);
98 /*write indentation for formatting*/
99 static void write_tabs(FileStream
* os
){
101 for(;i
<=tabCount
;i
++){
102 write_utf8_file(os
,UnicodeString(" "));
106 /*get ID for each element. ID is globally unique.*/
107 static char* getID(const char* id
, const char* curKey
, char* result
) {
109 result
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(id
) + 1);
110 uprv_memset(result
, 0, sizeof(char)*uprv_strlen(id
) + 1);
111 uprv_strcpy(result
, id
);
113 result
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
114 uprv_memset(result
, 0, sizeof(char)*(uprv_strlen(id
) + 1 + uprv_strlen(curKey
)) + 1);
116 uprv_strcpy(result
, id
);
117 uprv_strcat(result
, "_");
119 uprv_strcat(result
, curKey
);
124 /*compute CRC for binary code*/
125 /* The code is from http://www.theorem.com/java/CRC32.java
126 * Calculates the CRC32 - 32 bit Cyclical Redundancy Check
127 * <P> This check is used in numerous systems to verify the integrity
128 * of information. It's also used as a hashing function. Unlike a regular
129 * checksum, it's sensitive to the order of the characters.
130 * It produces a 32 bit
132 * @author Michael Lecuyer (mjl@theorem.com)
133 * @version 1.1 August 11, 1998
136 /* ICU is not endian portable, because ICU data generated on big endian machines can be
137 * ported to big endian machines but not to little endian machines and vice versa. The
138 * conversion is not portable across platforms with different endianess.
141 uint32_t computeCRC(const char *ptr
, uint32_t len
, uint32_t lastcrc
){
151 #define CRC32_POLYNOMIAL 0xEDB88320
154 for (i
= 0; i
<= 255; i
++) {
156 for (j
= 8; j
> 0; j
--) {
157 if ((crc2
& 1) == 1) {
158 crc2
= (crc2
>> 1) ^ CRC32_POLYNOMIAL
;
168 temp1
= (uint32_t)crc
>>8;
169 temp2
= crc_ta
[(crc
^*ptr
) & 0xFF];
176 static void strnrepchr(char* src
, int32_t srcLen
, char s
, char r
){
178 for(i
=0;i
<srcLen
;i
++){
184 /* Parse the filename, and get its language information.
185 * If it fails to get the language information from the filename,
186 * use "en" as the default value for language
188 static char* parseFilename(const char* id
, char* /*lang*/) {
189 int idLen
= (int) uprv_strlen(id
);
190 char* localeID
= (char*) uprv_malloc(idLen
);
192 int canonCapacity
= 0;
196 UErrorCode status
= U_ZERO_ERROR
;
197 const char *ext
= uprv_strchr(id
, '.');
200 pos
= (int) (ext
- id
);
204 uprv_memcpy(localeID
, id
, pos
);
205 localeID
[pos
]=0; /* NUL terminate the string */
207 canonCapacity
=pos
*3;
208 canon
= (char*) uprv_malloc(canonCapacity
);
209 canonLen
= uloc_canonicalize(localeID
, canon
, canonCapacity
, &status
);
211 if(U_FAILURE(status
)){
212 fprintf(stderr
, "Could not canonicalize the locale ID: %s. Error: %s\n", localeID
, u_errorName(status
));
215 strnrepchr(canon
, canonLen
, '_', '-');
219 static const char* xmlHeader
= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
221 static const char* bundleStart
= "<xliff version = \"1.2\" "
222 "xmlns='urn:oasis:names:tc:xliff:document:1.2' "
223 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
224 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'>\n";
226 static const char* bundleStart
= "<xliff version = \"1.1\" "
227 "xmlns='urn:oasis:names:tc:xliff:document:1.1' "
228 "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
229 "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd'>\n";
231 static const char* bundleEnd
= "</xliff>\n";
233 void res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
);
235 static char* convertAndEscape(char** pDest
, int32_t destCap
, int32_t* destLength
,
236 const UChar
* src
, int32_t srcLen
, UErrorCode
* status
){
243 if(status
==NULL
|| U_FAILURE(*status
) || pDest
==NULL
|| srcLen
==0 || src
== NULL
){
247 if(dest
==NULL
|| destCap
<=0){
248 destCap
= srcLen
* 8;
249 dest
= (char*) uprv_malloc(sizeof(char) * destCap
);
251 *status
=U_MEMORY_ALLOCATION_ERROR
;
258 while(srcIndex
<srcLen
){
259 U16_NEXT(src
, srcIndex
, srcLen
, c
);
261 if (U16_IS_LEAD(c
) || U16_IS_TRAIL(c
)) {
262 *status
= U_ILLEGAL_CHAR_FOUND
;
263 fprintf(stderr
, "Illegal Surrogate! \n");
268 if((destLen
+U8_LENGTH(c
)) < destCap
){
274 uprv_strcpy(dest
+( destLen
),"\x26\x61\x6d\x70\x3b"); /* &*/
275 destLen
+=(int32_t)uprv_strlen("\x26\x61\x6d\x70\x3b");
278 uprv_strcpy(dest
+(destLen
),"\x26\x6c\x74\x3b"); /* <*/
279 destLen
+=(int32_t)uprv_strlen("\x26\x6c\x74\x3b");
282 uprv_strcpy(dest
+(destLen
),"\x26\x67\x74\x3b"); /* >*/
283 destLen
+=(int32_t)uprv_strlen("\x26\x67\x74\x3b");
286 uprv_strcpy(dest
+(destLen
),"\x26\x71\x75\x6f\x74\x3b"); /* "*/
287 destLen
+=(int32_t)uprv_strlen("\x26\x71\x75\x6f\x74\x3b");
290 uprv_strcpy(dest
+(destLen
),"\x26\x61\x70\x6f\x73\x3b"); /* ' */
291 destLen
+=(int32_t)uprv_strlen("\x26\x61\x70\x6f\x73\x3b");
294 /* Disallow C0 controls except TAB, CR, LF*/
327 *status
= U_ILLEGAL_CHAR_FOUND
;
328 fprintf(stderr
, "Illegal Character \\u%04X!\n",(int)c
);
332 dest
[destLen
++]=(char)c
;
335 UBool isError
= FALSE
;
336 U8_APPEND((unsigned char*)dest
,destLen
,destCap
,c
,isError
);
338 *status
= U_ILLEGAL_CHAR_FOUND
;
339 fprintf(stderr
, "Illegal Character \\U%08X!\n",(int)c
);
347 temp
= (char*) uprv_malloc(sizeof(char)*destCap
);
349 *status
=U_MEMORY_ALLOCATION_ERROR
;
353 uprv_memmove(temp
,dest
,destLen
);
361 *destLength
= destLen
;
365 #define ASTERISK 0x002A
369 #define AT_SIGN 0x0040
371 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0
373 trim(char **src
, int32_t *len
){
377 if(src
== NULL
|| *src
== NULL
){
381 /* trim from the end */
382 for( i
=(*len
-1); i
>= 0; i
--){
400 print(UChar
* src
, int32_t srcLen
,const char *tagStart
,const char *tagEnd
, UErrorCode
*status
){
401 int32_t bufCapacity
= srcLen
*4;
405 if(U_FAILURE(*status
)){
409 buf
= (char*) (uprv_malloc(bufCapacity
));
411 fprintf(stderr
, "Could not allocate memory!!");
412 exit(U_MEMORY_ALLOCATION_ERROR
);
414 buf
= convertAndEscape(&buf
, bufCapacity
, &bufLen
, src
, srcLen
,status
);
415 if(U_SUCCESS(*status
)){
417 write_utf8_file(out
,UnicodeString(tagStart
));
418 write_utf8_file(out
,UnicodeString(buf
, bufLen
, "UTF-8"));
419 write_utf8_file(out
,UnicodeString(tagEnd
));
420 write_utf8_file(out
,UnicodeString("\n"));
427 printNoteElements(const UString
*src
, UErrorCode
*status
){
429 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
431 int32_t capacity
= 0;
440 capacity
= src
->fLength
;
441 note
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
443 count
= getCount(src
->fChars
,src
->fLength
, UPC_NOTE
, status
);
444 if(U_FAILURE(*status
)){
448 for(i
=0; i
< count
; i
++){
449 noteLen
= getAt(src
->fChars
,src
->fLength
, ¬e
, capacity
, i
, UPC_NOTE
, status
);
450 if(U_FAILURE(*status
)){
456 print(note
, noteLen
,"<note>", "</note>", status
);
462 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
464 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
468 static void printAttribute(const char *name
, const char *value
, int32_t /*len*/)
470 write_utf8_file(out
, UnicodeString(" "));
471 write_utf8_file(out
, UnicodeString(name
));
472 write_utf8_file(out
, UnicodeString(" = \""));
473 write_utf8_file(out
, UnicodeString(value
));
474 write_utf8_file(out
, UnicodeString("\""));
477 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
478 static void printAttribute(const char *name
, const UnicodeString value
, int32_t /*len*/)
480 write_utf8_file(out
, UnicodeString(" "));
481 write_utf8_file(out
, UnicodeString(name
));
482 write_utf8_file(out
, UnicodeString(" = \""));
483 write_utf8_file(out
, value
);
484 write_utf8_file(out
, UnicodeString("\""));
489 printComments(struct UString
*src
, const char *resName
, UBool printTranslate
, UErrorCode
*status
){
491 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
493 if(status
==NULL
|| U_FAILURE(*status
)){
497 int32_t capacity
= src
->fLength
+ 1;
500 UChar
* desc
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
501 UChar
* trans
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* capacity
);
503 int32_t descLen
= 0, transLen
=0;
504 if(desc
==NULL
|| trans
==NULL
){
505 *status
= U_MEMORY_ALLOCATION_ERROR
;
510 // TODO: make src const, stop modifying it in-place, make printContainer() take const resource, etc.
511 src
->fLength
= removeCmtText(src
->fChars
, src
->fLength
, status
);
512 descLen
= getDescription(src
->fChars
,src
->fLength
, &desc
, capacity
, status
);
513 transLen
= getTranslate(src
->fChars
,src
->fLength
, &trans
, capacity
, status
);
515 /* first print translate attribute */
518 /* print translate attribute */
519 buf
= convertAndEscape(&buf
, 0, &bufLen
, trans
, transLen
, status
);
520 if(U_SUCCESS(*status
)){
521 printAttribute("translate", UnicodeString(buf
, bufLen
, "UTF-8"), bufLen
);
522 write_utf8_file(out
,UnicodeString(">\n"));
524 }else if(getShowWarning()){
525 fprintf(stderr
, "Warning: Tranlate attribute for resource %s cannot be set. XLIFF prohibits it.\n", resName
);
526 /* no translate attribute .. just close the tag */
527 write_utf8_file(out
,UnicodeString(">\n"));
530 /* no translate attribute .. just close the tag */
531 write_utf8_file(out
,UnicodeString(">\n"));
536 print(desc
, descLen
, "<!--", "-->", status
);
543 fprintf(stderr
, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
545 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
550 * Print out a containing element, like:
551 * <trans-unit id = "blah" resname = "blah" restype = "x-id-alias" translate = "no">
552 * <group id "calendar_gregorian" resname = "gregorian" restype = "x-icu-array">
554 static char *printContainer(SResource
*res
, const char *container
, const char *restype
, const char *mimetype
, const char *id
, UErrorCode
*status
)
556 const char *resname
= NULL
;
561 resname
= res
->getKeyString(srBundle
);
562 if (resname
!= NULL
&& *resname
!= 0) {
563 sid
= getID(id
, resname
, sid
);
565 sid
= getID(id
, NULL
, sid
);
568 write_utf8_file(out
, UnicodeString("<"));
569 write_utf8_file(out
, UnicodeString(container
));
570 printAttribute("id", sid
, (int32_t) uprv_strlen(sid
));
572 if (resname
!= NULL
) {
573 printAttribute("resname", resname
, (int32_t) uprv_strlen(resname
));
576 if (mimetype
!= NULL
) {
577 printAttribute("mime-type", mimetype
, (int32_t) uprv_strlen(mimetype
));
580 if (restype
!= NULL
) {
581 printAttribute("restype", restype
, (int32_t) uprv_strlen(restype
));
585 if (res
->fComment
.fLength
> 0) {
586 /* printComments will print the closing ">\n" */
587 printComments(&res
->fComment
, resname
, TRUE
, status
);
589 write_utf8_file(out
, UnicodeString(">\n"));
595 /* Writing Functions */
597 static const char *trans_unit
= "trans-unit";
598 static const char *close_trans_unit
= "</trans-unit>\n";
599 static const char *source
= "<source>";
600 static const char *close_source
= "</source>\n";
601 static const char *group
= "group";
602 static const char *close_group
= "</group>\n";
604 static const char *bin_unit
= "bin-unit";
605 static const char *close_bin_unit
= "</bin-unit>\n";
606 static const char *bin_source
= "<bin-source>\n";
607 static const char *close_bin_source
= "</bin-source>\n";
608 static const char *external_file
= "<external-file";
609 /*static const char *close_external_file = "</external-file>\n";*/
610 static const char *internal_file
= "<internal-file";
611 static const char *close_internal_file
= "</internal-file>\n";
613 static const char *application_mimetype
= "application"; /* add "/octet-stream"? */
615 static const char *alias_restype
= "x-icu-alias";
616 static const char *array_restype
= "x-icu-array";
617 static const char *binary_restype
= "x-icu-binary";
618 static const char *integer_restype
= "x-icu-integer";
619 static const char *intvector_restype
= "x-icu-intvector";
620 static const char *table_restype
= "x-icu-table";
623 string_write_xml(StringResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
629 if(status
==NULL
|| U_FAILURE(*status
)){
633 sid
= printContainer(res
, trans_unit
, NULL
, NULL
, id
, status
);
637 write_utf8_file(out
, UnicodeString(source
));
639 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->getBuffer(), res
->length(), status
);
641 if (U_FAILURE(*status
)) {
645 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
646 write_utf8_file(out
, UnicodeString(close_source
));
648 printNoteElements(&res
->fComment
, status
);
653 write_utf8_file(out
, UnicodeString(close_trans_unit
));
660 alias_write_xml(AliasResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
665 sid
= printContainer(res
, trans_unit
, alias_restype
, NULL
, id
, status
);
669 write_utf8_file(out
, UnicodeString(source
));
671 buf
= convertAndEscape(&buf
, 0, &bufLen
, res
->getBuffer(), res
->length(), status
);
673 if(U_FAILURE(*status
)){
676 write_utf8_file(out
, UnicodeString(buf
, bufLen
, "UTF-8"));
677 write_utf8_file(out
, UnicodeString(close_source
));
679 printNoteElements(&res
->fComment
, status
);
684 write_utf8_file(out
, UnicodeString(close_trans_unit
));
691 array_write_xml(ArrayResource
*res
, const char* id
, const char* language
, UErrorCode
*status
) {
695 struct SResource
*current
= NULL
;
697 sid
= printContainer(res
, group
, array_restype
, NULL
, id
, status
);
699 current
= res
->fFirst
;
701 while (current
!= NULL
) {
705 itostr(c
, index
, 10, 0);
707 subId
= getID(sid
, c
, subId
);
709 res_write_xml(current
, subId
, language
, FALSE
, status
);
713 if(U_FAILURE(*status
)){
717 current
= current
->fNext
;
722 write_utf8_file(out
, UnicodeString(close_group
));
728 intvector_write_xml(IntVectorResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
733 char buf
[256] = {'0'};
735 sid
= printContainer(res
, group
, intvector_restype
, NULL
, id
, status
);
737 for(i
= 0; i
< res
->fCount
; i
+= 1) {
741 ivd
= getID(sid
, c
, ivd
);
742 len
= itostr(buf
, res
->fArray
[i
], 10, 0);
745 write_utf8_file(out
, UnicodeString("<"));
746 write_utf8_file(out
, UnicodeString(trans_unit
));
748 printAttribute("id", ivd
, (int32_t)uprv_strlen(ivd
));
749 printAttribute("restype", integer_restype
, (int32_t) strlen(integer_restype
));
751 write_utf8_file(out
, UnicodeString(">\n"));
755 write_utf8_file(out
, UnicodeString(source
));
757 write_utf8_file(out
, UnicodeString(buf
, len
));
759 write_utf8_file(out
, UnicodeString(close_source
));
762 write_utf8_file(out
, UnicodeString(close_trans_unit
));
771 write_utf8_file(out
, UnicodeString(close_group
));
777 int_write_xml(IntResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
782 sid
= printContainer(res
, trans_unit
, integer_restype
, NULL
, id
, status
);
786 write_utf8_file(out
, UnicodeString(source
));
788 len
= itostr(buf
, res
->fValue
, 10, 0);
789 write_utf8_file(out
, UnicodeString(buf
, len
));
791 write_utf8_file(out
, UnicodeString(close_source
));
793 printNoteElements(&res
->fComment
, status
);
798 write_utf8_file(out
, UnicodeString(close_trans_unit
));
805 bin_write_xml(BinaryResource
*res
, const char* id
, const char* /*language*/, UErrorCode
*status
) {
806 const char* m_type
= application_mimetype
;
808 uint32_t crc
= 0xFFFFFFFF;
810 char fileName
[1024] ={0};
811 int32_t tLen
= ( outDir
== NULL
) ? 0 :(int32_t)uprv_strlen(outDir
);
812 char* fn
= (char*) uprv_malloc(sizeof(char) * (tLen
+1024 +
813 (res
->fFileName
!=NULL
?
814 uprv_strlen(res
->fFileName
) :0)));
815 const char* ext
= NULL
;
821 if(res
->fFileName
!= NULL
){
822 uprv_strcpy(fileName
, res
->fFileName
);
823 f
= uprv_strrchr(fileName
, '\\');
831 ext
= uprv_strrchr(fileName
, '.');
834 fprintf(stderr
, "Error: %s is an unknown binary filename type.\n", fileName
);
835 exit(U_ILLEGAL_ARGUMENT_ERROR
);
838 if(uprv_strcmp(ext
, ".jpg")==0 || uprv_strcmp(ext
, ".jpeg")==0 || uprv_strcmp(ext
, ".gif")==0 ){
840 } else if(uprv_strcmp(ext
, ".wav")==0 || uprv_strcmp(ext
, ".au")==0 ){
842 } else if(uprv_strcmp(ext
, ".avi")==0 || uprv_strcmp(ext
, ".mpg")==0 || uprv_strcmp(ext
, ".mpeg")==0){
844 } else if(uprv_strcmp(ext
, ".txt")==0 || uprv_strcmp(ext
, ".text")==0){
848 sid
= printContainer(res
, bin_unit
, binary_restype
, m_type
, id
, status
);
852 write_utf8_file(out
, UnicodeString(bin_source
));
857 write_utf8_file(out
, UnicodeString(external_file
));
858 printAttribute("href", f
, (int32_t)uprv_strlen(f
));
859 write_utf8_file(out
, UnicodeString("/>\n"));
863 write_utf8_file(out
, UnicodeString(close_bin_source
));
865 printNoteElements(&res
->fComment
, status
);
868 write_utf8_file(out
, UnicodeString(close_bin_unit
));
870 char temp
[256] = {0};
874 sid
= printContainer(res
, bin_unit
, binary_restype
, m_type
, id
, status
);
877 write_utf8_file(out
, UnicodeString(bin_source
));
882 write_utf8_file(out
, UnicodeString(internal_file
));
883 printAttribute("form", application_mimetype
, (int32_t) uprv_strlen(application_mimetype
));
885 while(i
<res
->fLength
){
886 len
= itostr(temp
, res
->fData
[i
], 16, 2);
887 crc
= computeCRC(temp
, len
, crc
);
891 len
= itostr(temp
, crc
, 10, 0);
892 printAttribute("crc", temp
, len
);
894 write_utf8_file(out
, UnicodeString(">"));
897 while(i
<res
->fLength
){
898 len
= itostr(temp
, res
->fData
[i
], 16, 2);
899 write_utf8_file(out
, UnicodeString(temp
));
903 write_utf8_file(out
, UnicodeString(close_internal_file
));
908 write_utf8_file(out
, UnicodeString(close_bin_source
));
909 printNoteElements(&res
->fComment
, status
);
913 write_utf8_file(out
, UnicodeString(close_bin_unit
));
925 table_write_xml(TableResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
) {
929 struct SResource
*current
= NULL
;
932 if (U_FAILURE(*status
)) {
936 sid
= printContainer(res
, group
, table_restype
, NULL
, id
, status
);
942 current
= res
->fFirst
;
945 while (current
!= NULL
) {
946 res_write_xml(current
, sid
, language
, FALSE
, status
);
948 if(U_FAILURE(*status
)){
953 current
= current
->fNext
;
959 write_utf8_file(out
, UnicodeString(close_group
));
966 res_write_xml(struct SResource
*res
, const char* id
, const char* language
, UBool isTopLevel
, UErrorCode
*status
) {
968 if (U_FAILURE(*status
)) {
973 switch (res
->fType
) {
975 string_write_xml (static_cast<StringResource
*>(res
), id
, language
, status
);
979 alias_write_xml (static_cast<AliasResource
*>(res
), id
, language
, status
);
982 case URES_INT_VECTOR
:
983 intvector_write_xml (static_cast<IntVectorResource
*>(res
), id
, language
, status
);
987 bin_write_xml (static_cast<BinaryResource
*>(res
), id
, language
, status
);
991 int_write_xml (static_cast<IntResource
*>(res
), id
, language
, status
);
995 array_write_xml (static_cast<ArrayResource
*>(res
), id
, language
, status
);
999 table_write_xml (static_cast<TableResource
*>(res
), id
, language
, isTopLevel
, status
);
1007 *status
= U_INTERNAL_PROGRAM_ERROR
;
1011 bundle_write_xml(struct SRBRoot
*bundle
, const char *outputDir
,const char* outputEnc
, const char* filename
,
1012 char *writtenFilename
, int writtenFilenameLen
,
1013 const char* language
, const char* outFileName
, UErrorCode
*status
) {
1015 char* xmlfileName
= NULL
;
1016 char* outputFileName
= NULL
;
1017 char* originalFileName
= NULL
;
1018 const char* fileStart
= "<file xml:space = \"preserve\" source-language = \"";
1019 const char* file1
= "\" datatype = \"x-icu-resource-bundle\" ";
1020 const char* file2
= "original = \"";
1021 const char* file4
= "\" date = \"";
1022 const char* fileEnd
= "</file>\n";
1023 const char* headerStart
= "<header>\n";
1024 const char* headerEnd
= "</header>\n";
1025 const char* bodyStart
= "<body>\n";
1026 const char* bodyEnd
= "</body>\n";
1028 const char *tool_start
= "<tool";
1029 const char *tool_id
= "genrb-" GENRB_VERSION
"-icu-" U_ICU_VERSION
;
1030 const char *tool_name
= "genrb";
1034 const char* pos
= NULL
;
1035 int32_t first
, index
;
1043 pos
= uprv_strrchr(filename
, '\\');
1045 first
= (int32_t)(pos
- filename
+ 1);
1049 index
= (int32_t)(uprv_strlen(filename
) - uprv_strlen(textExt
) - first
);
1050 originalFileName
= (char *)uprv_malloc(sizeof(char)*index
+1);
1051 uprv_memset(originalFileName
, 0, sizeof(char)*index
+1);
1052 uprv_strncpy(originalFileName
, filename
+ first
, index
);
1054 if(uprv_strcmp(originalFileName
, srBundle
->fLocale
) != 0) {
1055 fprintf(stdout
, "Warning: The file name is not same as the resource name!\n");
1058 temp
= originalFileName
;
1059 originalFileName
= (char *)uprv_malloc(sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1060 uprv_memset(originalFileName
, 0, sizeof(char)* (uprv_strlen(temp
)+uprv_strlen(textExt
)) + 1);
1061 uprv_strcat(originalFileName
, temp
);
1062 uprv_strcat(originalFileName
, textExt
);
1067 if (language
== NULL
) {
1068 /* lang = parseFilename(filename, lang);
1069 if (lang == NULL) {*/
1070 /* now check if locale name is valid or not
1071 * this is to cater for situation where
1072 * pegasusServer.txt contains
1078 lang
= parseFilename(srBundle
->fLocale
, lang
);
1080 * Neither the file name nor the table name inside the
1081 * txt file contain a valid country and language codes
1083 * pegasusServer.txt contains
1090 fprintf(stderr
, "Error: The file name and table name do not contain a valid language code. Please use -l option to specify it.\n");
1091 exit(U_ILLEGAL_ARGUMENT_ERROR
);
1095 lang
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(language
) +1);
1096 uprv_memset(lang
, 0, sizeof(char)*uprv_strlen(language
) +1);
1097 uprv_strcpy(lang
, language
);
1101 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(outFileName
) + 1);
1102 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(outFileName
) + 1);
1103 uprv_strcpy(outputFileName
,outFileName
);
1105 outputFileName
= (char *)uprv_malloc(sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1106 uprv_memset(outputFileName
, 0, sizeof(char)*uprv_strlen(srBundle
->fLocale
) + 1);
1107 uprv_strcpy(outputFileName
,srBundle
->fLocale
);
1111 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputDir
) + uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1112 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputDir
)+ uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
) + 1) +1);
1114 xmlfileName
= (char *)uprv_malloc(sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1115 uprv_memset(xmlfileName
, 0, sizeof(char)*(uprv_strlen(outputFileName
) + uprv_strlen(xliffExt
)) +1);
1119 uprv_strcpy(xmlfileName
, outputDir
);
1120 if(outputDir
[uprv_strlen(outputDir
)-1] !=U_FILE_SEP_CHAR
){
1121 uprv_strcat(xmlfileName
,U_FILE_SEP_STRING
);
1124 uprv_strcat(xmlfileName
,outputFileName
);
1125 uprv_strcat(xmlfileName
,xliffExt
);
1127 if (writtenFilename
) {
1128 uprv_strncpy(writtenFilename
, xmlfileName
, writtenFilenameLen
);
1131 if (U_FAILURE(*status
)) {
1132 goto cleanup_bundle_write_xml
;
1135 out
= T_FileStream_open(xmlfileName
,"w");
1138 *status
= U_FILE_ACCESS_ERROR
;
1139 goto cleanup_bundle_write_xml
;
1141 write_utf8_file(out
, UnicodeString(xmlHeader
));
1143 if(outputEnc
&& *outputEnc
!='\0'){
1144 /* store the output encoding */
1146 conv
=ucnv_open(enc
,status
);
1147 if(U_FAILURE(*status
)){
1148 goto cleanup_bundle_write_xml
;
1151 write_utf8_file(out
, UnicodeString(bundleStart
));
1153 write_utf8_file(out
, UnicodeString(fileStart
));
1154 /* check if lang and language are the same */
1155 if(language
!= NULL
&& uprv_strcmp(lang
, srBundle
->fLocale
)!=0){
1156 fprintf(stderr
,"Warning: The top level tag in the resource and language specified are not the same. Please check the input.\n");
1158 write_utf8_file(out
, UnicodeString(lang
));
1159 write_utf8_file(out
, UnicodeString(file1
));
1160 write_utf8_file(out
, UnicodeString(file2
));
1161 write_utf8_file(out
, UnicodeString(originalFileName
));
1162 write_utf8_file(out
, UnicodeString(file4
));
1165 strftime(timeBuf
, sizeof(timeBuf
), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currTime
));
1166 write_utf8_file(out
, UnicodeString(timeBuf
));
1167 write_utf8_file(out
, UnicodeString("\">\n"));
1171 write_utf8_file(out
, UnicodeString(headerStart
));
1176 write_utf8_file(out
, UnicodeString(tool_start
));
1177 printAttribute("tool-id", tool_id
, (int32_t) uprv_strlen(tool_id
));
1178 printAttribute("tool-name", tool_name
, (int32_t) uprv_strlen(tool_name
));
1179 write_utf8_file(out
, UnicodeString("/>\n"));
1184 write_utf8_file(out
, UnicodeString(headerEnd
));
1189 write_utf8_file(out
, UnicodeString(bodyStart
));
1192 res_write_xml(bundle
->fRoot
, bundle
->fLocale
, lang
, TRUE
, status
);
1197 write_utf8_file(out
, UnicodeString(bodyEnd
));
1200 write_utf8_file(out
, UnicodeString(fileEnd
));
1203 write_utf8_file(out
, UnicodeString(bundleEnd
));
1204 T_FileStream_close(out
);
1208 cleanup_bundle_write_xml
:
1209 uprv_free(originalFileName
);
1211 if(xmlfileName
!= NULL
) {
1212 uprv_free(xmlfileName
);
1214 if(outputFileName
!= NULL
){
1215 uprv_free(outputFileName
);