OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * | 3 * |
4 * Copyright (C) 1998-2014, International Business Machines | 4 * Copyright (C) 1998-2015, International Business Machines |
5 * Corporation and others. All Rights Reserved. | 5 * Corporation and others. All Rights Reserved. |
6 * | 6 * |
7 ******************************************************************************* | 7 ******************************************************************************* |
8 * | 8 * |
9 * File parse.cpp | 9 * File parse.cpp |
10 * | 10 * |
11 * Modification History: | 11 * Modification History: |
12 * | 12 * |
13 * Date Name Description | 13 * Date Name Description |
14 * 05/26/99 stephen Creation. | 14 * 05/26/99 stephen Creation. |
15 * 02/25/00 weiv Overhaul to write udata | 15 * 02/25/00 weiv Overhaul to write udata |
16 * 5/10/01 Ram removed ustdio dependency | 16 * 5/10/01 Ram removed ustdio dependency |
17 * 06/10/2001 Dominic Ludlam <dom@recoil.org> Rewritten | 17 * 06/10/2001 Dominic Ludlam <dom@recoil.org> Rewritten |
18 ******************************************************************************* | 18 ******************************************************************************* |
19 */ | 19 */ |
20 | 20 |
21 // Safer use of UnicodeString. | 21 // Safer use of UnicodeString. |
22 #ifndef UNISTR_FROM_CHAR_EXPLICIT | 22 #ifndef UNISTR_FROM_CHAR_EXPLICIT |
23 # define UNISTR_FROM_CHAR_EXPLICIT explicit | 23 # define UNISTR_FROM_CHAR_EXPLICIT explicit |
24 #endif | 24 #endif |
25 | 25 |
26 // Less important, but still a good idea. | 26 // Less important, but still a good idea. |
27 #ifndef UNISTR_FROM_STRING_EXPLICIT | 27 #ifndef UNISTR_FROM_STRING_EXPLICIT |
28 # define UNISTR_FROM_STRING_EXPLICIT explicit | 28 # define UNISTR_FROM_STRING_EXPLICIT explicit |
29 #endif | 29 #endif |
30 | 30 |
| 31 #include <assert.h> |
31 #include "parse.h" | 32 #include "parse.h" |
32 #include "errmsg.h" | 33 #include "errmsg.h" |
33 #include "uhash.h" | 34 #include "uhash.h" |
34 #include "cmemory.h" | 35 #include "cmemory.h" |
35 #include "cstring.h" | 36 #include "cstring.h" |
36 #include "uinvchar.h" | 37 #include "uinvchar.h" |
37 #include "read.h" | 38 #include "read.h" |
38 #include "ustr.h" | 39 #include "ustr.h" |
39 #include "reslist.h" | 40 #include "reslist.h" |
40 #include "rbt_pars.h" | 41 #include "rbt_pars.h" |
41 #include "genrb.h" | 42 #include "genrb.h" |
| 43 #include "unicode/stringpiece.h" |
| 44 #include "unicode/unistr.h" |
42 #include "unicode/ustring.h" | 45 #include "unicode/ustring.h" |
43 #include "unicode/uscript.h" | 46 #include "unicode/uscript.h" |
44 #include "unicode/utf16.h" | 47 #include "unicode/utf16.h" |
45 #include "unicode/putil.h" | 48 #include "unicode/putil.h" |
| 49 #include "charstr.h" |
46 #include "collationbuilder.h" | 50 #include "collationbuilder.h" |
47 #include "collationdata.h" | 51 #include "collationdata.h" |
48 #include "collationdatareader.h" | 52 #include "collationdatareader.h" |
49 #include "collationdatawriter.h" | 53 #include "collationdatawriter.h" |
50 #include "collationfastlatinbuilder.h" | 54 #include "collationfastlatinbuilder.h" |
51 #include "collationinfo.h" | 55 #include "collationinfo.h" |
52 #include "collationroot.h" | 56 #include "collationroot.h" |
53 #include "collationruleparser.h" | 57 #include "collationruleparser.h" |
54 #include "collationtailoring.h" | 58 #include "collationtailoring.h" |
55 #include <stdio.h> | 59 #include <stdio.h> |
56 | 60 |
57 /* Number of tokens to read ahead of the current stream position */ | 61 /* Number of tokens to read ahead of the current stream position */ |
58 #define MAX_LOOKAHEAD 3 | 62 #define MAX_LOOKAHEAD 3 |
59 | 63 |
60 #define CR 0x000D | 64 #define CR 0x000D |
61 #define LF 0x000A | 65 #define LF 0x000A |
62 #define SPACE 0x0020 | 66 #define SPACE 0x0020 |
63 #define TAB 0x0009 | 67 #define TAB 0x0009 |
64 #define ESCAPE 0x005C | 68 #define ESCAPE 0x005C |
65 #define HASH 0x0023 | 69 #define HASH 0x0023 |
66 #define QUOTE 0x0027 | 70 #define QUOTE 0x0027 |
67 #define ZERO 0x0030 | 71 #define ZERO 0x0030 |
68 #define STARTCOMMAND 0x005B | 72 #define STARTCOMMAND 0x005B |
69 #define ENDCOMMAND 0x005D | 73 #define ENDCOMMAND 0x005D |
70 #define OPENSQBRACKET 0x005B | 74 #define OPENSQBRACKET 0x005B |
71 #define CLOSESQBRACKET 0x005D | 75 #define CLOSESQBRACKET 0x005D |
72 | 76 |
| 77 using icu::CharString; |
| 78 using icu::LocalMemory; |
73 using icu::LocalPointer; | 79 using icu::LocalPointer; |
| 80 using icu::LocalUCHARBUFPointer; |
| 81 using icu::StringPiece; |
74 using icu::UnicodeString; | 82 using icu::UnicodeString; |
75 | 83 |
76 struct Lookahead | 84 struct Lookahead |
77 { | 85 { |
78 enum ETokenType type; | 86 enum ETokenType type; |
79 struct UString value; | 87 struct UString value; |
80 struct UString comment; | 88 struct UString comment; |
81 uint32_t line; | 89 uint32_t line; |
82 }; | 90 }; |
83 | 91 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 fprintf(stderr, " Warning: writing empty transliteration data ( UCONFIG_NO_T
RANSLITERATION ) \n"); | 517 fprintf(stderr, " Warning: writing empty transliteration data ( UCONFIG_NO_T
RANSLITERATION ) \n"); |
510 #endif | 518 #endif |
511 result = string_open(state->bundle, tag, pTarget, size, NULL, status); | 519 result = string_open(state->bundle, tag, pTarget, size, NULL, status); |
512 | 520 |
513 ucbuf_close(ucbuf); | 521 ucbuf_close(ucbuf); |
514 uprv_free(pTarget); | 522 uprv_free(pTarget); |
515 T_FileStream_close(file); | 523 T_FileStream_close(file); |
516 | 524 |
517 return result; | 525 return result; |
518 } | 526 } |
519 static struct SResource* dependencyArray = NULL; | 527 static ArrayResource* dependencyArray = NULL; |
520 | 528 |
521 static struct SResource * | 529 static struct SResource * |
522 parseDependency(ParseState* state, char *tag, uint32_t startline, const struct U
String* comment, UErrorCode *status) | 530 parseDependency(ParseState* state, char *tag, uint32_t startline, const struct U
String* comment, UErrorCode *status) |
523 { | 531 { |
524 struct SResource *result = NULL; | 532 struct SResource *result = NULL; |
525 struct SResource *elem = NULL; | 533 struct SResource *elem = NULL; |
526 struct UString *tokenValue; | 534 struct UString *tokenValue; |
527 uint32_t line; | 535 uint32_t line; |
528 char filename[256] = { '\0' }; | 536 char filename[256] = { '\0' }; |
529 char cs[128] = { '\0' }; | 537 char cs[128] = { '\0' }; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 } | 572 } |
565 } | 573 } |
566 if(dependencyArray==NULL){ | 574 if(dependencyArray==NULL){ |
567 dependencyArray = array_open(state->bundle, "%%DEPENDENCY", NULL, status
); | 575 dependencyArray = array_open(state->bundle, "%%DEPENDENCY", NULL, status
); |
568 } | 576 } |
569 if(tag!=NULL){ | 577 if(tag!=NULL){ |
570 result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue-
>fLength, comment, status); | 578 result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue-
>fLength, comment, status); |
571 } | 579 } |
572 elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLen
gth, comment, status); | 580 elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLen
gth, comment, status); |
573 | 581 |
574 array_add(dependencyArray, elem, status); | 582 dependencyArray->add(elem); |
575 | 583 |
576 if (U_FAILURE(*status)) | 584 if (U_FAILURE(*status)) |
577 { | 585 { |
578 return NULL; | 586 return NULL; |
579 } | 587 } |
580 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); | 588 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); |
581 return result; | 589 return result; |
582 } | 590 } |
583 static struct SResource * | 591 static struct SResource * |
584 parseString(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng* comment, UErrorCode *status) | 592 parseString(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng* comment, UErrorCode *status) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 } | 652 } |
645 | 653 |
646 return result; | 654 return result; |
647 } | 655 } |
648 | 656 |
649 #if !UCONFIG_NO_COLLATION | 657 #if !UCONFIG_NO_COLLATION |
650 | 658 |
651 namespace { | 659 namespace { |
652 | 660 |
653 static struct SResource* resLookup(struct SResource* res, const char* key){ | 661 static struct SResource* resLookup(struct SResource* res, const char* key){ |
654 struct SResource *current = NULL; | 662 if (res == res_none() || !res->isTable()) { |
655 struct SResTable *list; | |
656 if (res == res_none()) { | |
657 return NULL; | 663 return NULL; |
658 } | 664 } |
659 | 665 |
660 list = &(res->u.fTable); | 666 TableResource *list = static_cast<TableResource *>(res); |
661 | 667 SResource *current = list->fFirst; |
662 current = list->fFirst; | |
663 while (current != NULL) { | 668 while (current != NULL) { |
664 if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) { | 669 if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) { |
665 return current; | 670 return current; |
666 } | 671 } |
667 current = current->fNext; | 672 current = current->fNext; |
668 } | 673 } |
669 return NULL; | 674 return NULL; |
670 } | 675 } |
671 | 676 |
672 class GenrbImporter : public icu::CollationRuleParser::Importer { | 677 class GenrbImporter : public icu::CollationRuleParser::Importer { |
(...skipping 10 matching lines...) Expand all Loading... |
683 const char *outputDir; | 688 const char *outputDir; |
684 }; | 689 }; |
685 | 690 |
686 GenrbImporter::~GenrbImporter() {} | 691 GenrbImporter::~GenrbImporter() {} |
687 | 692 |
688 void | 693 void |
689 GenrbImporter::getRules( | 694 GenrbImporter::getRules( |
690 const char *localeID, const char *collationType, | 695 const char *localeID, const char *collationType, |
691 UnicodeString &rules, | 696 UnicodeString &rules, |
692 const char *& /*errorReason*/, UErrorCode &errorCode) { | 697 const char *& /*errorReason*/, UErrorCode &errorCode) { |
693 struct SRBRoot *data = NULL; | 698 CharString filename(localeID, errorCode); |
694 UCHARBUF *ucbuf = NULL; | 699 for(int32_t i = 0; i < filename.length(); i++){ |
695 int localeLength = strlen(localeID); | |
696 char* filename = (char*)uprv_malloc(localeLength+5); | |
697 char *inputDirBuf = NULL; | |
698 char *openFileName = NULL; | |
699 const char* cp = ""; | |
700 int32_t i = 0; | |
701 int32_t dirlen = 0; | |
702 int32_t filelen = 0; | |
703 struct SResource* root; | |
704 struct SResource* collations; | |
705 struct SResource* collation; | |
706 struct SResource* sequence; | |
707 | |
708 memcpy(filename, localeID, localeLength); | |
709 for(i = 0; i < localeLength; i++){ | |
710 if(filename[i] == '-'){ | 700 if(filename[i] == '-'){ |
711 filename[i] = '_'; | 701 filename.data()[i] = '_'; |
712 } | 702 } |
713 } | 703 } |
714 filename[localeLength] = '.'; | 704 filename.append(".txt", errorCode); |
715 filename[localeLength+1] = 't'; | |
716 filename[localeLength+2] = 'x'; | |
717 filename[localeLength+3] = 't'; | |
718 filename[localeLength+4] = 0; | |
719 | |
720 | |
721 if (U_FAILURE(errorCode)) { | 705 if (U_FAILURE(errorCode)) { |
722 return; | 706 return; |
723 } | 707 } |
724 if(filename==NULL){ | 708 CharString inputDirBuf; |
725 errorCode=U_ILLEGAL_ARGUMENT_ERROR; | 709 CharString openFileName; |
726 return; | |
727 }else{ | |
728 filelen = (int32_t)uprv_strlen(filename); | |
729 } | |
730 if(inputDir == NULL) { | 710 if(inputDir == NULL) { |
731 const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR); | 711 const char *filenameBegin = uprv_strrchr(filename.data(), U_FILE_SEP_CHA
R); |
732 openFileName = (char *) uprv_malloc(dirlen + filelen + 2); | |
733 openFileName[0] = '\0'; | |
734 if (filenameBegin != NULL) { | 712 if (filenameBegin != NULL) { |
735 /* | 713 /* |
736 * When a filename ../../../data/root.txt is specified, | 714 * When a filename ../../../data/root.txt is specified, |
737 * we presume that the input directory is ../../../data | 715 * we presume that the input directory is ../../../data |
738 * This is very important when the resource file includes | 716 * This is very important when the resource file includes |
739 * another file, like UCARules.txt or thaidict.brk. | 717 * another file, like UCARules.txt or thaidict.brk. |
740 */ | 718 */ |
741 int32_t filenameSize = (int32_t)(filenameBegin - filename + 1); | 719 StringPiece dir = filename.toStringPiece(); |
742 inputDirBuf = (char *)uprv_malloc(filenameSize); | 720 const char *filenameLimit = filename.data() + filename.length(); |
743 | 721 dir.remove_suffix((int32_t)(filenameLimit - filenameBegin)); |
744 /* test for NULL */ | 722 inputDirBuf.append(dir, errorCode); |
745 if(inputDirBuf == NULL) { | 723 inputDir = inputDirBuf.data(); |
746 errorCode = U_MEMORY_ALLOCATION_ERROR; | |
747 goto finish; | |
748 } | |
749 | |
750 uprv_strncpy(inputDirBuf, filename, filenameSize); | |
751 inputDirBuf[filenameSize - 1] = 0; | |
752 inputDir = inputDirBuf; | |
753 dirlen = (int32_t)uprv_strlen(inputDir); | |
754 } | 724 } |
755 }else{ | 725 }else{ |
756 dirlen = (int32_t)uprv_strlen(inputDir); | 726 int32_t dirlen = (int32_t)uprv_strlen(inputDir); |
757 | 727 |
758 if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) { | 728 if((filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')) { |
759 openFileName = (char *) uprv_malloc(dirlen + filelen + 2); | |
760 | |
761 /* test for NULL */ | |
762 if(openFileName == NULL) { | |
763 errorCode = U_MEMORY_ALLOCATION_ERROR; | |
764 goto finish; | |
765 } | |
766 | |
767 openFileName[0] = '\0'; | |
768 /* | 729 /* |
769 * append the input dir to openFileName if the first char in | 730 * append the input dir to openFileName if the first char in |
770 * filename is not file seperation char and the last char input dire
ctory is not '.'. | 731 * filename is not file separator char and the last char input direc
tory is not '.'. |
771 * This is to support : | 732 * This is to support : |
772 * genrb -s. /home/icu/data | 733 * genrb -s. /home/icu/data |
773 * genrb -s. icu/data | 734 * genrb -s. icu/data |
774 * The user cannot mix notations like | 735 * The user cannot mix notations like |
775 * genrb -s. /icu/data --- the absolute path specified. -s redundant | 736 * genrb -s. /icu/data --- the absolute path specified. -s redundant |
776 * user should use | 737 * user should use |
777 * genrb -s. icu/data --- start from CWD and look in icu/data dir | 738 * genrb -s. icu/data --- start from CWD and look in icu/data dir |
778 */ | 739 */ |
779 if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){ | 740 openFileName.append(inputDir, dirlen, errorCode); |
780 uprv_strcpy(openFileName, inputDir); | 741 if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) { |
781 openFileName[dirlen] = U_FILE_SEP_CHAR; | 742 openFileName.append(U_FILE_SEP_CHAR, errorCode); |
782 } | 743 } |
783 openFileName[dirlen + 1] = '\0'; | |
784 } else { | |
785 openFileName = (char *) uprv_malloc(dirlen + filelen + 1); | |
786 | |
787 /* test for NULL */ | |
788 if(openFileName == NULL) { | |
789 errorCode = U_MEMORY_ALLOCATION_ERROR; | |
790 goto finish; | |
791 } | |
792 | |
793 uprv_strcpy(openFileName, inputDir); | |
794 | |
795 } | 744 } |
796 } | 745 } |
797 uprv_strcat(openFileName, filename); | 746 openFileName.append(filename, errorCode); |
798 /* printf("%s\n", openFileName); */ | 747 if(U_FAILURE(errorCode)) { |
799 errorCode = U_ZERO_ERROR; | 748 return; |
800 ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, &errorCode); | 749 } |
801 | 750 // printf("GenrbImporter::getRules(%s, %s) reads %s\n", localeID, collationT
ype, openFileName.data()); |
| 751 const char* cp = ""; |
| 752 LocalUCHARBUFPointer ucbuf( |
| 753 ucbuf_open(openFileName.data(), &cp, getShowWarning(), TRUE, &errorC
ode)); |
802 if(errorCode == U_FILE_ACCESS_ERROR) { | 754 if(errorCode == U_FILE_ACCESS_ERROR) { |
803 | 755 fprintf(stderr, "couldn't open file %s\n", openFileName.data()); |
804 fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filena
me : openFileName); | 756 return; |
805 goto finish; | |
806 } | 757 } |
807 if (ucbuf == NULL || U_FAILURE(errorCode)) { | 758 if (ucbuf.isNull() || U_FAILURE(errorCode)) { |
808 fprintf(stderr, "An error occured processing file %s. Error: %s\n", open
FileName == NULL ? filename : openFileName,u_errorName(errorCode)); | 759 fprintf(stderr, "An error occured processing file %s. Error: %s\n", open
FileName.data(), u_errorName(errorCode)); |
809 goto finish; | 760 return; |
810 } | 761 } |
811 | 762 |
812 /* Parse the data into an SRBRoot */ | 763 /* Parse the data into an SRBRoot */ |
813 data = parse(ucbuf, inputDir, outputDir, filename, FALSE, FALSE, &errorCode)
; | 764 struct SRBRoot *data = |
| 765 parse(ucbuf.getAlias(), inputDir, outputDir, filename.data(), FALSE,
FALSE, &errorCode); |
814 if (U_FAILURE(errorCode)) { | 766 if (U_FAILURE(errorCode)) { |
815 goto finish; | 767 return; |
816 } | 768 } |
817 | 769 |
818 root = data->fRoot; | 770 struct SResource *root = data->fRoot; |
819 collations = resLookup(root, "collations"); | 771 struct SResource *collations = resLookup(root, "collations"); |
820 if (collations != NULL) { | 772 if (collations != NULL) { |
821 collation = resLookup(collations, collationType); | 773 struct SResource *collation = resLookup(collations, collationType); |
822 if (collation != NULL) { | 774 if (collation != NULL) { |
823 sequence = resLookup(collation, "Sequence"); | 775 struct SResource *sequence = resLookup(collation, "Sequence"); |
824 if (sequence != NULL) { | 776 if (sequence != NULL && sequence->isString()) { |
825 // No string pointer aliasing so that we need not hold onto the resour
ce bundle. | 777 // No string pointer aliasing so that we need not hold onto the resour
ce bundle. |
826 rules.setTo(sequence->u.fString.fChars, sequence->u.fString.fLength); | 778 StringResource *sr = static_cast<StringResource *>(sequence); |
| 779 rules = sr->fString; |
827 } | 780 } |
828 } | 781 } |
829 } | 782 } |
830 | |
831 finish: | |
832 if (inputDirBuf != NULL) { | |
833 uprv_free(inputDirBuf); | |
834 } | |
835 | |
836 if (openFileName != NULL) { | |
837 uprv_free(openFileName); | |
838 } | |
839 | |
840 if(ucbuf) { | |
841 ucbuf_close(ucbuf); | |
842 } | |
843 } | 783 } |
844 | 784 |
845 // Quick-and-dirty escaping function. | 785 // Quick-and-dirty escaping function. |
846 // Assumes that we are on an ASCII-based platform. | 786 // Assumes that we are on an ASCII-based platform. |
847 static void | 787 static void |
848 escape(const UChar *s, char *buffer) { | 788 escape(const UChar *s, char *buffer) { |
849 int32_t length = u_strlen(s); | 789 int32_t length = u_strlen(s); |
850 int32_t i = 0; | 790 int32_t i = 0; |
851 for (;;) { | 791 for (;;) { |
852 UChar32 c; | 792 UChar32 c; |
853 U16_NEXT(s, i, length, c); | 793 U16_NEXT(s, i, length, c); |
854 if (c == 0) { | 794 if (c == 0) { |
855 *buffer = 0; | 795 *buffer = 0; |
856 return; | 796 return; |
857 } else if (0x20 <= c && c <= 0x7e) { | 797 } else if (0x20 <= c && c <= 0x7e) { |
858 // printable ASCII | 798 // printable ASCII |
859 *buffer++ = (char)c; // assumes ASCII-based platform | 799 *buffer++ = (char)c; // assumes ASCII-based platform |
860 } else { | 800 } else { |
861 buffer += sprintf(buffer, "\\u%04X", (int)c); | 801 buffer += sprintf(buffer, "\\u%04X", (int)c); |
862 } | 802 } |
863 } | 803 } |
864 } | 804 } |
865 | 805 |
866 } // namespace | 806 } // namespace |
867 | 807 |
868 #endif // !UCONFIG_NO_COLLATION | 808 #endif // !UCONFIG_NO_COLLATION |
869 | 809 |
870 static struct SResource * | 810 static TableResource * |
871 addCollation(ParseState* state, struct SResource *result, const char *collation
Type, | 811 addCollation(ParseState* state, TableResource *result, const char *collationTyp
e, |
872 uint32_t startline, UErrorCode *status) | 812 uint32_t startline, UErrorCode *status) |
873 { | 813 { |
874 // TODO: Use LocalPointer for result, or make caller close it when there is
a failure. | 814 // TODO: Use LocalPointer for result, or make caller close it when there is
a failure. |
875 struct SResource *member = NULL; | 815 struct SResource *member = NULL; |
876 struct UString *tokenValue; | 816 struct UString *tokenValue; |
877 struct UString comment; | 817 struct UString comment; |
878 enum ETokenType token; | 818 enum ETokenType token; |
879 char subtag[1024]; | 819 char subtag[1024]; |
880 UnicodeString rules; | 820 UnicodeString rules; |
881 UBool haveRules = FALSE; | 821 UBool haveRules = FALSE; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 | 864 |
925 if (U_FAILURE(*status)) | 865 if (U_FAILURE(*status)) |
926 { | 866 { |
927 res_close(result); | 867 res_close(result); |
928 return NULL; | 868 return NULL; |
929 } | 869 } |
930 if (result == NULL) | 870 if (result == NULL) |
931 { | 871 { |
932 // Ignore the parsed resources, continue parsing. | 872 // Ignore the parsed resources, continue parsing. |
933 } | 873 } |
934 else if (uprv_strcmp(subtag, "Version") == 0) | 874 else if (uprv_strcmp(subtag, "Version") == 0 && member->isString()) |
935 { | 875 { |
| 876 StringResource *sr = static_cast<StringResource *>(member); |
936 char ver[40]; | 877 char ver[40]; |
937 int32_t length = member->u.fString.fLength; | 878 int32_t length = sr->length(); |
938 | 879 |
939 if (length >= (int32_t) sizeof(ver)) | 880 if (length >= UPRV_LENGTHOF(ver)) |
940 { | 881 { |
941 length = (int32_t) sizeof(ver) - 1; | 882 length = UPRV_LENGTHOF(ver) - 1; |
942 } | 883 } |
943 | 884 |
944 u_UCharsToChars(member->u.fString.fChars, ver, length + 1); /* +1 fo
r copying NULL */ | 885 sr->fString.extract(0, length, ver, UPRV_LENGTHOF(ver), US_INV); |
945 u_versionFromString(version, ver); | 886 u_versionFromString(version, ver); |
946 | 887 |
947 table_add(result, member, line, status); | 888 result->add(member, line, *status); |
948 member = NULL; | 889 member = NULL; |
949 } | 890 } |
950 else if(uprv_strcmp(subtag, "%%CollationBin")==0) | 891 else if(uprv_strcmp(subtag, "%%CollationBin")==0) |
951 { | 892 { |
952 /* discard duplicate %%CollationBin if any*/ | 893 /* discard duplicate %%CollationBin if any*/ |
953 } | 894 } |
954 else if (uprv_strcmp(subtag, "Sequence") == 0) | 895 else if (uprv_strcmp(subtag, "Sequence") == 0 && member->isString()) |
955 { | 896 { |
956 rules.setTo(member->u.fString.fChars, member->u.fString.fLength); | 897 StringResource *sr = static_cast<StringResource *>(member); |
| 898 rules = sr->fString; |
957 haveRules = TRUE; | 899 haveRules = TRUE; |
958 // Defer building the collator until we have seen | 900 // Defer building the collator until we have seen |
959 // all sub-elements of the collation table, including the Version. | 901 // all sub-elements of the collation table, including the Version. |
960 /* in order to achieve smaller data files, we can direct genrb */ | 902 /* in order to achieve smaller data files, we can direct genrb */ |
961 /* to omit collation rules */ | 903 /* to omit collation rules */ |
962 if(!state->omitCollationRules) { | 904 if(!state->omitCollationRules) { |
963 table_add(result, member, line, status); | 905 result->add(member, line, *status); |
964 member = NULL; | 906 member = NULL; |
965 } | 907 } |
966 } | 908 } |
967 else // Just copy non-special items. | 909 else // Just copy non-special items. |
968 { | 910 { |
969 table_add(result, member, line, status); | 911 result->add(member, line, *status); |
970 member = NULL; | 912 member = NULL; |
971 } | 913 } |
972 res_close(member); // TODO: use LocalPointer | 914 res_close(member); // TODO: use LocalPointer |
973 if (U_FAILURE(*status)) | 915 if (U_FAILURE(*status)) |
974 { | 916 { |
975 res_close(result); | 917 res_close(result); |
976 return NULL; | 918 return NULL; |
977 } | 919 } |
978 } | 920 } |
979 | 921 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 error(line, "CollationBuilder failed at %s~%s/Sequence rule offset %ld:
%s %s", | 962 error(line, "CollationBuilder failed at %s~%s/Sequence rule offset %ld:
%s %s", |
1021 state->filename, collationType, | 963 state->filename, collationType, |
1022 (long)parseError.offset, u_errorName(intStatus), reason); | 964 (long)parseError.offset, u_errorName(intStatus), reason); |
1023 if(parseError.preContext[0] != 0 || parseError.postContext[0] != 0) { | 965 if(parseError.preContext[0] != 0 || parseError.postContext[0] != 0) { |
1024 // Print pre- and post-context. | 966 // Print pre- and post-context. |
1025 char preBuffer[100], postBuffer[100]; | 967 char preBuffer[100], postBuffer[100]; |
1026 escape(parseError.preContext, preBuffer); | 968 escape(parseError.preContext, preBuffer); |
1027 escape(parseError.postContext, postBuffer); | 969 escape(parseError.postContext, postBuffer); |
1028 error(line, " error context: \"...%s\" ! \"%s...\"", preBuffer, pos
tBuffer); | 970 error(line, " error context: \"...%s\" ! \"%s...\"", preBuffer, pos
tBuffer); |
1029 } | 971 } |
1030 if(isStrict()) { | 972 if(isStrict() || t.isNull()) { |
1031 *status = intStatus; | 973 *status = intStatus; |
1032 res_close(result); | 974 res_close(result); |
1033 return NULL; | 975 return NULL; |
1034 } | 976 } |
1035 } | 977 } |
1036 icu::LocalMemory<uint8_t> buffer; | 978 icu::LocalMemory<uint8_t> buffer; |
1037 int32_t capacity = 100000; | 979 int32_t capacity = 100000; |
1038 uint8_t *dest = buffer.allocateInsteadAndCopy(capacity); | 980 uint8_t *dest = buffer.allocateInsteadAndCopy(capacity); |
1039 if(dest == NULL) { | 981 if(dest == NULL) { |
1040 fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\
n", | 982 fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\
n", |
(...skipping 21 matching lines...) Expand all Loading... |
1062 } | 1004 } |
1063 if(U_FAILURE(intStatus)) { | 1005 if(U_FAILURE(intStatus)) { |
1064 fprintf(stderr, "CollationDataWriter::writeTailoring() failed: %s\n", | 1006 fprintf(stderr, "CollationDataWriter::writeTailoring() failed: %s\n", |
1065 u_errorName(intStatus)); | 1007 u_errorName(intStatus)); |
1066 res_close(result); | 1008 res_close(result); |
1067 return NULL; | 1009 return NULL; |
1068 } | 1010 } |
1069 if(isVerbose()) { | 1011 if(isVerbose()) { |
1070 printf("%s~%s collation tailoring part sizes:\n", state->filename, colla
tionType); | 1012 printf("%s~%s collation tailoring part sizes:\n", state->filename, colla
tionType); |
1071 icu::CollationInfo::printSizes(totalSize, indexes); | 1013 icu::CollationInfo::printSizes(totalSize, indexes); |
| 1014 if(t->settings->hasReordering()) { |
| 1015 printf("%s~%s collation reordering ranges:\n", state->filename, coll
ationType); |
| 1016 icu::CollationInfo::printReorderRanges( |
| 1017 *t->data, t->settings->reorderCodes, t->settings->reorderCod
esLength); |
| 1018 } |
1072 } | 1019 } |
1073 struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", t
otalSize, dest, NULL, NULL, status); | 1020 struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", t
otalSize, dest, NULL, NULL, status); |
1074 table_add(result, collationBin, line, status); | 1021 result->add(collationBin, line, *status); |
1075 if (U_FAILURE(*status)) { | 1022 if (U_FAILURE(*status)) { |
1076 res_close(result); | 1023 res_close(result); |
1077 return NULL; | 1024 return NULL; |
1078 } | 1025 } |
1079 #endif | 1026 #endif |
1080 return result; | 1027 return result; |
1081 } | 1028 } |
1082 | 1029 |
1083 static UBool | 1030 static UBool |
1084 keepCollationType(const char * /*type*/) { | 1031 keepCollationType(const char * /*type*/) { |
1085 return TRUE; | 1032 return TRUE; |
1086 } | 1033 } |
1087 | 1034 |
1088 static struct SResource * | 1035 static struct SResource * |
1089 parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
ewCollation, UErrorCode *status) | 1036 parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
ewCollation, UErrorCode *status) |
1090 { | 1037 { |
1091 struct SResource *result = NULL; | 1038 TableResource *result = NULL; |
1092 struct SResource *member = NULL; | 1039 struct SResource *member = NULL; |
1093 struct SResource *collationRes = NULL; | |
1094 struct UString *tokenValue; | 1040 struct UString *tokenValue; |
1095 struct UString comment; | 1041 struct UString comment; |
1096 enum ETokenType token; | 1042 enum ETokenType token; |
1097 char subtag[1024], typeKeyword[1024]; | 1043 char subtag[1024], typeKeyword[1024]; |
1098 uint32_t line; | 1044 uint32_t line; |
1099 | 1045 |
1100 result = table_open(state->bundle, tag, NULL, status); | 1046 result = table_open(state->bundle, tag, NULL, status); |
1101 | 1047 |
1102 if (result == NULL || U_FAILURE(*status)) | 1048 if (result == NULL || U_FAILURE(*status)) |
1103 { | 1049 { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 if (uprv_strcmp(subtag, "default") == 0) | 1093 if (uprv_strcmp(subtag, "default") == 0) |
1148 { | 1094 { |
1149 member = parseResource(state, subtag, NULL, status); | 1095 member = parseResource(state, subtag, NULL, status); |
1150 | 1096 |
1151 if (U_FAILURE(*status)) | 1097 if (U_FAILURE(*status)) |
1152 { | 1098 { |
1153 res_close(result); | 1099 res_close(result); |
1154 return NULL; | 1100 return NULL; |
1155 } | 1101 } |
1156 | 1102 |
1157 table_add(result, member, line, status); | 1103 result->add(member, line, *status); |
1158 } | 1104 } |
1159 else | 1105 else |
1160 { | 1106 { |
1161 token = peekToken(state, 0, &tokenValue, &line, &comment, status
); | 1107 token = peekToken(state, 0, &tokenValue, &line, &comment, status
); |
1162 /* this probably needs to be refactored or recursively use the p
arser */ | 1108 /* this probably needs to be refactored or recursively use the p
arser */ |
1163 /* first we assume that our collation table won't have the expli
cit type */ | 1109 /* first we assume that our collation table won't have the expli
cit type */ |
1164 /* then, we cannot handle aliases */ | 1110 /* then, we cannot handle aliases */ |
1165 if(token == TOK_OPEN_BRACE) { | 1111 if(token == TOK_OPEN_BRACE) { |
1166 token = getToken(state, &tokenValue, &comment, &line, status
); | 1112 token = getToken(state, &tokenValue, &comment, &line, status
); |
| 1113 TableResource *collationRes; |
1167 if (keepCollationType(subtag)) { | 1114 if (keepCollationType(subtag)) { |
1168 collationRes = table_open(state->bundle, subtag, NULL, s
tatus); | 1115 collationRes = table_open(state->bundle, subtag, NULL, s
tatus); |
1169 } else { | 1116 } else { |
1170 collationRes = NULL; | 1117 collationRes = NULL; |
1171 } | 1118 } |
1172 // need to parse the collation data regardless | 1119 // need to parse the collation data regardless |
1173 collationRes = addCollation(state, collationRes, subtag, sta
rtline, status); | 1120 collationRes = addCollation(state, collationRes, subtag, sta
rtline, status); |
1174 if (collationRes != NULL) { | 1121 if (collationRes != NULL) { |
1175 table_add(result, collationRes, startline, status); | 1122 result->add(collationRes, startline, *status); |
1176 } | 1123 } |
1177 } else if(token == TOK_COLON) { /* right now, we'll just try to
see if we have aliases */ | 1124 } else if(token == TOK_COLON) { /* right now, we'll just try to
see if we have aliases */ |
1178 /* we could have a table too */ | 1125 /* we could have a table too */ |
1179 token = peekToken(state, 1, &tokenValue, &line, &comment, st
atus); | 1126 token = peekToken(state, 1, &tokenValue, &line, &comment, st
atus); |
1180 u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(to
kenValue->fChars) + 1); | 1127 u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(to
kenValue->fChars) + 1); |
1181 if(uprv_strcmp(typeKeyword, "alias") == 0) { | 1128 if(uprv_strcmp(typeKeyword, "alias") == 0) { |
1182 member = parseResource(state, subtag, NULL, status); | 1129 member = parseResource(state, subtag, NULL, status); |
1183 if (U_FAILURE(*status)) | 1130 if (U_FAILURE(*status)) |
1184 { | 1131 { |
1185 res_close(result); | 1132 res_close(result); |
1186 return NULL; | 1133 return NULL; |
1187 } | 1134 } |
1188 | 1135 |
1189 table_add(result, member, line, status); | 1136 result->add(member, line, *status); |
1190 } else { | 1137 } else { |
1191 res_close(result); | 1138 res_close(result); |
1192 *status = U_INVALID_FORMAT_ERROR; | 1139 *status = U_INVALID_FORMAT_ERROR; |
1193 return NULL; | 1140 return NULL; |
1194 } | 1141 } |
1195 } else { | 1142 } else { |
1196 res_close(result); | 1143 res_close(result); |
1197 *status = U_INVALID_FORMAT_ERROR; | 1144 *status = U_INVALID_FORMAT_ERROR; |
1198 return NULL; | 1145 return NULL; |
1199 } | 1146 } |
1200 } | 1147 } |
1201 | 1148 |
1202 /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValu
e->fLength, status);*/ | 1149 /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValu
e->fLength, status);*/ |
1203 | 1150 |
1204 /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/ | 1151 /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/ |
1205 | 1152 |
1206 if (U_FAILURE(*status)) | 1153 if (U_FAILURE(*status)) |
1207 { | 1154 { |
1208 res_close(result); | 1155 res_close(result); |
1209 return NULL; | 1156 return NULL; |
1210 } | 1157 } |
1211 } | 1158 } |
1212 } | 1159 } |
1213 } | 1160 } |
1214 | 1161 |
1215 /* Necessary, because CollationElements requires the bundle->fRoot member to be
present which, | 1162 /* Necessary, because CollationElements requires the bundle->fRoot member to be
present which, |
1216 if this weren't special-cased, wouldn't be set until the entire file had been
processed. */ | 1163 if this weren't special-cased, wouldn't be set until the entire file had been
processed. */ |
1217 static struct SResource * | 1164 static struct SResource * |
1218 realParseTable(ParseState* state, struct SResource *table, char *tag, uint32_t s
tartline, UErrorCode *status) | 1165 realParseTable(ParseState* state, TableResource *table, char *tag, uint32_t star
tline, UErrorCode *status) |
1219 { | 1166 { |
1220 struct SResource *member = NULL; | 1167 struct SResource *member = NULL; |
1221 struct UString *tokenValue=NULL; | 1168 struct UString *tokenValue=NULL; |
1222 struct UString comment; | 1169 struct UString comment; |
1223 enum ETokenType token; | 1170 enum ETokenType token; |
1224 char subtag[1024]; | 1171 char subtag[1024]; |
1225 uint32_t line; | 1172 uint32_t line; |
1226 UBool readToken = FALSE; | 1173 UBool readToken = FALSE; |
1227 | 1174 |
1228 /* '{' . (name resource)* '}' */ | 1175 /* '{' . (name resource)* '}' */ |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 } | 1221 } |
1275 | 1222 |
1276 member = parseResource(state, subtag, &comment, status); | 1223 member = parseResource(state, subtag, &comment, status); |
1277 | 1224 |
1278 if (member == NULL || U_FAILURE(*status)) | 1225 if (member == NULL || U_FAILURE(*status)) |
1279 { | 1226 { |
1280 error(line, "parse error. Stopped parsing resource with %s", u_error
Name(*status)); | 1227 error(line, "parse error. Stopped parsing resource with %s", u_error
Name(*status)); |
1281 return NULL; | 1228 return NULL; |
1282 } | 1229 } |
1283 | 1230 |
1284 table_add(table, member, line, status); | 1231 table->add(member, line, *status); |
1285 | 1232 |
1286 if (U_FAILURE(*status)) | 1233 if (U_FAILURE(*status)) |
1287 { | 1234 { |
1288 error(line, "parse error. Stopped parsing table with %s", u_errorNam
e(*status)); | 1235 error(line, "parse error. Stopped parsing table with %s", u_errorNam
e(*status)); |
1289 return NULL; | 1236 return NULL; |
1290 } | 1237 } |
1291 readToken = TRUE; | 1238 readToken = TRUE; |
1292 ustr_deinit(&comment); | 1239 ustr_deinit(&comment); |
1293 } | 1240 } |
1294 | 1241 |
1295 /* not reached */ | 1242 /* not reached */ |
1296 /* A compiler warning will appear if all paths don't contain a return statem
ent. */ | 1243 /* A compiler warning will appear if all paths don't contain a return statem
ent. */ |
1297 /* *status = U_INTERNAL_PROGRAM_ERROR; | 1244 /* *status = U_INTERNAL_PROGRAM_ERROR; |
1298 return NULL;*/ | 1245 return NULL;*/ |
1299 } | 1246 } |
1300 | 1247 |
1301 static struct SResource * | 1248 static struct SResource * |
1302 parseTable(ParseState* state, char *tag, uint32_t startline, const struct UStrin
g *comment, UErrorCode *status) | 1249 parseTable(ParseState* state, char *tag, uint32_t startline, const struct UStrin
g *comment, UErrorCode *status) |
1303 { | 1250 { |
1304 struct SResource *result; | |
1305 | |
1306 if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0) | 1251 if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0) |
1307 { | 1252 { |
1308 return parseCollationElements(state, tag, startline, FALSE, status); | 1253 return parseCollationElements(state, tag, startline, FALSE, status); |
1309 } | 1254 } |
1310 if (tag != NULL && uprv_strcmp(tag, "collations") == 0) | 1255 if (tag != NULL && uprv_strcmp(tag, "collations") == 0) |
1311 { | 1256 { |
1312 return parseCollationElements(state, tag, startline, TRUE, status); | 1257 return parseCollationElements(state, tag, startline, TRUE, status); |
1313 } | 1258 } |
1314 if(isVerbose()){ | 1259 if(isVerbose()){ |
1315 printf(" table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)
startline); | 1260 printf(" table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)
startline); |
1316 } | 1261 } |
1317 | 1262 |
1318 result = table_open(state->bundle, tag, comment, status); | 1263 TableResource *result = table_open(state->bundle, tag, comment, status); |
1319 | 1264 |
1320 if (result == NULL || U_FAILURE(*status)) | 1265 if (result == NULL || U_FAILURE(*status)) |
1321 { | 1266 { |
1322 return NULL; | 1267 return NULL; |
1323 } | 1268 } |
1324 return realParseTable(state, result, tag, startline, status); | 1269 return realParseTable(state, result, tag, startline, status); |
1325 } | 1270 } |
1326 | 1271 |
1327 static struct SResource * | 1272 static struct SResource * |
1328 parseArray(ParseState* state, char *tag, uint32_t startline, const struct UStrin
g *comment, UErrorCode *status) | 1273 parseArray(ParseState* state, char *tag, uint32_t startline, const struct UStrin
g *comment, UErrorCode *status) |
1329 { | 1274 { |
1330 struct SResource *result = NULL; | |
1331 struct SResource *member = NULL; | 1275 struct SResource *member = NULL; |
1332 struct UString *tokenValue; | 1276 struct UString *tokenValue; |
1333 struct UString memberComments; | 1277 struct UString memberComments; |
1334 enum ETokenType token; | 1278 enum ETokenType token; |
1335 UBool readToken = FALSE; | 1279 UBool readToken = FALSE; |
1336 | 1280 |
1337 result = array_open(state->bundle, tag, comment, status); | 1281 ArrayResource *result = array_open(state->bundle, tag, comment, status); |
1338 | 1282 |
1339 if (result == NULL || U_FAILURE(*status)) | 1283 if (result == NULL || U_FAILURE(*status)) |
1340 { | 1284 { |
1341 return NULL; | 1285 return NULL; |
1342 } | 1286 } |
1343 if(isVerbose()){ | 1287 if(isVerbose()){ |
1344 printf(" array %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)
startline); | 1288 printf(" array %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)
startline); |
1345 } | 1289 } |
1346 | 1290 |
1347 ustr_init(&memberComments); | 1291 ustr_init(&memberComments); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 { | 1327 { |
1384 member = parseResource(state, NULL, &memberComments, status); | 1328 member = parseResource(state, NULL, &memberComments, status); |
1385 } | 1329 } |
1386 | 1330 |
1387 if (member == NULL || U_FAILURE(*status)) | 1331 if (member == NULL || U_FAILURE(*status)) |
1388 { | 1332 { |
1389 res_close(result); | 1333 res_close(result); |
1390 return NULL; | 1334 return NULL; |
1391 } | 1335 } |
1392 | 1336 |
1393 array_add(result, member, status); | 1337 result->add(member); |
1394 | |
1395 if (U_FAILURE(*status)) | |
1396 { | |
1397 res_close(result); | |
1398 return NULL; | |
1399 } | |
1400 | 1338 |
1401 /* eat optional comma if present */ | 1339 /* eat optional comma if present */ |
1402 token = peekToken(state, 0, NULL, NULL, NULL, status); | 1340 token = peekToken(state, 0, NULL, NULL, NULL, status); |
1403 | 1341 |
1404 if (token == TOK_COMMA) | 1342 if (token == TOK_COMMA) |
1405 { | 1343 { |
1406 getToken(state, NULL, NULL, NULL, status); | 1344 getToken(state, NULL, NULL, NULL, status); |
1407 } | 1345 } |
1408 | 1346 |
1409 if (U_FAILURE(*status)) | 1347 if (U_FAILURE(*status)) |
1410 { | 1348 { |
1411 res_close(result); | 1349 res_close(result); |
1412 return NULL; | 1350 return NULL; |
1413 } | 1351 } |
1414 readToken = TRUE; | 1352 readToken = TRUE; |
1415 } | 1353 } |
1416 | 1354 |
1417 ustr_deinit(&memberComments); | 1355 ustr_deinit(&memberComments); |
1418 return result; | 1356 return result; |
1419 } | 1357 } |
1420 | 1358 |
1421 static struct SResource * | 1359 static struct SResource * |
1422 parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct US
tring *comment, UErrorCode *status) | 1360 parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct US
tring *comment, UErrorCode *status) |
1423 { | 1361 { |
1424 struct SResource *result = NULL; | |
1425 enum ETokenType token; | 1362 enum ETokenType token; |
1426 char *string; | 1363 char *string; |
1427 int32_t value; | 1364 int32_t value; |
1428 UBool readToken = FALSE; | 1365 UBool readToken = FALSE; |
1429 char *stopstring; | 1366 char *stopstring; |
1430 uint32_t len; | 1367 uint32_t len; |
1431 struct UString memberComments; | 1368 struct UString memberComments; |
1432 | 1369 |
1433 result = intvector_open(state->bundle, tag, comment, status); | 1370 IntVectorResource *result = intvector_open(state->bundle, tag, comment, stat
us); |
1434 | 1371 |
1435 if (result == NULL || U_FAILURE(*status)) | 1372 if (result == NULL || U_FAILURE(*status)) |
1436 { | 1373 { |
1437 return NULL; | 1374 return NULL; |
1438 } | 1375 } |
1439 | 1376 |
1440 if(isVerbose()){ | 1377 if(isVerbose()){ |
1441 printf(" vector %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); | 1378 printf(" vector %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); |
1442 } | 1379 } |
1443 ustr_init(&memberComments); | 1380 ustr_init(&memberComments); |
(...skipping 23 matching lines...) Expand all Loading... |
1467 res_close(result); | 1404 res_close(result); |
1468 return NULL; | 1405 return NULL; |
1469 } | 1406 } |
1470 | 1407 |
1471 /* For handling illegal char in the Intvector */ | 1408 /* For handling illegal char in the Intvector */ |
1472 value = uprv_strtoul(string, &stopstring, 0);/* make intvector support d
ecimal,hexdigit,octal digit ranging from -2^31-2^32-1*/ | 1409 value = uprv_strtoul(string, &stopstring, 0);/* make intvector support d
ecimal,hexdigit,octal digit ranging from -2^31-2^32-1*/ |
1473 len=(uint32_t)(stopstring-string); | 1410 len=(uint32_t)(stopstring-string); |
1474 | 1411 |
1475 if(len==uprv_strlen(string)) | 1412 if(len==uprv_strlen(string)) |
1476 { | 1413 { |
1477 intvector_add(result, value, status); | 1414 result->add(value, *status); |
1478 uprv_free(string); | 1415 uprv_free(string); |
1479 token = peekToken(state, 0, NULL, NULL, NULL, status); | 1416 token = peekToken(state, 0, NULL, NULL, NULL, status); |
1480 } | 1417 } |
1481 else | 1418 else |
1482 { | 1419 { |
1483 uprv_free(string); | 1420 uprv_free(string); |
1484 *status=U_INVALID_CHAR_FOUND; | 1421 *status=U_INVALID_CHAR_FOUND; |
1485 } | 1422 } |
1486 | 1423 |
1487 if (U_FAILURE(*status)) | 1424 if (U_FAILURE(*status)) |
(...skipping 14 matching lines...) Expand all Loading... |
1502 /* not reached */ | 1439 /* not reached */ |
1503 /* A compiler warning will appear if all paths don't contain a return statem
ent. */ | 1440 /* A compiler warning will appear if all paths don't contain a return statem
ent. */ |
1504 /* intvector_close(result, status); | 1441 /* intvector_close(result, status); |
1505 *status = U_INTERNAL_PROGRAM_ERROR; | 1442 *status = U_INTERNAL_PROGRAM_ERROR; |
1506 return NULL;*/ | 1443 return NULL;*/ |
1507 } | 1444 } |
1508 | 1445 |
1509 static struct SResource * | 1446 static struct SResource * |
1510 parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng *comment, UErrorCode *status) | 1447 parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng *comment, UErrorCode *status) |
1511 { | 1448 { |
1512 struct SResource *result = NULL; | 1449 uint32_t line; |
1513 uint8_t *value; | 1450 LocalMemory<char> string(getInvariantString(state, &line, NULL, status)); |
1514 char *string; | 1451 if (string.isNull() || U_FAILURE(*status)) |
1515 char toConv[3] = {'\0', '\0', '\0'}; | |
1516 uint32_t count; | |
1517 uint32_t i; | |
1518 uint32_t line; | |
1519 char *stopstring; | |
1520 uint32_t len; | |
1521 | |
1522 string = getInvariantString(state, &line, NULL, status); | |
1523 | |
1524 if (string == NULL || U_FAILURE(*status)) | |
1525 { | 1452 { |
1526 return NULL; | 1453 return NULL; |
1527 } | 1454 } |
1528 | 1455 |
1529 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); | 1456 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); |
1530 | |
1531 if (U_FAILURE(*status)) | 1457 if (U_FAILURE(*status)) |
1532 { | 1458 { |
1533 uprv_free(string); | |
1534 return NULL; | 1459 return NULL; |
1535 } | 1460 } |
1536 | 1461 |
1537 if(isVerbose()){ | 1462 if(isVerbose()){ |
1538 printf(" binary %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); | 1463 printf(" binary %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); |
1539 } | 1464 } |
1540 | 1465 |
1541 count = (uint32_t)uprv_strlen(string); | 1466 uint32_t count = (uint32_t)uprv_strlen(string.getAlias()); |
1542 if (count > 0){ | 1467 if (count > 0){ |
1543 if((count % 2)==0){ | 1468 if((count % 2)==0){ |
1544 value = static_cast<uint8_t *>(uprv_malloc(sizeof(uint8_t) * count))
; | 1469 LocalMemory<uint8_t> value; |
1545 | 1470 if (value.allocateInsteadAndCopy(count) == NULL) |
1546 if (value == NULL) | |
1547 { | 1471 { |
1548 uprv_free(string); | |
1549 *status = U_MEMORY_ALLOCATION_ERROR; | 1472 *status = U_MEMORY_ALLOCATION_ERROR; |
1550 return NULL; | 1473 return NULL; |
1551 } | 1474 } |
1552 | 1475 |
1553 for (i = 0; i < count; i += 2) | 1476 char toConv[3] = {'\0', '\0', '\0'}; |
| 1477 for (uint32_t i = 0; i < count; i += 2) |
1554 { | 1478 { |
1555 toConv[0] = string[i]; | 1479 toConv[0] = string[i]; |
1556 toConv[1] = string[i + 1]; | 1480 toConv[1] = string[i + 1]; |
1557 | 1481 |
| 1482 char *stopstring; |
1558 value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16); | 1483 value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16); |
1559 len=(uint32_t)(stopstring-toConv); | 1484 uint32_t len=(uint32_t)(stopstring-toConv); |
1560 | 1485 |
1561 if(len!=uprv_strlen(toConv)) | 1486 if(len!=2) |
1562 { | 1487 { |
1563 uprv_free(string); | |
1564 *status=U_INVALID_CHAR_FOUND; | 1488 *status=U_INVALID_CHAR_FOUND; |
1565 return NULL; | 1489 return NULL; |
1566 } | 1490 } |
1567 } | 1491 } |
1568 | 1492 |
1569 result = bin_open(state->bundle, tag, (i >> 1), value,NULL, comment,
status); | 1493 return bin_open(state->bundle, tag, count >> 1, value.getAlias(), NU
LL, comment, status); |
1570 | |
1571 uprv_free(value); | |
1572 } | 1494 } |
1573 else | 1495 else |
1574 { | 1496 { |
1575 *status = U_INVALID_CHAR_FOUND; | 1497 *status = U_INVALID_CHAR_FOUND; |
1576 uprv_free(string); | 1498 error(line, "Encountered invalid binary value (length is odd)"); |
1577 error(line, "Encountered invalid binary string"); | |
1578 return NULL; | 1499 return NULL; |
1579 } | 1500 } |
1580 } | 1501 } |
1581 else | 1502 else |
1582 { | 1503 { |
1583 result = bin_open(state->bundle, tag, 0, NULL, "",comment,status); | 1504 warning(startline, "Encountered empty binary value"); |
1584 warning(startline, "Encountered empty binary tag"); | 1505 return bin_open(state->bundle, tag, 0, NULL, "", comment, status); |
1585 } | 1506 } |
1586 uprv_free(string); | |
1587 | |
1588 return result; | |
1589 } | 1507 } |
1590 | 1508 |
1591 static struct SResource * | 1509 static struct SResource * |
1592 parseInteger(ParseState* state, char *tag, uint32_t startline, const struct UStr
ing *comment, UErrorCode *status) | 1510 parseInteger(ParseState* state, char *tag, uint32_t startline, const struct UStr
ing *comment, UErrorCode *status) |
1593 { | 1511 { |
1594 struct SResource *result = NULL; | 1512 struct SResource *result = NULL; |
1595 int32_t value; | 1513 int32_t value; |
1596 char *string; | 1514 char *string; |
1597 char *stopstring; | 1515 char *stopstring; |
1598 uint32_t len; | 1516 uint32_t len; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 *status=U_INVALID_CHAR_FOUND; | 1552 *status=U_INVALID_CHAR_FOUND; |
1635 } | 1553 } |
1636 uprv_free(string); | 1554 uprv_free(string); |
1637 | 1555 |
1638 return result; | 1556 return result; |
1639 } | 1557 } |
1640 | 1558 |
1641 static struct SResource * | 1559 static struct SResource * |
1642 parseImport(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng* comment, UErrorCode *status) | 1560 parseImport(ParseState* state, char *tag, uint32_t startline, const struct UStri
ng* comment, UErrorCode *status) |
1643 { | 1561 { |
1644 struct SResource *result; | |
1645 FileStream *file; | |
1646 int32_t len; | |
1647 uint8_t *data; | |
1648 char *filename; | |
1649 uint32_t line; | 1562 uint32_t line; |
1650 char *fullname = NULL; | 1563 LocalMemory<char> filename(getInvariantString(state, &line, NULL, status)); |
1651 filename = getInvariantString(state, &line, NULL, status); | |
1652 | |
1653 if (U_FAILURE(*status)) | 1564 if (U_FAILURE(*status)) |
1654 { | 1565 { |
1655 return NULL; | 1566 return NULL; |
1656 } | 1567 } |
1657 | 1568 |
1658 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); | 1569 expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status); |
1659 | 1570 |
1660 if (U_FAILURE(*status)) | 1571 if (U_FAILURE(*status)) |
1661 { | 1572 { |
1662 uprv_free(filename); | |
1663 return NULL; | 1573 return NULL; |
1664 } | 1574 } |
1665 | 1575 |
1666 if(isVerbose()){ | 1576 if(isVerbose()){ |
1667 printf(" import %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); | 1577 printf(" import %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int
)startline); |
1668 } | 1578 } |
1669 | 1579 |
1670 /* Open the input file for reading */ | 1580 /* Open the input file for reading */ |
1671 if (state->inputdir == NULL) | 1581 CharString fullname; |
1672 { | 1582 if (state->inputdir != NULL) { |
1673 #if 1 | 1583 fullname.append(state->inputdir, *status); |
1674 /* | |
1675 * Always save file file name, even if there's | |
1676 * no input directory specified. MIGHT BREAK SOMETHING | |
1677 */ | |
1678 int32_t filenameLength = uprv_strlen(filename); | |
1679 | |
1680 fullname = (char *) uprv_malloc(filenameLength + 1); | |
1681 uprv_strcpy(fullname, filename); | |
1682 #endif | |
1683 | |
1684 file = T_FileStream_open(filename, "rb"); | |
1685 } | 1584 } |
1686 else | 1585 fullname.appendPathPart(filename.getAlias(), *status); |
1687 { | 1586 if (U_FAILURE(*status)) { |
1688 | 1587 return NULL; |
1689 int32_t count = (int32_t)uprv_strlen(filename); | |
1690 | |
1691 if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR) | |
1692 { | |
1693 fullname = (char *) uprv_malloc(state->inputdirLength + count + 2); | |
1694 | |
1695 /* test for NULL */ | |
1696 if(fullname == NULL) | |
1697 { | |
1698 *status = U_MEMORY_ALLOCATION_ERROR; | |
1699 return NULL; | |
1700 } | |
1701 | |
1702 uprv_strcpy(fullname, state->inputdir); | |
1703 | |
1704 fullname[state->inputdirLength] = U_FILE_SEP_CHAR; | |
1705 fullname[state->inputdirLength + 1] = '\0'; | |
1706 | |
1707 uprv_strcat(fullname, filename); | |
1708 } | |
1709 else | |
1710 { | |
1711 fullname = (char *) uprv_malloc(state->inputdirLength + count + 1); | |
1712 | |
1713 /* test for NULL */ | |
1714 if(fullname == NULL) | |
1715 { | |
1716 *status = U_MEMORY_ALLOCATION_ERROR; | |
1717 return NULL; | |
1718 } | |
1719 | |
1720 uprv_strcpy(fullname, state->inputdir); | |
1721 uprv_strcat(fullname, filename); | |
1722 } | |
1723 | |
1724 file = T_FileStream_open(fullname, "rb"); | |
1725 | |
1726 } | 1588 } |
1727 | 1589 |
| 1590 FileStream *file = T_FileStream_open(fullname.data(), "rb"); |
1728 if (file == NULL) | 1591 if (file == NULL) |
1729 { | 1592 { |
1730 error(line, "couldn't open input file %s", filename); | 1593 error(line, "couldn't open input file %s", filename.getAlias()); |
1731 *status = U_FILE_ACCESS_ERROR; | 1594 *status = U_FILE_ACCESS_ERROR; |
1732 return NULL; | 1595 return NULL; |
1733 } | 1596 } |
1734 | 1597 |
1735 len = T_FileStream_size(file); | 1598 int32_t len = T_FileStream_size(file); |
1736 data = (uint8_t*)uprv_malloc(len * sizeof(uint8_t)); | 1599 LocalMemory<uint8_t> data; |
1737 /* test for NULL */ | 1600 if(data.allocateInsteadAndCopy(len) == NULL) |
1738 if(data == NULL) | |
1739 { | 1601 { |
1740 *status = U_MEMORY_ALLOCATION_ERROR; | 1602 *status = U_MEMORY_ALLOCATION_ERROR; |
1741 T_FileStream_close (file); | 1603 T_FileStream_close (file); |
1742 return NULL; | 1604 return NULL; |
1743 } | 1605 } |
1744 | 1606 |
1745 /* int32_t numRead = */ T_FileStream_read (file, data, len); | 1607 /* int32_t numRead = */ T_FileStream_read(file, data.getAlias(), len); |
1746 T_FileStream_close (file); | 1608 T_FileStream_close (file); |
1747 | 1609 |
1748 result = bin_open(state->bundle, tag, len, data, fullname, comment, status); | 1610 return bin_open(state->bundle, tag, len, data.getAlias(), fullname.data(), c
omment, status); |
1749 | |
1750 uprv_free(data); | |
1751 uprv_free(filename); | |
1752 uprv_free(fullname); | |
1753 | |
1754 return result; | |
1755 } | 1611 } |
1756 | 1612 |
1757 static struct SResource * | 1613 static struct SResource * |
1758 parseInclude(ParseState* state, char *tag, uint32_t startline, const struct UStr
ing* comment, UErrorCode *status) | 1614 parseInclude(ParseState* state, char *tag, uint32_t startline, const struct UStr
ing* comment, UErrorCode *status) |
1759 { | 1615 { |
1760 struct SResource *result; | 1616 struct SResource *result; |
1761 int32_t len=0; | 1617 int32_t len=0; |
1762 char *filename; | 1618 char *filename; |
1763 uint32_t line; | 1619 uint32_t line; |
1764 UChar *pTarget = NULL; | 1620 UChar *pTarget = NULL; |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2126 state.inputdirLength = (state.inputdir != NULL) ? (uint32_t)uprv_strlen(stat
e.inputdir) : 0; | 1982 state.inputdirLength = (state.inputdir != NULL) ? (uint32_t)uprv_strlen(stat
e.inputdir) : 0; |
2127 state.outputdir = outputDir; | 1983 state.outputdir = outputDir; |
2128 state.outputdirLength = (state.outputdir != NULL) ? (uint32_t)uprv_strlen(st
ate.outputdir) : 0; | 1984 state.outputdirLength = (state.outputdir != NULL) ? (uint32_t)uprv_strlen(st
ate.outputdir) : 0; |
2129 state.filename = filename; | 1985 state.filename = filename; |
2130 state.makeBinaryCollation = makeBinaryCollation; | 1986 state.makeBinaryCollation = makeBinaryCollation; |
2131 state.omitCollationRules = omitCollationRules; | 1987 state.omitCollationRules = omitCollationRules; |
2132 | 1988 |
2133 ustr_init(&comment); | 1989 ustr_init(&comment); |
2134 expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status); | 1990 expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status); |
2135 | 1991 |
2136 state.bundle = bundle_open(&comment, FALSE, status); | 1992 state.bundle = new SRBRoot(&comment, FALSE, *status); |
2137 | 1993 |
2138 if (state.bundle == NULL || U_FAILURE(*status)) | 1994 if (state.bundle == NULL || U_FAILURE(*status)) |
2139 { | 1995 { |
2140 return NULL; | 1996 return NULL; |
2141 } | 1997 } |
2142 | 1998 |
2143 | 1999 |
2144 bundle_setlocale(state.bundle, tokenValue->fChars, status); | 2000 state.bundle->setLocale(tokenValue->fChars, *status); |
2145 | 2001 |
2146 /* The following code is to make Empty bundle work no matter with :table spe
cifer or not */ | 2002 /* The following code is to make Empty bundle work no matter with :table spe
cifer or not */ |
2147 token = getToken(&state, NULL, NULL, &line, status); | 2003 token = getToken(&state, NULL, NULL, &line, status); |
2148 if(token==TOK_COLON) { | 2004 if(token==TOK_COLON) { |
2149 *status=U_ZERO_ERROR; | 2005 *status=U_ZERO_ERROR; |
2150 bundleType=parseResourceType(&state, status); | 2006 bundleType=parseResourceType(&state, status); |
2151 | 2007 |
2152 if(isTable(bundleType)) | 2008 if(isTable(bundleType)) |
2153 { | 2009 { |
2154 expect(&state, TOK_OPEN_BRACE, NULL, NULL, &line, status); | 2010 expect(&state, TOK_OPEN_BRACE, NULL, NULL, &line, status); |
(...skipping 16 matching lines...) Expand all Loading... |
2171 { | 2027 { |
2172 /* neither colon nor open brace */ | 2028 /* neither colon nor open brace */ |
2173 *status=U_PARSE_ERROR; | 2029 *status=U_PARSE_ERROR; |
2174 bundleType=RESTYPE_UNKNOWN; | 2030 bundleType=RESTYPE_UNKNOWN; |
2175 error(line, "parse error, did not find open-brace '{' or colon ':',
stopped with %s", u_errorName(*status)); | 2031 error(line, "parse error, did not find open-brace '{' or colon ':',
stopped with %s", u_errorName(*status)); |
2176 } | 2032 } |
2177 } | 2033 } |
2178 | 2034 |
2179 if (U_FAILURE(*status)) | 2035 if (U_FAILURE(*status)) |
2180 { | 2036 { |
2181 bundle_close(state.bundle, status); | 2037 delete state.bundle; |
2182 return NULL; | 2038 return NULL; |
2183 } | 2039 } |
2184 | 2040 |
2185 if(bundleType==RESTYPE_TABLE_NO_FALLBACK) { | 2041 if(bundleType==RESTYPE_TABLE_NO_FALLBACK) { |
2186 /* | 2042 /* |
2187 * Parse a top-level table with the table(nofallback) declaration. | 2043 * Parse a top-level table with the table(nofallback) declaration. |
2188 * This is the same as a regular table, but also sets the | 2044 * This is the same as a regular table, but also sets the |
2189 * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] . | 2045 * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] . |
2190 */ | 2046 */ |
2191 state.bundle->noFallback=TRUE; | 2047 state.bundle->fNoFallback=TRUE; |
2192 } | 2048 } |
2193 /* top-level tables need not handle special table names like "collations" */ | 2049 /* top-level tables need not handle special table names like "collations" */ |
2194 realParseTable(&state, state.bundle->fRoot, NULL, line, status); | 2050 assert(!state.bundle->fIsPoolBundle); |
| 2051 assert(state.bundle->fRoot->fType == URES_TABLE); |
| 2052 TableResource *rootTable = static_cast<TableResource *>(state.bundle->fRoot)
; |
| 2053 realParseTable(&state, rootTable, NULL, line, status); |
2195 if(dependencyArray!=NULL){ | 2054 if(dependencyArray!=NULL){ |
2196 table_add(state.bundle->fRoot, dependencyArray, 0, status); | 2055 rootTable->add(dependencyArray, 0, *status); |
2197 dependencyArray = NULL; | 2056 dependencyArray = NULL; |
2198 } | 2057 } |
2199 if (U_FAILURE(*status)) | 2058 if (U_FAILURE(*status)) |
2200 { | 2059 { |
2201 bundle_close(state.bundle, status); | 2060 delete state.bundle; |
2202 res_close(dependencyArray); | 2061 res_close(dependencyArray); |
2203 return NULL; | 2062 return NULL; |
2204 } | 2063 } |
2205 | 2064 |
2206 if (getToken(&state, NULL, NULL, &line, status) != TOK_EOF) | 2065 if (getToken(&state, NULL, NULL, &line, status) != TOK_EOF) |
2207 { | 2066 { |
2208 warning(line, "extraneous text after resource bundle (perhaps unmatched
braces)"); | 2067 warning(line, "extraneous text after resource bundle (perhaps unmatched
braces)"); |
2209 if(isStrict()){ | 2068 if(isStrict()){ |
2210 *status = U_INVALID_FORMAT_ERROR; | 2069 *status = U_INVALID_FORMAT_ERROR; |
2211 return NULL; | 2070 return NULL; |
2212 } | 2071 } |
2213 } | 2072 } |
2214 | 2073 |
2215 cleanupLookahead(&state); | 2074 cleanupLookahead(&state); |
2216 ustr_deinit(&comment); | 2075 ustr_deinit(&comment); |
2217 return state.bundle; | 2076 return state.bundle; |
2218 } | 2077 } |
OLD | NEW |