1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
41b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert*   Copyright (C) 1998-2015, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* File parse.cpp
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date          Name          Description
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/26/99     stephen       Creation.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   02/25/00     weiv          Overhaul to write udata
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   5/10/01      Ram           removed ustdio dependency
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/10/2001  Dominic Ludlam <dom@recoil.org> Rewritten
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Safer use of UnicodeString.
22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef UNISTR_FROM_CHAR_EXPLICIT
23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#   define UNISTR_FROM_CHAR_EXPLICIT explicit
24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Less important, but still a good idea.
27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef UNISTR_FROM_STRING_EXPLICIT
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#   define UNISTR_FROM_STRING_EXPLICIT explicit
29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
31c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include <assert.h>
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "parse.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "errmsg.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uhash.h"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uinvchar.h"
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "read.h"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr.h"
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "reslist.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "rbt_pars.h"
4227f654740f2a26ad62a5c155af9199af9e69b889claireho#include "genrb.h"
43c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/stringpiece.h"
44c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/unistr.h"
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
4627f654740f2a26ad62a5c155af9199af9e69b889claireho#include "unicode/uscript.h"
47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utf16.h"
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
49c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "charstr.h"
50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationbuilder.h"
51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdata.h"
52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatareader.h"
53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatawriter.h"
54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationfastlatinbuilder.h"
55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationinfo.h"
56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationroot.h"
57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationruleparser.h"
58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationtailoring.h"
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Number of tokens to read ahead of the current stream position */
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MAX_LOOKAHEAD   3
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CR               0x000D
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LF               0x000A
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define SPACE            0x0020
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TAB              0x0009
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ESCAPE           0x005C
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define HASH             0x0023
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define QUOTE            0x0027
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZERO             0x0030
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define STARTCOMMAND     0x005B
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ENDCOMMAND       0x005D
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define OPENSQBRACKET    0x005B
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CLOSESQBRACKET   0x005D
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
77c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::CharString;
78c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::LocalMemory;
79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliususing icu::LocalPointer;
80c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::LocalUCHARBUFPointer;
81c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertusing icu::StringPiece;
82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliususing icu::UnicodeString;
83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct Lookahead
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     enum   ETokenType type;
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     struct UString    value;
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     struct UString    comment;
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     uint32_t          line;
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* keep in sync with token defines in read.h */
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *tokenNames[TOK_TOKEN_COUNT] =
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "string",             /* A string token, such as "MonthNames" */
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "'{'",                 /* An opening brace character */
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "'}'",                 /* A closing brace character */
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "','",                 /* A comma */
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "':'",                 /* A colon */
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "<end of file>",     /* End of the file has been reached successfully */
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     "<end of line>"
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Just to store "TRUE" */
10654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const UChar trueValue[] = {0x0054, 0x0052, 0x0055, 0x0045, 0x0000};
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10827f654740f2a26ad62a5c155af9199af9e69b889clairehotypedef struct {
10927f654740f2a26ad62a5c155af9199af9e69b889claireho    struct Lookahead  lookahead[MAX_LOOKAHEAD + 1];
11027f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t          lookaheadPosition;
11127f654740f2a26ad62a5c155af9199af9e69b889claireho    UCHARBUF         *buffer;
11227f654740f2a26ad62a5c155af9199af9e69b889claireho    struct SRBRoot *bundle;
11327f654740f2a26ad62a5c155af9199af9e69b889claireho    const char     *inputdir;
11427f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t        inputdirLength;
11527f654740f2a26ad62a5c155af9199af9e69b889claireho    const char     *outputdir;
11627f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t        outputdirLength;
117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char     *filename;
118103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UBool           makeBinaryCollation;
11959d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool           omitCollationRules;
12027f654740f2a26ad62a5c155af9199af9e69b889claireho} ParseState;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12227f654740f2a26ad62a5c155af9199af9e69b889clairehotypedef struct SResource *
12327f654740f2a26ad62a5c155af9199af9e69b889clairehoParseResourceFunction(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status);
12427f654740f2a26ad62a5c155af9199af9e69b889claireho
12527f654740f2a26ad62a5c155af9199af9e69b889clairehostatic struct SResource *parseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status);
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* The nature of the lookahead buffer:
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   There are MAX_LOOKAHEAD + 1 slots, used as a circular buffer.  This provides
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   MAX_LOOKAHEAD lookahead tokens and a slot for the current token and value.
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   When getToken is called, the current pointer is moved to the next slot and the
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   old slot is filled with the next token from the reader by calling getNextToken.
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   The token values are stored in the slot, which means that token values don't
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   survive a call to getToken, ie.
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   UString *value;
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   getToken(&value, NULL, status);
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   getToken(NULL,   NULL, status);       bad - value is now a different string
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
14127f654740f2a26ad62a5c155af9199af9e69b889clairehoinitLookahead(ParseState* state, UCHARBUF *buf, UErrorCode *status)
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static uint32_t initTypeStrings = 0;
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t i;
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!initTypeStrings)
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        initTypeStrings = 1;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15127f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookaheadPosition   = 0;
15227f654740f2a26ad62a5c155af9199af9e69b889claireho    state->buffer              = buf;
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    resetLineNumber();
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < MAX_LOOKAHEAD; i++)
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
15827f654740f2a26ad62a5c155af9199af9e69b889claireho        state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_ZERO_ERROR;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void
16927f654740f2a26ad62a5c155af9199af9e69b889clairehocleanupLookahead(ParseState* state)
170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
171c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint32_t i;
17254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    for (i = 0; i <= MAX_LOOKAHEAD; i++)
173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {
17427f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_deinit(&state->lookahead[i].value);
17527f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_deinit(&state->lookahead[i].comment);
176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum ETokenType
18127f654740f2a26ad62a5c155af9199af9e69b889clairehogetToken(ParseState* state, struct UString **tokenValue, struct UString* comment, uint32_t *linenumber, UErrorCode *status)
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum ETokenType result;
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          i;
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18627f654740f2a26ad62a5c155af9199af9e69b889claireho    result = state->lookahead[state->lookaheadPosition].type;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tokenValue != NULL)
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
19027f654740f2a26ad62a5c155af9199af9e69b889claireho        *tokenValue = &state->lookahead[state->lookaheadPosition].value;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
19527f654740f2a26ad62a5c155af9199af9e69b889claireho        *linenumber = state->lookahead[state->lookaheadPosition].line;
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (comment != NULL)
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
20027f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20327f654740f2a26ad62a5c155af9199af9e69b889claireho    i = (state->lookaheadPosition + MAX_LOOKAHEAD) % (MAX_LOOKAHEAD + 1);
20427f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookaheadPosition = (state->lookaheadPosition + 1) % (MAX_LOOKAHEAD + 1);
20527f654740f2a26ad62a5c155af9199af9e69b889claireho    ustr_setlen(&state->lookahead[i].comment, 0, status);
20627f654740f2a26ad62a5c155af9199af9e69b889claireho    ustr_setlen(&state->lookahead[i].value, 0, status);
20727f654740f2a26ad62a5c155af9199af9e69b889claireho    state->lookahead[i].type = getNextToken(state->buffer, &state->lookahead[i].value, &state->lookahead[i].line, &state->lookahead[i].comment, status);
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* printf("getToken, returning %s\n", tokenNames[result]); */
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum ETokenType
21527f654740f2a26ad62a5c155af9199af9e69b889clairehopeekToken(ParseState* state, uint32_t lookaheadCount, struct UString **tokenValue, uint32_t *linenumber, struct UString *comment, UErrorCode *status)
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
21727f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t i = (state->lookaheadPosition + lookaheadCount) % (MAX_LOOKAHEAD + 1);
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TOK_ERROR;
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (lookaheadCount >= MAX_LOOKAHEAD)
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INTERNAL_PROGRAM_ERROR;
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TOK_ERROR;
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tokenValue != NULL)
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
23227f654740f2a26ad62a5c155af9199af9e69b889claireho        *tokenValue = &state->lookahead[i].value;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
23727f654740f2a26ad62a5c155af9199af9e69b889claireho        *linenumber = state->lookahead[i].line;
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(comment != NULL){
24127f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_cpy(comment, &(state->lookahead[state->lookaheadPosition].comment), status);
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24427f654740f2a26ad62a5c155af9199af9e69b889claireho    return state->lookahead[i].type;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
24827f654740f2a26ad62a5c155af9199af9e69b889clairehoexpect(ParseState* state, enum ETokenType expectedToken, struct UString **tokenValue, struct UString *comment, uint32_t *linenumber, UErrorCode *status)
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t        line;
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25227f654740f2a26ad62a5c155af9199af9e69b889claireho    enum ETokenType token = getToken(state, tokenValue, comment, &line, status);
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (linenumber != NULL)
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *linenumber = line;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (token != expectedToken)
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "expecting %s, got %s", tokenNames[expectedToken], tokenNames[token]);
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    else
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_ZERO_ERROR;
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27527f654740f2a26ad62a5c155af9199af9e69b889clairehostatic char *getInvariantString(ParseState* state, uint32_t *line, struct UString *comment, UErrorCode *status)
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString *tokenValue;
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char           *result;
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t        count;
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
28127f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, comment, line, status);
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    count = u_strlen(tokenValue->fChars);
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!uprv_isInvariantUString(tokenValue->fChars, count)) {
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(*line, "invariant characters required for table keys, binary data, etc.");
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
29554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    result = static_cast<char *>(uprv_malloc(count+1));
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL)
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, result, count+1);
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
308103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusparseUCARules(ParseState* state, char *tag, uint32_t startline, const struct UString* /*comment*/, UErrorCode *status)
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FileStream       *file          = NULL;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool quoted = FALSE;
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf=NULL;
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32   c     = 0;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp  = NULL;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *target      = NULL;
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *targetLimit = NULL;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = 0;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
32527f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
33627f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->inputdir != NULL)
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
33827f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->inputdir);
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34027f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34827f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35659d709d503bab6e2b61931737e662dd293b40578ccornelius    if(state->omitCollationRules) {
357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return res_none();
358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(filename, &cp, getShowWarning(),FALSE, status);
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "An error occured while opening the input file %s\n", filename);
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We allocate more space than actually required
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * since the actual size needed for storing UChars
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * is not known in UTF-8 byte stream
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size        = ucbuf_size(ucbuf) + 1;
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pTarget     = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * size);
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(pTarget, 0, size*U_SIZEOF_UCHAR);
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    target      = pTarget;
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    targetLimit = pTarget+size;
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* read the rules into the buffer */
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (target < targetLimit)
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        c = ucbuf_getc(ucbuf, status);
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(c == QUOTE) {
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            quoted = (UBool)!quoted;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* weiv (06/26/2002): adding the following:
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * - preserving spaces in commands [...]
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * - # comments until the end of line
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (c == STARTCOMMAND && !quoted)
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* preserve commands
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * closing bracket will be handled by the
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * append at the end of the loop
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(c != ENDCOMMAND) {
39554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                U_APPEND_CHAR32_ONLY(c, target);
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c = ucbuf_getc(ucbuf, status);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (c == HASH && !quoted) {
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* skip comments */
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(c != CR && c != LF) {
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                c = ucbuf_getc(ucbuf, status);
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (c == ESCAPE)
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            c = unescape(ucbuf, status);
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
410103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (c == (UChar32)U_ERR)
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uprv_free(pTarget);
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                T_FileStream_close(file);
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (!quoted && (c == SPACE || c == TAB || c == CR || c == LF))
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* ignore spaces carriage returns
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            * and line feed unless in the form \uXXXX
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            */
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Append UChar * after dissembling if c > 0xffff*/
426103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (c != (UChar32)U_EOF)
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
42854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            U_APPEND_CHAR32_ONLY(c, target);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* terminate the string */
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(target < targetLimit){
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *target = 0x0000;
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44127f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, pTarget, (int32_t)(target - pTarget), NULL, status);
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf_close(ucbuf);
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close(file);
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
452103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusparseTransliterator(ParseState* state, char *tag, uint32_t startline, const struct UString* /*comment*/, UErrorCode *status)
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    FileStream       *file          = NULL;
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf=NULL;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp  = NULL;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *pSource     = NULL;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t size = 0;
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46627f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
47727f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->inputdir != NULL)
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
47927f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->inputdir);
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48127f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48927f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(filename, &cp, getShowWarning(),FALSE, status);
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "An error occured while opening the input file %s\n", filename);
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We allocate more space than actually required
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * since the actual size needed for storing UChars
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * is not known in UTF-8 byte stream
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    */
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pSource = ucbuf_getBuffer(ucbuf, &size, status);
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pTarget     = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * (size + 1));
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(pTarget, 0, size*U_SIZEOF_UCHAR);
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size = utrans_stripRules(pSource, size, pTarget, status);
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    size = 0;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(stderr, " Warning: writing empty transliteration data ( UCONFIG_NO_TRANSLITERATION ) \n");
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
51927f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, pTarget, size, NULL, status);
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf_close(ucbuf);
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close(file);
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
527c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic ArrayResource* dependencyArray = NULL;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
53027f654740f2a26ad62a5c155af9199af9e69b889clairehoparseDependency(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *elem = NULL;
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              filename[256] = { '\0' };
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              cs[128]       = { '\0' };
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
53927f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, &line, status);
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* make the filename including the directory */
55027f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state->outputdir != NULL)
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
55227f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_strcat(filename, state->outputdir);
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->outputdir[state->outputdirLength - 1] != U_FILE_SEP_CHAR)
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(filename, U_FILE_SEP_STRING);
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(tokenValue->fChars, cs, tokenValue->fLength);
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_strcat(filename, cs);
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!T_FileStream_file_exists(filename)){
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isStrict()){
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "The dependency file %s does not exist. Please make sure it exists.\n",filename);
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }else{
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            warning(line, "The dependency file %s does not exist. Please make sure it exists.\n",filename);
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dependencyArray==NULL){
57527f654740f2a26ad62a5c155af9199af9e69b889claireho        dependencyArray = array_open(state->bundle, "%%DEPENDENCY", NULL, status);
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(tag!=NULL){
57827f654740f2a26ad62a5c155af9199af9e69b889claireho        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
58027f654740f2a26ad62a5c155af9199af9e69b889claireho    elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, comment, status);
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
582c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    dependencyArray->add(elem);
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
58827f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
59227f654740f2a26ad62a5c155af9199af9e69b889clairehoparseString(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*    if (tag != NULL && uprv_strcmp(tag, "%%UCARULES") == 0)
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return parseUCARules(tag, startline, status);
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }*/
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" string %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
60427f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, NULL, status);
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(*status))
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        doesn't survive expect either) */
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61127f654740f2a26ad62a5c155af9199af9e69b889claireho        result = string_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_SUCCESS(*status) && result) {
61327f654740f2a26ad62a5c155af9199af9e69b889claireho            expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
615c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (U_FAILURE(*status))
616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            {
617c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return NULL;
619c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
62727f654740f2a26ad62a5c155af9199af9e69b889clairehoparseAlias(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString   *tokenValue;
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result  = NULL;
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63227f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, NULL, NULL, status);
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" alias %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(*status))
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* create the string now - tokenValue doesn't survive a call to getToken (and therefore
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        doesn't survive expect either) */
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64327f654740f2a26ad62a5c155af9199af9e69b889claireho        result = alias_open(state->bundle, tag, tokenValue->fChars, tokenValue->fLength, comment, status);
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
64527f654740f2a26ad62a5c155af9199af9e69b889claireho        expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
649c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
657fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_COLLATION
658fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
659fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusnamespace {
66027f654740f2a26ad62a5c155af9199af9e69b889claireho
66127f654740f2a26ad62a5c155af9199af9e69b889clairehostatic struct SResource* resLookup(struct SResource* res, const char* key){
662c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (res == res_none() || !res->isTable()) {
66327f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
66427f654740f2a26ad62a5c155af9199af9e69b889claireho    }
66527f654740f2a26ad62a5c155af9199af9e69b889claireho
666c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *list = static_cast<TableResource *>(res);
667c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    SResource *current = list->fFirst;
66827f654740f2a26ad62a5c155af9199af9e69b889claireho    while (current != NULL) {
66927f654740f2a26ad62a5c155af9199af9e69b889claireho        if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) {
67027f654740f2a26ad62a5c155af9199af9e69b889claireho            return current;
67127f654740f2a26ad62a5c155af9199af9e69b889claireho        }
67227f654740f2a26ad62a5c155af9199af9e69b889claireho        current = current->fNext;
67327f654740f2a26ad62a5c155af9199af9e69b889claireho    }
67427f654740f2a26ad62a5c155af9199af9e69b889claireho    return NULL;
67527f654740f2a26ad62a5c155af9199af9e69b889claireho}
67627f654740f2a26ad62a5c155af9199af9e69b889claireho
677fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass GenrbImporter : public icu::CollationRuleParser::Importer {
678fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic:
679fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    GenrbImporter(const char *in, const char *out) : inputDir(in), outputDir(out) {}
680fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    virtual ~GenrbImporter();
681f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    virtual void getRules(
682fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            const char *localeID, const char *collationType,
683f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            UnicodeString &rules,
684fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            const char *&errorReason, UErrorCode &errorCode);
685fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
686fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate:
687fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char *inputDir;
688fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char *outputDir;
689fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius};
690fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
691fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusGenrbImporter::~GenrbImporter() {}
692fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
693f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusvoid
694fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusGenrbImporter::getRules(
695fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *localeID, const char *collationType,
696f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        UnicodeString &rules,
697fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *& /*errorReason*/, UErrorCode &errorCode) {
698c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString filename(localeID, errorCode);
699c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    for(int32_t i = 0; i < filename.length(); i++){
70027f654740f2a26ad62a5c155af9199af9e69b889claireho        if(filename[i] == '-'){
701c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            filename.data()[i] = '_';
70227f654740f2a26ad62a5c155af9199af9e69b889claireho        }
70327f654740f2a26ad62a5c155af9199af9e69b889claireho    }
704c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    filename.append(".txt", errorCode);
705fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(errorCode)) {
706f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
70727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
708c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString inputDirBuf;
709c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString openFileName;
710fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(inputDir == NULL) {
711c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        const char *filenameBegin = uprv_strrchr(filename.data(), U_FILE_SEP_CHAR);
71227f654740f2a26ad62a5c155af9199af9e69b889claireho        if (filenameBegin != NULL) {
71327f654740f2a26ad62a5c155af9199af9e69b889claireho            /*
71427f654740f2a26ad62a5c155af9199af9e69b889claireho             * When a filename ../../../data/root.txt is specified,
71527f654740f2a26ad62a5c155af9199af9e69b889claireho             * we presume that the input directory is ../../../data
71627f654740f2a26ad62a5c155af9199af9e69b889claireho             * This is very important when the resource file includes
71727f654740f2a26ad62a5c155af9199af9e69b889claireho             * another file, like UCARules.txt or thaidict.brk.
71827f654740f2a26ad62a5c155af9199af9e69b889claireho             */
719c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringPiece dir = filename.toStringPiece();
720c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            const char *filenameLimit = filename.data() + filename.length();
721c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            dir.remove_suffix((int32_t)(filenameLimit - filenameBegin));
722c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            inputDirBuf.append(dir, errorCode);
723c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            inputDir = inputDirBuf.data();
72427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
72527f654740f2a26ad62a5c155af9199af9e69b889claireho    }else{
726c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        int32_t dirlen  = (int32_t)uprv_strlen(inputDir);
72727f654740f2a26ad62a5c155af9199af9e69b889claireho
728c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if((filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')) {
72927f654740f2a26ad62a5c155af9199af9e69b889claireho            /*
73027f654740f2a26ad62a5c155af9199af9e69b889claireho             * append the input dir to openFileName if the first char in
731c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert             * filename is not file separator char and the last char input directory is  not '.'.
73227f654740f2a26ad62a5c155af9199af9e69b889claireho             * This is to support :
73327f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. /home/icu/data
73427f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. icu/data
73527f654740f2a26ad62a5c155af9199af9e69b889claireho             * The user cannot mix notations like
73627f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. /icu/data --- the absolute path specified. -s redundant
73727f654740f2a26ad62a5c155af9199af9e69b889claireho             * user should use
73827f654740f2a26ad62a5c155af9199af9e69b889claireho             * genrb -s. icu/data  --- start from CWD and look in icu/data dir
73927f654740f2a26ad62a5c155af9199af9e69b889claireho             */
740c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            openFileName.append(inputDir, dirlen, errorCode);
741c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
742c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                openFileName.append(U_FILE_SEP_CHAR, errorCode);
74327f654740f2a26ad62a5c155af9199af9e69b889claireho            }
74427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
74527f654740f2a26ad62a5c155af9199af9e69b889claireho    }
746c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    openFileName.append(filename, errorCode);
747c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if(U_FAILURE(errorCode)) {
748c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
749c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
750c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    // printf("GenrbImporter::getRules(%s, %s) reads %s\n", localeID, collationType, openFileName.data());
751c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    const char* cp = "";
752c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalUCHARBUFPointer ucbuf(
753c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            ucbuf_open(openFileName.data(), &cp, getShowWarning(), TRUE, &errorCode));
754fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(errorCode == U_FILE_ACCESS_ERROR) {
755c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fprintf(stderr, "couldn't open file %s\n", openFileName.data());
756c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
75727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
758c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (ucbuf.isNull() || U_FAILURE(errorCode)) {
759c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName.data(), u_errorName(errorCode));
760c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
76127f654740f2a26ad62a5c155af9199af9e69b889claireho    }
76227f654740f2a26ad62a5c155af9199af9e69b889claireho
76327f654740f2a26ad62a5c155af9199af9e69b889claireho    /* Parse the data into an SRBRoot */
764c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SRBRoot *data =
765c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            parse(ucbuf.getAlias(), inputDir, outputDir, filename.data(), FALSE, FALSE, &errorCode);
766f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(errorCode)) {
767c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
768f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
76927f654740f2a26ad62a5c155af9199af9e69b889claireho
770c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SResource *root = data->fRoot;
771c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    struct SResource *collations = resLookup(root, "collations");
772103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (collations != NULL) {
773c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert      struct SResource *collation = resLookup(collations, collationType);
774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      if (collation != NULL) {
775c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        struct SResource *sequence = resLookup(collation, "Sequence");
776c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (sequence != NULL && sequence->isString()) {
777f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius          // No string pointer aliasing so that we need not hold onto the resource bundle.
778c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert          StringResource *sr = static_cast<StringResource *>(sequence);
779c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert          rules = sr->fString;
780103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
781103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      }
782103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
78327f654740f2a26ad62a5c155af9199af9e69b889claireho}
78427f654740f2a26ad62a5c155af9199af9e69b889claireho
785103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Quick-and-dirty escaping function.
786103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Assumes that we are on an ASCII-based platform.
787103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic void
788103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusescape(const UChar *s, char *buffer) {
789103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t length = u_strlen(s);
790103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t i = 0;
791103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    for (;;) {
792103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UChar32 c;
793103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U16_NEXT(s, i, length, c);
794103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (c == 0) {
795103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            *buffer = 0;
796103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return;
797103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else if (0x20 <= c && c <= 0x7e) {
798103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            // printable ASCII
799103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            *buffer++ = (char)c;  // assumes ASCII-based platform
800103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else {
801103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            buffer += sprintf(buffer, "\\u%04X", (int)c);
802103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
803103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
805103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
806fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}  // namespace
807fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
808fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif  // !UCONFIG_NO_COLLATION
809fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
810c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic TableResource *
811c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertaddCollation(ParseState* state, TableResource  *result, const char *collationType,
812fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             uint32_t startline, UErrorCode *status)
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
814fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // TODO: Use LocalPointer for result, or make caller close it when there is a failure.
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     comment;
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char               subtag[1024];
820fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UnicodeString      rules;
821fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UBool              haveRules = FALSE;
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UVersionInfo       version;
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
824fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . (name resource)* '}' */
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    version[0]=0; version[1]=0; version[2]=0; version[3]=0;
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_init(&comment);
83127f654740f2a26ad62a5c155af9199af9e69b889claireho        token = getToken(state, &tokenValue, &comment, &line, status);
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
835fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            break;
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token != TOK_STRING)
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
840c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_EOF)
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(startline, "unterminated table");
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "Unexpected token %s", tokenNames[token]);
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
859c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86327f654740f2a26ad62a5c155af9199af9e69b889claireho        member = parseResource(state, subtag, NULL, status);
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
870fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (result == NULL)
871fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        {
872fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Ignore the parsed resources, continue parsing.
873fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
874c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else if (uprv_strcmp(subtag, "Version") == 0 && member->isString())
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
876c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringResource *sr = static_cast<StringResource *>(member);
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char     ver[40];
878c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            int32_t length = sr->length();
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
880c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if (length >= UPRV_LENGTHOF(ver))
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
882c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                length = UPRV_LENGTHOF(ver) - 1;
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
885c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            sr->fString.extract(0, length, ver, UPRV_LENGTHOF(ver), US_INV);
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_versionFromString(version, ver);
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
888c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(member, line, *status);
889fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            member = NULL;
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(uprv_strcmp(subtag, "%%CollationBin")==0)
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* discard duplicate %%CollationBin if any*/
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
895c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else if (uprv_strcmp(subtag, "Sequence") == 0 && member->isString())
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
897c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            StringResource *sr = static_cast<StringResource *>(member);
898c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            rules = sr->fString;
899fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            haveRules = TRUE;
900fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Defer building the collator until we have seen
901fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // all sub-elements of the collation table, including the Version.
90250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* in order to achieve smaller data files, we can direct genrb */
90350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* to omit collation rules */
904fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if(!state->omitCollationRules) {
905c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                result->add(member, line, *status);
906fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                member = NULL;
90750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
909fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        else  // Just copy non-special items.
910fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        {
911c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(member, line, *status);
912fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            member = NULL;
913fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
914fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(member);  // TODO: use LocalPointer
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
917c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
922fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (!haveRules) { return result; }
923fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
924fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if UCONFIG_NO_COLLATION || UCONFIG_NO_FILE_IO
925fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    warning(line, "Not building collation elements because of UCONFIG_NO_COLLATION and/or UCONFIG_NO_FILE_IO, see uconfig.h");
926fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    (void)collationType;
927fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#else
928f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // CLDR ticket #3949, ICU ticket #8082:
929f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // Do not build collation binary data for for-import-only "private" collation rule strings.
930f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (uprv_strncmp(collationType, "private-", 8) == 0) {
931f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if(isVerbose()) {
932f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            printf("Not building %s~%s collation binary\n", state->filename, collationType);
933f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
934f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return result;
935f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
936f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
937fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(!state->makeBinaryCollation) {
938fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(isVerbose()) {
939fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            printf("Not building %s~%s collation binary\n", state->filename, collationType);
940fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
941fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return result;
942fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
943fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode intStatus = U_ZERO_ERROR;
944fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UParseError parseError;
945fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uprv_memset(&parseError, 0, sizeof(parseError));
946fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    GenrbImporter importer(state->inputdir, state->outputdir);
947fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const icu::CollationTailoring *base = icu::CollationRoot::getRoot(intStatus);
948fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
949fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        error(line, "failed to load root collator (ucadata.icu) - %s", u_errorName(intStatus));
950fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
951fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;  // TODO: use LocalUResourceBundlePointer for result
952fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
953fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    icu::CollationBuilder builder(base, intStatus);
954fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(uprv_strncmp(collationType, "search", 6) == 0) {
955fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        builder.disableFastLatin();  // build fast-Latin table unless search collator
956fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
957fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    LocalPointer<icu::CollationTailoring> t(
958fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            builder.parseAndBuild(rules, version, &importer, &parseError, intStatus));
959fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
960fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const char *reason = builder.getErrorReason();
961fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(reason == NULL) { reason = ""; }
962fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        error(line, "CollationBuilder failed at %s~%s/Sequence rule offset %ld: %s  %s",
963fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                state->filename, collationType,
964fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (long)parseError.offset, u_errorName(intStatus), reason);
965fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(parseError.preContext[0] != 0 || parseError.postContext[0] != 0) {
966fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Print pre- and post-context.
967fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            char preBuffer[100], postBuffer[100];
968fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            escape(parseError.preContext, preBuffer);
969fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            escape(parseError.postContext, postBuffer);
970fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            error(line, "  error context: \"...%s\" ! \"%s...\"", preBuffer, postBuffer);
971fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
972c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if(isStrict() || t.isNull()) {
973fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = intStatus;
974fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            res_close(result);
975fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return NULL;
976fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
977fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
978fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    icu::LocalMemory<uint8_t> buffer;
979fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t capacity = 100000;
980fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    uint8_t *dest = buffer.allocateInsteadAndCopy(capacity);
981fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(dest == NULL) {
982fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\n",
983fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (long)capacity);
984fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        *status = U_MEMORY_ALLOCATION_ERROR;
985fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
986fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
987fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
988fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t indexes[icu::CollationDataReader::IX_TOTAL_SIZE + 1];
989fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t totalSize = icu::CollationDataWriter::writeTailoring(
990fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *t, *t->settings, indexes, dest, capacity, intStatus);
991fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(intStatus == U_BUFFER_OVERFLOW_ERROR) {
992fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        intStatus = U_ZERO_ERROR;
993fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        capacity = totalSize;
994fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        dest = buffer.allocateInsteadAndCopy(capacity);
995fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if(dest == NULL) {
996fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            fprintf(stderr, "memory allocation (%ld bytes) for file contents failed\n",
997fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    (long)capacity);
998fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            *status = U_MEMORY_ALLOCATION_ERROR;
999fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            res_close(result);
1000fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return NULL;
1001fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1002fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        totalSize = icu::CollationDataWriter::writeTailoring(
1003fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                *t, *t->settings, indexes, dest, capacity, intStatus);
1004fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1005fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(U_FAILURE(intStatus)) {
1006fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        fprintf(stderr, "CollationDataWriter::writeTailoring() failed: %s\n",
1007fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                u_errorName(intStatus));
1008fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
1009fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
1010fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1011fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(isVerbose()) {
1012fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        printf("%s~%s collation tailoring part sizes:\n", state->filename, collationType);
1013fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        icu::CollationInfo::printSizes(totalSize, indexes);
10141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        if(t->settings->hasReordering()) {
10151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            printf("%s~%s collation reordering ranges:\n", state->filename, collationType);
10161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            icu::CollationInfo::printReorderRanges(
10171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert                    *t->data, t->settings->reorderCodes, t->settings->reorderCodesLength);
10181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
1019fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1020fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", totalSize, dest, NULL, NULL, status);
1021c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    result->add(collationBin, line, *status);
1022fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(*status)) {
1023fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        res_close(result);
1024fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return NULL;
1025fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1026fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1027fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return result;
1028fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1029fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1030fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool
1031fc41dc5b8c2370d49e461ba58d6cbe33b20ed002Fredrik RoubertkeepCollationType(const char *type) {  // android-changed
1032fc41dc5b8c2370d49e461ba58d6cbe33b20ed002Fredrik Roubert    // BEGIN android-added
1033fc41dc5b8c2370d49e461ba58d6cbe33b20ed002Fredrik Roubert    if (uprv_strcmp(type, "big5han") == 0) { return FALSE; }
1034fc41dc5b8c2370d49e461ba58d6cbe33b20ed002Fredrik Roubert    if (uprv_strcmp(type, "gb2312han") == 0) { return FALSE; }
1035fc41dc5b8c2370d49e461ba58d6cbe33b20ed002Fredrik Roubert    // END android-added
1036f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TRUE;
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
104027f654740f2a26ad62a5c155af9199af9e69b889clairehoparseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1042c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource  *result = NULL;
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     comment;
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char               subtag[1024], typeKeyword[1024];
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
105027f654740f2a26ad62a5c155af9199af9e69b889claireho    result = table_open(state->bundle, tag, NULL, status);
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" collation elements %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!newCollation) {
1060fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return addCollation(state, result, "(no type)", startline, status);
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ustr_init(&comment);
106527f654740f2a26ad62a5c155af9199af9e69b889claireho            token = getToken(state, &tokenValue, &comment, &line, status);
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_CLOSE_BRACE)
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return result;
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token != TOK_STRING)
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1074c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INVALID_FORMAT_ERROR;
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (token == TOK_EOF)
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    error(startline, "unterminated table");
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                else
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    error(line, "Unexpected token %s", tokenNames[token]);
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1093c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (uprv_strcmp(subtag, "default") == 0)
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
109927f654740f2a26ad62a5c155af9199af9e69b889claireho                member = parseResource(state, subtag, NULL, status);
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(*status))
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    res_close(result);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1107c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                result->add(member, line, *status);
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
111127f654740f2a26ad62a5c155af9199af9e69b889claireho                token = peekToken(state, 0, &tokenValue, &line, &comment, status);
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* this probably needs to be refactored or recursively use the parser */
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* first we assume that our collation table won't have the explicit type */
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* then, we cannot handle aliases */
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(token == TOK_OPEN_BRACE) {
111627f654740f2a26ad62a5c155af9199af9e69b889claireho                    token = getToken(state, &tokenValue, &comment, &line, status);
1117c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                    TableResource *collationRes;
1118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (keepCollationType(subtag)) {
1119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        collationRes = table_open(state->bundle, subtag, NULL, status);
1120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
1121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        collationRes = NULL;
1122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
1123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // need to parse the collation data regardless
1124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    collationRes = addCollation(state, collationRes, subtag, startline, status);
1125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (collationRes != NULL) {
1126c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                        result->add(collationRes, startline, *status);
112727f654740f2a26ad62a5c155af9199af9e69b889claireho                    }
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else if(token == TOK_COLON) { /* right now, we'll just try to see if we have aliases */
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* we could have a table too */
113027f654740f2a26ad62a5c155af9199af9e69b889claireho                    token = peekToken(state, 1, &tokenValue, &line, &comment, status);
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(tokenValue->fChars) + 1);
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(uprv_strcmp(typeKeyword, "alias") == 0) {
113327f654740f2a26ad62a5c155af9199af9e69b889claireho                        member = parseResource(state, subtag, NULL, status);
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (U_FAILURE(*status))
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        {
1136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            res_close(result);
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            return NULL;
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1140c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                        result->add(member, line, *status);
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
1142c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        res_close(result);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        *status = U_INVALID_FORMAT_ERROR;
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        return NULL;
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    res_close(result);
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *status = U_INVALID_FORMAT_ERROR;
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*member = string_open(bundle, subtag, tokenValue->fChars, tokenValue->fLength, status);*/
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*expect(TOK_CLOSE_BRACE, NULL, NULL, status);*/
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1159c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                res_close(result);
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   if this weren't special-cased, wouldn't be set until the entire file had been processed. */
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
1169c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertrealParseTable(ParseState* state, TableResource *table, char *tag, uint32_t startline, UErrorCode *status)
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue=NULL;
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    comment;
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType token;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              subtag[1024];
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool             readToken = FALSE;
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . (name resource)* '}' */
1180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" parsing table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline);
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_init(&comment);
118727f654740f2a26ad62a5c155af9199af9e69b889claireho        token = getToken(state, &tokenValue, &comment, &line, status);
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty table");
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return table;
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token != TOK_STRING)
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (token == TOK_EOF)
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(startline, "unterminated table");
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "unexpected token %s", tokenNames[token]);
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(uprv_isInvariantUString(tokenValue->fChars, -1)) {
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1);
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "invariant characters required for table keys");
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing tokens with %s", u_errorName(*status));
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122727f654740f2a26ad62a5c155af9199af9e69b889claireho        member = parseResource(state, subtag, &comment, status);
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (member == NULL || U_FAILURE(*status))
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing resource with %s", u_errorName(*status));
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1235c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        table->add(member, line, *status);
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            error(line, "parse error. Stopped parsing table with %s", u_errorName(*status));
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ustr_deinit(&comment);
1244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius   }
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* not reached */
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* A compiler warning will appear if all paths don't contain a return statement. */
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*     *status = U_INTERNAL_PROGRAM_ERROR;
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     return NULL;*/
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
125327f654740f2a26ad62a5c155af9199af9e69b889clairehoparseTable(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0)
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
125727f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseCollationElements(state, tag, startline, FALSE, status);
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (tag != NULL && uprv_strcmp(tag, "collations") == 0)
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
126127f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseCollationElements(state, tag, startline, TRUE, status);
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" table %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1267c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *result = table_open(state->bundle, tag, comment, status);
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
127327f654740f2a26ad62a5c155af9199af9e69b889claireho    return realParseTable(state, result, tag, startline,  status);
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
127727f654740f2a26ad62a5c155af9199af9e69b889clairehoparseArray(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource  *member = NULL;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    memberComments;
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType token;
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool             readToken = FALSE;
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1285c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    ArrayResource  *result = array_open(state->bundle, tag, comment, status);
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" array %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&memberComments);
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . resource [','] '}' */
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* reset length */
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_setlen(&memberComments, 0, status);
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* check for end of array, but don't consume next token unless it really is the end */
130427f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, &tokenValue, NULL, &memberComments, status);
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
130927f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty array");
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_EOF)
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(startline, "unterminated array");
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* string arrays are a special case */
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_STRING)
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
132727f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, &tokenValue, &memberComments, NULL, status);
132827f654740f2a26ad62a5c155af9199af9e69b889claireho            member = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, &memberComments, status);
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
133227f654740f2a26ad62a5c155af9199af9e69b889claireho            member = parseResource(state, NULL, &memberComments, status);
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (member == NULL || U_FAILURE(*status))
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1341c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        result->add(member);
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* eat optional comma if present */
134427f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, NULL, NULL, status);
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_COMMA)
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
134827f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ustr_deinit(&memberComments);
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
136427f654740f2a26ad62a5c155af9199af9e69b889clairehoparseIntVector(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType  token;
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              *string;
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t            value;
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool              readToken = FALSE;
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char              *stopstring;
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           len;
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString     memberComments;
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1374c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    IntVectorResource *result = intvector_open(state->bundle, tag, comment, status);
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (result == NULL || U_FAILURE(*status))
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" vector %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&memberComments);
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* '{' . string [','] '}' */
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;)
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ustr_setlen(&memberComments, 0, status);
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* check for end of array, but don't consume next token unless it really is the end */
139127f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, NULL,&memberComments, status);
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_CLOSE_BRACE)
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* it's the end, consume the close brace */
139627f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (!readToken) {
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                warning(startline, "Encountered empty int vector");
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            ustr_deinit(&memberComments);
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return result;
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
140427f654740f2a26ad62a5c155af9199af9e69b889claireho        string = getInvariantString(state, NULL, NULL, status);
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        /* For handling illegal char in the Intvector */
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        value = uprv_strtoul(string, &stopstring, 0);/* make intvector support decimal,hexdigit,octal digit ranging from -2^31-2^32-1*/
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        len=(uint32_t)(stopstring-string);
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(len==uprv_strlen(string))
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1418c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            result->add(value, *status);
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(string);
142027f654740f2a26ad62a5c155af9199af9e69b889claireho            token = peekToken(state, 0, NULL, NULL, NULL, status);
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(string);
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_INVALID_CHAR_FOUND;
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            res_close(result);
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the comma is optional (even though it is required to prevent the reader from concatenating
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        consecutive entries) so that a missing comma on the last entry isn't an error */
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_COMMA)
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
143827f654740f2a26ad62a5c155af9199af9e69b889claireho            getToken(state, NULL, NULL, NULL, status);
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        readToken = TRUE;
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* not reached */
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* A compiler warning will appear if all paths don't contain a return statement. */
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*    intvector_close(result, status);
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_INTERNAL_PROGRAM_ERROR;
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;*/
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
145127f654740f2a26ad62a5c155af9199af9e69b889clairehoparseBinary(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1453c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    uint32_t line;
1454c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<char> string(getInvariantString(state, &line, NULL, status));
1455c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (string.isNull() || U_FAILURE(*status))
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146027f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" binary %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1470c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    uint32_t count = (uint32_t)uprv_strlen(string.getAlias());
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (count > 0){
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((count % 2)==0){
1473c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            LocalMemory<uint8_t> value;
1474c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            if (value.allocateInsteadAndCopy(count) == NULL)
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1480c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            char toConv[3] = {'\0', '\0', '\0'};
1481c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            for (uint32_t i = 0; i < count; i += 2)
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                toConv[0] = string[i];
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                toConv[1] = string[i + 1];
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1486c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                char *stopstring;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16);
1488c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                uint32_t len=(uint32_t)(stopstring-toConv);
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                if(len!=2)
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *status=U_INVALID_CHAR_FOUND;
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return NULL;
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1497c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            return bin_open(state->bundle, tag, count >> 1, value.getAlias(), NULL, comment, status);
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_CHAR_FOUND;
1502c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            error(line, "Encountered invalid binary value (length is odd)");
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1508c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        warning(startline, "Encountered empty binary value");
1509c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return bin_open(state->bundle, tag, 0, NULL, "", comment, status);
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
151427f654740f2a26ad62a5c155af9199af9e69b889clairehoparseInteger(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result = NULL;
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t           value;
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *string;
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *stopstring;
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          len;
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152227f654740f2a26ad62a5c155af9199af9e69b889claireho    string = getInvariantString(state, NULL, NULL, status);
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (string == NULL || U_FAILURE(*status))
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152927f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(string);
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" integer %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (uprv_strlen(string) <= 0)
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        warning(startline, "Encountered empty integer. Default value is 0.");
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* Allow integer support for hexdecimal, octal digit and decimal*/
1547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    /* and handle illegal char in the integer*/
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    value = uprv_strtoul(string, &stopstring, 0);
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    len=(uint32_t)(stopstring-string);
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(len==uprv_strlen(string))
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
155227f654740f2a26ad62a5c155af9199af9e69b889claireho        result = int_open(state->bundle, tag, value, comment, status);
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status=U_INVALID_CHAR_FOUND;
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(string);
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
156427f654740f2a26ad62a5c155af9199af9e69b889clairehoparseImport(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1567c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<char> filename(getInvariantString(state, &line, NULL, status));
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
157327f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" import %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Open the input file for reading */
1585c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    CharString fullname;
1586c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (state->inputdir != NULL) {
1587c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        fullname.append(state->inputdir, *status);
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1589c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    fullname.appendPathPart(filename.getAlias(), *status);
1590c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (U_FAILURE(*status)) {
1591c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return NULL;
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1594c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    FileStream *file = T_FileStream_open(fullname.data(), "rb");
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (file == NULL)
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1597c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        error(line, "couldn't open input file %s", filename.getAlias());
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_FILE_ACCESS_ERROR;
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1602c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    int32_t len  = T_FileStream_size(file);
1603c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<uint8_t> data;
1604c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if(data.allocateInsteadAndCopy(len) == NULL)
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        T_FileStream_close (file);
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1611c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /* int32_t numRead = */ T_FileStream_read(file, data.getAlias(), len);
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    T_FileStream_close (file);
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1614c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return bin_open(state->bundle, tag, len, data.getAlias(), fullname.data(), comment, status);
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
161827f654740f2a26ad62a5c155af9199af9e69b889clairehoparseInclude(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct SResource *result;
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t           len=0;
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char             *filename;
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t          line;
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *pTarget     = NULL;
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCHARBUF *ucbuf;
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char     *fullname = NULL;
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  count     = 0;
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char* cp = NULL;
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* uBuffer = NULL;
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
163227f654740f2a26ad62a5c155af9199af9e69b889claireho    filename = getInvariantString(state, &line, NULL, status);
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    count     = (int32_t)uprv_strlen(filename);
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
164027f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(filename);
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" include %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165227f654740f2a26ad62a5c155af9199af9e69b889claireho    fullname = (char *) uprv_malloc(state->inputdirLength + count + 2);
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* test for NULL */
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fullname == NULL)
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(filename);
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166127f654740f2a26ad62a5c155af9199af9e69b889claireho    if(state->inputdir!=NULL){
166227f654740f2a26ad62a5c155af9199af9e69b889claireho        if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166527f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_strcpy(fullname, state->inputdir);
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166727f654740f2a26ad62a5c155af9199af9e69b889claireho            fullname[state->inputdirLength]      = U_FILE_SEP_CHAR;
166827f654740f2a26ad62a5c155af9199af9e69b889claireho            fullname[state->inputdirLength + 1] = '\0';
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(fullname, filename);
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
167427f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_strcpy(fullname, state->inputdir);
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(fullname, filename);
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }else{
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strcpy(fullname,filename);
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucbuf = ucbuf_open(fullname, &cp,getShowWarning(),FALSE,status);
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status)) {
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "couldn't open input file %s\n", filename);
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uBuffer = ucbuf_getBuffer(ucbuf,&len,status);
168927f654740f2a26ad62a5c155af9199af9e69b889claireho    result = string_open(state->bundle, tag, uBuffer, len, comment, status);
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
169154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    ucbuf_close(ucbuf);
169254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(pTarget);
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(filename);
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(fullname);
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_string,    "string",    6);
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_binary,    "binary",    6);
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_bin,       "bin",       3);
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_table,     "table",     5);
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_table_no_fallback,     "table(nofallback)",         17);
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_int,       "int",       3);
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_integer,   "integer",   7);
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_array,     "array",     5);
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_alias,     "alias",     5);
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_intvector, "intvector", 9);
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_import,    "import",    6);
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_include,   "include",   7);
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Various non-standard processing plugins that create one or more special resources. */
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_uca_rules,      "process(uca_rules)",        18);
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_collation,      "process(collation)",        18);
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_transliterator, "process(transliterator)",   23);
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_STRING_DECL(k_type_plugin_dependency,     "process(dependency)",       19);
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef enum EResourceType
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1726fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_UNKNOWN,
1727fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_STRING,
1728fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_BINARY,
1729fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_TABLE,
1730fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_TABLE_NO_FALLBACK,
1731fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INTEGER,
1732fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_ARRAY,
1733fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_ALIAS,
1734fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INTVECTOR,
1735fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_IMPORT,
1736fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_INCLUDE,
1737fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_UCA_RULES,
1738fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_COLLATION,
1739fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_TRANSLITERATOR,
1740fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_PROCESS_DEPENDENCY,
1741fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    RESTYPE_RESERVED
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} EResourceType;
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct {
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *nameChars;   /* only used for debugging */
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *nameUChars;
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ParseResourceFunction *parseFunction;
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} gResourceTypes[] = {
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"Unknown", NULL, NULL},
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"string", k_type_string, parseString},
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"binary", k_type_binary, parseBinary},
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"table", k_type_table, parseTable},
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"table(nofallback)", k_type_table_no_fallback, NULL}, /* parseFunction will never be called */
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"integer", k_type_integer, parseInteger},
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"array", k_type_array, parseArray},
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"alias", k_type_alias, parseAlias},
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"intvector", k_type_intvector, parseIntVector},
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"import", k_type_import, parseImport},
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"include", k_type_include, parseInclude},
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(uca_rules)", k_type_plugin_uca_rules, parseUCARules},
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(collation)", k_type_plugin_collation, NULL /* not implemented yet */},
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(transliterator)", k_type_plugin_transliterator, parseTransliterator},
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"process(dependency)", k_type_plugin_dependency, parseDependency},
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"reserved", NULL, NULL}
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
176759d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid initParser()
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_string,    "string",    6);
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_binary,    "binary",    6);
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_bin,       "bin",       3);
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_table,     "table",     5);
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_table_no_fallback,     "table(nofallback)",         17);
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_int,       "int",       3);
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_integer,   "integer",   7);
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_array,     "array",     5);
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_alias,     "alias",     5);
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_intvector, "intvector", 9);
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_import,    "import",    6);
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_include,   "include",   7);
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_uca_rules,      "process(uca_rules)",        18);
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_collation,      "process(collation)",        18);
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_transliterator, "process(transliterator)",   23);
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_STRING_INIT(k_type_plugin_dependency,     "process(dependency)",       19);
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1788103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline UBool isTable(enum EResourceType type) {
1789fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return (UBool)(type==RESTYPE_TABLE || type==RESTYPE_TABLE_NO_FALLBACK);
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic enum EResourceType
179327f654740f2a26ad62a5c155af9199af9e69b889clairehoparseResourceType(ParseState* state, UErrorCode *status)
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        *tokenValue;
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        comment;
1797fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    enum   EResourceType  result = RESTYPE_UNKNOWN;
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t              line=0;
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&comment);
180027f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(state, TOK_STRING, &tokenValue, &comment, &line, status);
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1804fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return RESTYPE_UNKNOWN;
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *status = U_ZERO_ERROR;
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Search for normal types */
1810fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    result=RESTYPE_UNKNOWN;
1811fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    while ((result=(EResourceType)(result+1)) < RESTYPE_RESERVED) {
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (u_strcmp(tokenValue->fChars, gResourceTypes[result].nameUChars) == 0) {
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Now search for the aliases */
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (u_strcmp(tokenValue->fChars, k_type_int) == 0) {
1818fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = RESTYPE_INTEGER;
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if (u_strcmp(tokenValue->fChars, k_type_bin) == 0) {
1821fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        result = RESTYPE_BINARY;
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1823fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    else if (result == RESTYPE_RESERVED) {
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char tokenBuffer[1024];
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u_austrncpy(tokenBuffer, tokenValue->fChars, sizeof(tokenBuffer));
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tokenBuffer[sizeof(tokenBuffer) - 1] = 0;
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(line, "unknown resource type '%s'", tokenBuffer);
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* parse a non-top-level resource */
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct SResource *
183627f654740f2a26ad62a5c155af9199af9e69b889clairehoparseResource(ParseState* state, char *tag, const struct UString *comment, UErrorCode *status)
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum   ETokenType      token;
1839fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    enum   EResourceType  resType = RESTYPE_UNKNOWN;
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ParseResourceFunction *parseFunction = NULL;
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString        *tokenValue;
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t                 startline;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t                 line;
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
184627f654740f2a26ad62a5c155af9199af9e69b889claireho    token = getToken(state, &tokenValue, NULL, &startline, status);
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isVerbose()){
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        printf(" resource %s at line %i \n",  (tag == NULL) ? "(null)" : tag, (int)startline);
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* name . [ ':' type ] '{' resource '}' */
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* This function parses from the colon onwards.  If the colon is present, parse the
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    type then try to parse a resource of that type.  If there is no explicit type,
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    work it out using the lookahead tokens. */
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (token)
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_EOF:
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "Unexpected EOF encountered");
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_ERROR:
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_COLON:
186827f654740f2a26ad62a5c155af9199af9e69b889claireho        resType = parseResourceType(state, status);
186927f654740f2a26ad62a5c155af9199af9e69b889claireho        expect(state, TOK_OPEN_BRACE, &tokenValue, NULL, &startline, status);
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case TOK_OPEN_BRACE:
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "syntax error while reading a resource, expected '{' or ':'");
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1887103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1888fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (resType == RESTYPE_UNKNOWN)
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* No explicit type, so try to work it out.  At this point, we've read the first '{'.
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        We could have any of the following:
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { {         => array (nested)
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { :/}       => array
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string ,  => string array
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string {  => table
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string :/{    => table
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        { string }      => string
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190227f654740f2a26ad62a5c155af9199af9e69b889claireho        token = peekToken(state, 0, NULL, &line, NULL,status);
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(*status))
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (token == TOK_OPEN_BRACE || token == TOK_COLON ||token ==TOK_CLOSE_BRACE )
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1911fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            resType = RESTYPE_ARRAY;
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if (token == TOK_STRING)
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
191527f654740f2a26ad62a5c155af9199af9e69b889claireho            token = peekToken(state, 1, NULL, &line, NULL, status);
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(*status))
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (token)
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1924fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_COMMA:         resType = RESTYPE_ARRAY;  break;
1925fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_OPEN_BRACE:    resType = RESTYPE_TABLE;  break;
1926fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_CLOSE_BRACE:   resType = RESTYPE_STRING; break;
1927fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case TOK_COLON:         resType = RESTYPE_TABLE;  break;
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            default:
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *status = U_INVALID_FORMAT_ERROR;
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                error(line, "Unexpected token after string, expected ',', '{' or '}'");
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return NULL;
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "Unexpected token after '{'");
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* printf("Type guessed as %s\n", resourceNames[resType]); */
1942fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else if(resType == RESTYPE_TABLE_NO_FALLBACK) {
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INVALID_FORMAT_ERROR;
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "error: %s resource type not valid except on top bundle level", gResourceTypes[resType].nameChars);
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1948103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We should now know what we need to parse next, so call the appropriate parser
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    function and return. */
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    parseFunction = gResourceTypes[resType].parseFunction;
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (parseFunction != NULL) {
195327f654740f2a26ad62a5c155af9199af9e69b889claireho        return parseFunction(state, tag, startline, comment, status);
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status = U_INTERNAL_PROGRAM_ERROR;
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        error(startline, "internal error: %s resource type found and not handled", gResourceTypes[resType].nameChars);
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* parse the top-level resource */
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SRBRoot *
1965fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusparse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *filename,
196659d709d503bab6e2b61931737e662dd293b40578ccornelius      UBool makeBinaryCollation, UBool omitCollationRules, UErrorCode *status)
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    *tokenValue;
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    struct UString    comment;
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t           line;
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum EResourceType bundleType;
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    enum ETokenType    token;
197327f654740f2a26ad62a5c155af9199af9e69b889claireho    ParseState state;
197427f654740f2a26ad62a5c155af9199af9e69b889claireho    uint32_t i;
1975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1976103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
197727f654740f2a26ad62a5c155af9199af9e69b889claireho    for (i = 0; i < MAX_LOOKAHEAD + 1; i++)
197827f654740f2a26ad62a5c155af9199af9e69b889claireho    {
197927f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_init(&state.lookahead[i].value);
198027f654740f2a26ad62a5c155af9199af9e69b889claireho        ustr_init(&state.lookahead[i].comment);
198127f654740f2a26ad62a5c155af9199af9e69b889claireho    }
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198327f654740f2a26ad62a5c155af9199af9e69b889claireho    initLookahead(&state, buf, status);
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198527f654740f2a26ad62a5c155af9199af9e69b889claireho    state.inputdir       = inputDir;
198627f654740f2a26ad62a5c155af9199af9e69b889claireho    state.inputdirLength = (state.inputdir != NULL) ? (uint32_t)uprv_strlen(state.inputdir) : 0;
198727f654740f2a26ad62a5c155af9199af9e69b889claireho    state.outputdir       = outputDir;
198827f654740f2a26ad62a5c155af9199af9e69b889claireho    state.outputdirLength = (state.outputdir != NULL) ? (uint32_t)uprv_strlen(state.outputdir) : 0;
1989fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    state.filename = filename;
1990103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    state.makeBinaryCollation = makeBinaryCollation;
199159d709d503bab6e2b61931737e662dd293b40578ccornelius    state.omitCollationRules = omitCollationRules;
1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ustr_init(&comment);
199427f654740f2a26ad62a5c155af9199af9e69b889claireho    expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status);
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1996c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    state.bundle = new SRBRoot(&comment, FALSE, *status);
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
199827f654740f2a26ad62a5c155af9199af9e69b889claireho    if (state.bundle == NULL || U_FAILURE(*status))
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2004c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    state.bundle->setLocale(tokenValue->fChars, *status);
200527f654740f2a26ad62a5c155af9199af9e69b889claireho
2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* The following code is to make Empty bundle work no matter with :table specifer or not */
200727f654740f2a26ad62a5c155af9199af9e69b889claireho    token = getToken(&state, NULL, NULL, &line, status);
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(token==TOK_COLON) {
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *status=U_ZERO_ERROR;
201027f654740f2a26ad62a5c155af9199af9e69b889claireho        bundleType=parseResourceType(&state, status);
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isTable(bundleType))
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
201427f654740f2a26ad62a5c155af9199af9e69b889claireho            expect(&state, TOK_OPEN_BRACE, NULL, NULL, &line, status);
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_PARSE_ERROR;
2019103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius             error(line, "parse error. Stopped parsing with %s", u_errorName(*status));
2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* not a colon */
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(token==TOK_OPEN_BRACE)
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_ZERO_ERROR;
2028fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            bundleType=RESTYPE_TABLE;
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* neither colon nor open brace */
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status=U_PARSE_ERROR;
2034fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            bundleType=RESTYPE_UNKNOWN;
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            error(line, "parse error, did not find open-brace '{' or colon ':', stopped with %s", u_errorName(*status));
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*status))
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2041c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete state.bundle;
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2045fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if(bundleType==RESTYPE_TABLE_NO_FALLBACK) {
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Parse a top-level table with the table(nofallback) declaration.
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * This is the same as a regular table, but also sets the
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
2051c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        state.bundle->fNoFallback=TRUE;
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* top-level tables need not handle special table names like "collations" */
2054c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    assert(!state.bundle->fIsPoolBundle);
2055c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    assert(state.bundle->fRoot->fType == URES_TABLE);
2056c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    TableResource *rootTable = static_cast<TableResource *>(state.bundle->fRoot);
2057c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    realParseTable(&state, rootTable, NULL, line, status);
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dependencyArray!=NULL){
2059c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        rootTable->add(dependencyArray, 0, *status);
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dependencyArray = NULL;
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2062103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius   if (U_FAILURE(*status))
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2064c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete state.bundle;
2065c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        res_close(dependencyArray);
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
206927f654740f2a26ad62a5c155af9199af9e69b889claireho    if (getToken(&state, NULL, NULL, &line, status) != TOK_EOF)
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        warning(line, "extraneous text after resource bundle (perhaps unmatched braces)");
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isStrict()){
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_INVALID_FORMAT_ERROR;
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207827f654740f2a26ad62a5c155af9199af9e69b889claireho    cleanupLookahead(&state);
2079c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    ustr_deinit(&comment);
208027f654740f2a26ad62a5c155af9199af9e69b889claireho    return state.bundle;
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2082