PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/deps/icu-small/source/tools/genrb/wrtxml.cpp

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